diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml new file mode 100644 index 000000000..1ef83c66f --- /dev/null +++ b/.github/workflows/docs.yml @@ -0,0 +1,55 @@ +# Based on https://vitepress.dev/guide/deploy#github-pages +name: Deploy VitePress site to GitHub Pages + +on: + push: + branches: [master] + workflow_dispatch: + +# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages +permissions: + contents: read + pages: write + id-token: write + +# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued. +# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete. +concurrency: + group: pages + cancel-in-progress: false + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Setup Node + uses: actions/setup-node@v4 + with: + node-version: 20 + cache: npm + - name: Setup Pages + uses: actions/configure-pages@v4 + - name: Install dependencies + run: npm ci + - name: Build with VitePress + run: npm run docs:build + - name: Upload artifact + uses: actions/upload-pages-artifact@v3 + with: + path: docs/.vitepress/dist + + deploy: + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + needs: build + runs-on: ubuntu-latest + name: Deploy + steps: + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 diff --git a/.gitignore b/.gitignore index 8912d0f0f..8adfdd765 100644 --- a/.gitignore +++ b/.gitignore @@ -93,3 +93,8 @@ features.toml .vscode/settings.json + +# Documentation +docs/.vitepress/dist +docs/.vitepress/cache +node_modules diff --git a/docs/.vitepress/config.mts b/docs/.vitepress/config.mts new file mode 100644 index 000000000..fe7139230 --- /dev/null +++ b/docs/.vitepress/config.mts @@ -0,0 +1,44 @@ +import { defineConfig } from "vitepress"; + +// https://vitepress.dev/reference/site-config +export default defineConfig({ + title: "Pumpkin", + description: + "Empowering everyone to host fast and efficient Minecraft servers", + lang: "en-US", + base: "/Pumpkin/", + themeConfig: { + // https://vitepress.dev/reference/default-theme-config + sidebar: [ + { + text: "About", + items: [ + { text: "Introduction", link: "/about/introduction" }, + { text: "Quick Start", link: "/about/quick-start" }, + { + text: "Contributing", + link: "https://github.com/Snowiiii/Pumpkin/blob/master/CONTRIBUTING.md", + }, + ], + }, + { + text: "Plugins", + items: [ + { text: "About Plugins", link: "/plugins/about" }, + { + text: "Getting Started in Rust", + link: "/plugins/getting-started-rs", + }, + ], + }, + ], + + socialLinks: [ + { icon: "github", link: "https://github.com/Snowiiii/Pumpkin" }, + { icon: "discord", link: "https://discord.gg/RNm224ZsDq" }, + ], + + logo: "/assets/icon.png", + }, + head: [["link", { rel: "icon", href: "/assets/favicon.ico" }]], +}); diff --git a/docs/.vitepress/theme/index.ts b/docs/.vitepress/theme/index.ts new file mode 100644 index 000000000..def4cfc87 --- /dev/null +++ b/docs/.vitepress/theme/index.ts @@ -0,0 +1,17 @@ +// https://vitepress.dev/guide/custom-theme +import { h } from 'vue' +import type { Theme } from 'vitepress' +import DefaultTheme from 'vitepress/theme' +import './style.css' + +export default { + extends: DefaultTheme, + Layout: () => { + return h(DefaultTheme.Layout, null, { + // https://vitepress.dev/guide/extending-default-theme#layout-slots + }) + }, + enhanceApp({ app, router, siteData }) { + // ... + } +} satisfies Theme diff --git a/docs/.vitepress/theme/style.css b/docs/.vitepress/theme/style.css new file mode 100644 index 000000000..d63aee82d --- /dev/null +++ b/docs/.vitepress/theme/style.css @@ -0,0 +1,139 @@ +/** + * Customize default theme styling by overriding CSS variables: + * https://github.com/vuejs/vitepress/blob/main/src/client/theme-default/styles/vars.css + */ + +/** + * Colors + * + * Each colors have exact same color scale system with 3 levels of solid + * colors with different brightness, and 1 soft color. + * + * - `XXX-1`: The most solid color used mainly for colored text. It must + * satisfy the contrast ratio against when used on top of `XXX-soft`. + * + * - `XXX-2`: The color used mainly for hover state of the button. + * + * - `XXX-3`: The color for solid background, such as bg color of the button. + * It must satisfy the contrast ratio with pure white (#ffffff) text on + * top of it. + * + * - `XXX-soft`: The color used for subtle background such as custom container + * or badges. It must satisfy the contrast ratio when putting `XXX-1` colors + * on top of it. + * + * The soft color must be semi transparent alpha channel. This is crucial + * because it allows adding multiple "soft" colors on top of each other + * to create a accent, such as when having inline code block inside + * custom containers. + * + * - `default`: The color used purely for subtle indication without any + * special meanings attched to it such as bg color for menu hover state. + * + * - `brand`: Used for primary brand colors, such as link text, button with + * brand theme, etc. + * + * - `tip`: Used to indicate useful information. The default theme uses the + * brand color for this by default. + * + * - `warning`: Used to indicate warning to the users. Used in custom + * container, badges, etc. + * + * - `danger`: Used to show error, or dangerous message to the users. Used + * in custom container, badges, etc. + * -------------------------------------------------------------------------- */ + + :root { + --vp-c-default-1: var(--vp-c-gray-1); + --vp-c-default-2: var(--vp-c-gray-2); + --vp-c-default-3: var(--vp-c-gray-3); + --vp-c-default-soft: var(--vp-c-gray-soft); + + --vp-c-brand-1: var(--vp-c-indigo-1); + --vp-c-brand-2: var(--vp-c-indigo-2); + --vp-c-brand-3: var(--vp-c-indigo-3); + --vp-c-brand-soft: var(--vp-c-indigo-soft); + + --vp-c-tip-1: var(--vp-c-brand-1); + --vp-c-tip-2: var(--vp-c-brand-2); + --vp-c-tip-3: var(--vp-c-brand-3); + --vp-c-tip-soft: var(--vp-c-brand-soft); + + --vp-c-warning-1: var(--vp-c-yellow-1); + --vp-c-warning-2: var(--vp-c-yellow-2); + --vp-c-warning-3: var(--vp-c-yellow-3); + --vp-c-warning-soft: var(--vp-c-yellow-soft); + + --vp-c-danger-1: var(--vp-c-red-1); + --vp-c-danger-2: var(--vp-c-red-2); + --vp-c-danger-3: var(--vp-c-red-3); + --vp-c-danger-soft: var(--vp-c-red-soft); +} + +/** + * Component: Button + * -------------------------------------------------------------------------- */ + +:root { + --vp-button-brand-border: transparent; + --vp-button-brand-text: var(--vp-c-white); + --vp-button-brand-bg: var(--vp-c-brand-3); + --vp-button-brand-hover-border: transparent; + --vp-button-brand-hover-text: var(--vp-c-white); + --vp-button-brand-hover-bg: var(--vp-c-brand-2); + --vp-button-brand-active-border: transparent; + --vp-button-brand-active-text: var(--vp-c-white); + --vp-button-brand-active-bg: var(--vp-c-brand-1); +} + +/** + * Component: Home + * -------------------------------------------------------------------------- */ + +:root { + --vp-home-hero-name-color: transparent; + --vp-home-hero-name-background: -webkit-linear-gradient( + 120deg, + #bd34fe 30%, + #41d1ff + ); + + --vp-home-hero-image-background-image: linear-gradient( + -45deg, + #bd34fe 50%, + #47caff 50% + ); + --vp-home-hero-image-filter: blur(44px); +} + +@media (min-width: 640px) { + :root { + --vp-home-hero-image-filter: blur(56px); + } +} + +@media (min-width: 960px) { + :root { + --vp-home-hero-image-filter: blur(68px); + } +} + +/** + * Component: Custom Block + * -------------------------------------------------------------------------- */ + +:root { + --vp-custom-block-tip-border: transparent; + --vp-custom-block-tip-text: var(--vp-c-text-1); + --vp-custom-block-tip-bg: var(--vp-c-brand-soft); + --vp-custom-block-tip-code-bg: var(--vp-c-brand-soft); +} + +/** + * Component: Algolia + * -------------------------------------------------------------------------- */ + +.DocSearch { + --docsearch-primary-color: var(--vp-c-brand-1) !important; +} + diff --git a/docs/about/introduction.md b/docs/about/introduction.md new file mode 100644 index 000000000..ffb6f8b28 --- /dev/null +++ b/docs/about/introduction.md @@ -0,0 +1,22 @@ +# Pumpkin + +Pumpkin is a Minecraft server built entirely in **Rust**, offering a fast, efficient, +and customizable experience. It prioritizes performance and player enjoyment while adhering to the core mechanics of the game. + +![image](https://github.com/user-attachments/assets/7e2e865e-b150-4675-a2d5-b52f9900378e) + +## What Pumpkin wants to achieve + +- **Performance**: Leveraging multi-threading for maximum speed and efficiency. +- **Compatibility**: Supports the latest Minecraft server version and adheres to vanilla game mechanics. +- **Security**: Prioritizes security by preventing known exploits. +- **Flexibility**: Highly configurable with the ability to disable unnecessary features. +- **Extensibility**: Provides a foundation for plugin development. + +## What Pumpkin will not + +- Provide compatibility with Vanilla or Bukkit servers (including configs and plugins). +- Function as a framework for building a server from scratch. + +> [!IMPORTANT] +> Pumpkin is currently under heavy development. Check out our [Github Project](https://github.com/users/Snowiiii/projects/12/views/3) to see current progress diff --git a/docs/about/quick-start.md b/docs/about/quick-start.md new file mode 100644 index 000000000..851502b7b --- /dev/null +++ b/docs/about/quick-start.md @@ -0,0 +1,41 @@ +# Quick Start + +There are currently no release builds, because there was no release :D. + +To get Pumpkin running you first have to clone it: + +```shell +git clone https://github.com/Snowiiii/Pumpkin.git +cd Pumpkin +``` + +You also may have to [install rust](https://www.rust-lang.org/tools/install) when you don't already have. + +You can place a vanilla world into the Pumpkin/ directory when you want. Just name the World to `world` + +Then run: + +> [!NOTE] +> This can take a while. Because we enabled heavy optimizations for release builds +> +> To apply further optimizations specfic to your CPU and use your CPU features. You should set the target-cpu=native +> Rust flag. + +```shell +cargo run --release +``` + +## Docker + +Experimental Docker support is available. +The image is currently not published anywhere, but you can use the following command to build it: + +```shell +docker build . -t pumpkin +``` + +To run it use the following command: + +```shell +docker run --rm -v "./world:/pumpkin/world" pumpkin +``` diff --git a/docs/assets/favicon.ico b/docs/assets/favicon.ico new file mode 100644 index 000000000..a2f932b03 Binary files /dev/null and b/docs/assets/favicon.ico differ diff --git a/docs/assets/icon.png b/docs/assets/icon.png new file mode 100644 index 000000000..a09608130 Binary files /dev/null and b/docs/assets/icon.png differ diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 000000000..8a34490e0 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,27 @@ +--- +# https://vitepress.dev/reference/default-theme-home-page +layout: home + +hero: + name: 'Pumpkin' + text: 'Minecraft Server' + tagline: Empowering everyone to host fast and efficient Minecraft servers + actions: + - theme: brand + text: Quick Start + link: /about/quick-start + - theme: alt + text: Documentation + link: /about/introduction + - theme: alt + text: For developers + link: /plugins/about + +features: + - title: Written in Rust + details: Pumpkin is written 100% in Rust, ensuring memory safety and unmatched performance. + - title: Feature complete + details: With all vanilla features supported, you will have no issues. + - title: Extensible + details: Using Extism you can extend Pumpkin to your needs. Play your way! +--- diff --git a/docs/plugins/about.md b/docs/plugins/about.md new file mode 100644 index 000000000..110fe955a --- /dev/null +++ b/docs/plugins/about.md @@ -0,0 +1,15 @@ +# Plugins + +Pumpkin uses [Extism](https://extism.org/) for loading plugins. +This means that you can write your plugins in any language that can compile to Extism WASM. +These languages include: + +- Rust +- JavaScript / TypeScript +- Golang +- C# +- F# +- C +- Haskell +- Zig +- AssemblyScript diff --git a/docs/plugins/getting-started-rs.md b/docs/plugins/getting-started-rs.md new file mode 100644 index 000000000..5bed83b39 --- /dev/null +++ b/docs/plugins/getting-started-rs.md @@ -0,0 +1,4 @@ +# Getting Started in Rust + +Rust in one of the supported plugin languages. +This page has not been written yet. diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 000000000..2325a32a8 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,1062 @@ +{ + "name": "Pumpkin", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "devDependencies": { + "vitepress": "^1.3.4", + "vue": "^3.4.38" + } + }, + "node_modules/@algolia/autocomplete-core": { + "version": "1.9.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/autocomplete-plugin-algolia-insights": "1.9.3", + "@algolia/autocomplete-shared": "1.9.3" + } + }, + "node_modules/@algolia/autocomplete-plugin-algolia-insights": { + "version": "1.9.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/autocomplete-shared": "1.9.3" + }, + "peerDependencies": { + "search-insights": ">= 1 < 3" + } + }, + "node_modules/@algolia/autocomplete-preset-algolia": { + "version": "1.9.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/autocomplete-shared": "1.9.3" + }, + "peerDependencies": { + "@algolia/client-search": ">= 4.9.1 < 6", + "algoliasearch": ">= 4.9.1 < 6" + } + }, + "node_modules/@algolia/autocomplete-shared": { + "version": "1.9.3", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@algolia/client-search": ">= 4.9.1 < 6", + "algoliasearch": ">= 4.9.1 < 6" + } + }, + "node_modules/@algolia/cache-browser-local-storage": { + "version": "4.24.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/cache-common": "4.24.0" + } + }, + "node_modules/@algolia/cache-common": { + "version": "4.24.0", + "dev": true, + "license": "MIT" + }, + "node_modules/@algolia/cache-in-memory": { + "version": "4.24.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/cache-common": "4.24.0" + } + }, + "node_modules/@algolia/client-account": { + "version": "4.24.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "4.24.0", + "@algolia/client-search": "4.24.0", + "@algolia/transporter": "4.24.0" + } + }, + "node_modules/@algolia/client-analytics": { + "version": "4.24.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "4.24.0", + "@algolia/client-search": "4.24.0", + "@algolia/requester-common": "4.24.0", + "@algolia/transporter": "4.24.0" + } + }, + "node_modules/@algolia/client-common": { + "version": "4.24.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/requester-common": "4.24.0", + "@algolia/transporter": "4.24.0" + } + }, + "node_modules/@algolia/client-personalization": { + "version": "4.24.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "4.24.0", + "@algolia/requester-common": "4.24.0", + "@algolia/transporter": "4.24.0" + } + }, + "node_modules/@algolia/client-search": { + "version": "4.24.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "4.24.0", + "@algolia/requester-common": "4.24.0", + "@algolia/transporter": "4.24.0" + } + }, + "node_modules/@algolia/logger-common": { + "version": "4.24.0", + "dev": true, + "license": "MIT" + }, + "node_modules/@algolia/logger-console": { + "version": "4.24.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/logger-common": "4.24.0" + } + }, + "node_modules/@algolia/recommend": { + "version": "4.24.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/cache-browser-local-storage": "4.24.0", + "@algolia/cache-common": "4.24.0", + "@algolia/cache-in-memory": "4.24.0", + "@algolia/client-common": "4.24.0", + "@algolia/client-search": "4.24.0", + "@algolia/logger-common": "4.24.0", + "@algolia/logger-console": "4.24.0", + "@algolia/requester-browser-xhr": "4.24.0", + "@algolia/requester-common": "4.24.0", + "@algolia/requester-node-http": "4.24.0", + "@algolia/transporter": "4.24.0" + } + }, + "node_modules/@algolia/requester-browser-xhr": { + "version": "4.24.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/requester-common": "4.24.0" + } + }, + "node_modules/@algolia/requester-common": { + "version": "4.24.0", + "dev": true, + "license": "MIT" + }, + "node_modules/@algolia/requester-node-http": { + "version": "4.24.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/requester-common": "4.24.0" + } + }, + "node_modules/@algolia/transporter": { + "version": "4.24.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/cache-common": "4.24.0", + "@algolia/logger-common": "4.24.0", + "@algolia/requester-common": "4.24.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.24.8", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.24.7", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.25.6", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.25.6" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/types": { + "version": "7.25.6", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.24.8", + "@babel/helper-validator-identifier": "^7.24.7", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@docsearch/css": { + "version": "3.6.1", + "dev": true, + "license": "MIT" + }, + "node_modules/@docsearch/js": { + "version": "3.6.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@docsearch/react": "3.6.1", + "preact": "^10.0.0" + } + }, + "node_modules/@docsearch/react": { + "version": "3.6.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/autocomplete-core": "1.9.3", + "@algolia/autocomplete-preset-algolia": "1.9.3", + "@docsearch/css": "3.6.1", + "algoliasearch": "^4.19.1" + }, + "peerDependencies": { + "@types/react": ">= 16.8.0 < 19.0.0", + "react": ">= 16.8.0 < 19.0.0", + "react-dom": ">= 16.8.0 < 19.0.0", + "search-insights": ">= 1 < 3" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "react": { + "optional": true + }, + "react-dom": { + "optional": true + }, + "search-insights": { + "optional": true + } + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.21.5", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "dev": true, + "license": "MIT" + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.21.2", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.21.2", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@shikijs/core": { + "version": "1.16.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/vscode-textmate": "^9.2.0", + "@types/hast": "^3.0.4" + } + }, + "node_modules/@shikijs/transformers": { + "version": "1.16.1", + "dev": true, + "license": "MIT", + "dependencies": { + "shiki": "1.16.1" + } + }, + "node_modules/@shikijs/vscode-textmate": { + "version": "9.2.0", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/estree": { + "version": "1.0.5", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/hast": { + "version": "3.0.4", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/linkify-it": { + "version": "5.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/markdown-it": { + "version": "14.1.2", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/linkify-it": "^5", + "@types/mdurl": "^2" + } + }, + "node_modules/@types/mdurl": { + "version": "2.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/unist": { + "version": "3.0.3", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/web-bluetooth": { + "version": "0.0.20", + "dev": true, + "license": "MIT" + }, + "node_modules/@vitejs/plugin-vue": { + "version": "5.1.3", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "peerDependencies": { + "vite": "^5.0.0", + "vue": "^3.2.25" + } + }, + "node_modules/@vue/compiler-core": { + "version": "3.4.38", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.24.7", + "@vue/shared": "3.4.38", + "entities": "^4.5.0", + "estree-walker": "^2.0.2", + "source-map-js": "^1.2.0" + } + }, + "node_modules/@vue/compiler-dom": { + "version": "3.4.38", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/compiler-core": "3.4.38", + "@vue/shared": "3.4.38" + } + }, + "node_modules/@vue/compiler-sfc": { + "version": "3.4.38", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.24.7", + "@vue/compiler-core": "3.4.38", + "@vue/compiler-dom": "3.4.38", + "@vue/compiler-ssr": "3.4.38", + "@vue/shared": "3.4.38", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.10", + "postcss": "^8.4.40", + "source-map-js": "^1.2.0" + } + }, + "node_modules/@vue/compiler-ssr": { + "version": "3.4.38", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.4.38", + "@vue/shared": "3.4.38" + } + }, + "node_modules/@vue/devtools-api": { + "version": "7.3.9", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/devtools-kit": "^7.3.9" + } + }, + "node_modules/@vue/devtools-kit": { + "version": "7.3.9", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/devtools-shared": "^7.3.9", + "birpc": "^0.2.17", + "hookable": "^5.5.3", + "mitt": "^3.0.1", + "perfect-debounce": "^1.0.0", + "speakingurl": "^14.0.1", + "superjson": "^2.2.1" + } + }, + "node_modules/@vue/devtools-shared": { + "version": "7.3.9", + "dev": true, + "license": "MIT", + "dependencies": { + "rfdc": "^1.4.1" + } + }, + "node_modules/@vue/reactivity": { + "version": "3.4.38", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/shared": "3.4.38" + } + }, + "node_modules/@vue/runtime-core": { + "version": "3.4.38", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.4.38", + "@vue/shared": "3.4.38" + } + }, + "node_modules/@vue/runtime-dom": { + "version": "3.4.38", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.4.38", + "@vue/runtime-core": "3.4.38", + "@vue/shared": "3.4.38", + "csstype": "^3.1.3" + } + }, + "node_modules/@vue/server-renderer": { + "version": "3.4.38", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/compiler-ssr": "3.4.38", + "@vue/shared": "3.4.38" + }, + "peerDependencies": { + "vue": "3.4.38" + } + }, + "node_modules/@vue/shared": { + "version": "3.4.38", + "dev": true, + "license": "MIT" + }, + "node_modules/@vueuse/core": { + "version": "11.0.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/web-bluetooth": "^0.0.20", + "@vueuse/metadata": "11.0.3", + "@vueuse/shared": "11.0.3", + "vue-demi": ">=0.14.10" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@vueuse/integrations": { + "version": "11.0.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@vueuse/core": "11.0.3", + "@vueuse/shared": "11.0.3", + "vue-demi": ">=0.14.10" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "async-validator": "^4", + "axios": "^1", + "change-case": "^5", + "drauu": "^0.4", + "focus-trap": "^7", + "fuse.js": "^7", + "idb-keyval": "^6", + "jwt-decode": "^4", + "nprogress": "^0.2", + "qrcode": "^1.5", + "sortablejs": "^1", + "universal-cookie": "^7" + }, + "peerDependenciesMeta": { + "async-validator": { + "optional": true + }, + "axios": { + "optional": true + }, + "change-case": { + "optional": true + }, + "drauu": { + "optional": true + }, + "focus-trap": { + "optional": true + }, + "fuse.js": { + "optional": true + }, + "idb-keyval": { + "optional": true + }, + "jwt-decode": { + "optional": true + }, + "nprogress": { + "optional": true + }, + "qrcode": { + "optional": true + }, + "sortablejs": { + "optional": true + }, + "universal-cookie": { + "optional": true + } + } + }, + "node_modules/@vueuse/metadata": { + "version": "11.0.3", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@vueuse/shared": { + "version": "11.0.3", + "dev": true, + "license": "MIT", + "dependencies": { + "vue-demi": ">=0.14.10" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/algoliasearch": { + "version": "4.24.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/cache-browser-local-storage": "4.24.0", + "@algolia/cache-common": "4.24.0", + "@algolia/cache-in-memory": "4.24.0", + "@algolia/client-account": "4.24.0", + "@algolia/client-analytics": "4.24.0", + "@algolia/client-common": "4.24.0", + "@algolia/client-personalization": "4.24.0", + "@algolia/client-search": "4.24.0", + "@algolia/logger-common": "4.24.0", + "@algolia/logger-console": "4.24.0", + "@algolia/recommend": "4.24.0", + "@algolia/requester-browser-xhr": "4.24.0", + "@algolia/requester-common": "4.24.0", + "@algolia/requester-node-http": "4.24.0", + "@algolia/transporter": "4.24.0" + } + }, + "node_modules/birpc": { + "version": "0.2.17", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/copy-anything": { + "version": "3.0.5", + "dev": true, + "license": "MIT", + "dependencies": { + "is-what": "^4.1.8" + }, + "engines": { + "node": ">=12.13" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, + "node_modules/csstype": { + "version": "3.1.3", + "dev": true, + "license": "MIT" + }, + "node_modules/entities": { + "version": "4.5.0", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/esbuild": { + "version": "0.21.5", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" + } + }, + "node_modules/estree-walker": { + "version": "2.0.2", + "dev": true, + "license": "MIT" + }, + "node_modules/focus-trap": { + "version": "7.5.4", + "dev": true, + "license": "MIT", + "dependencies": { + "tabbable": "^6.2.0" + } + }, + "node_modules/hookable": { + "version": "5.5.3", + "dev": true, + "license": "MIT" + }, + "node_modules/is-what": { + "version": "4.1.16", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.13" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, + "node_modules/magic-string": { + "version": "0.30.11", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0" + } + }, + "node_modules/mark.js": { + "version": "8.11.1", + "dev": true, + "license": "MIT" + }, + "node_modules/minisearch": { + "version": "7.1.0", + "dev": true, + "license": "MIT" + }, + "node_modules/mitt": { + "version": "3.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.7", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/perfect-debounce": { + "version": "1.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.0.1", + "dev": true, + "license": "ISC" + }, + "node_modules/postcss": { + "version": "8.4.44", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.7", + "picocolors": "^1.0.1", + "source-map-js": "^1.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/preact": { + "version": "10.23.2", + "dev": true, + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/preact" + } + }, + "node_modules/rfdc": { + "version": "1.4.1", + "dev": true, + "license": "MIT" + }, + "node_modules/rollup": { + "version": "4.21.2", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.5" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.21.2", + "@rollup/rollup-android-arm64": "4.21.2", + "@rollup/rollup-darwin-arm64": "4.21.2", + "@rollup/rollup-darwin-x64": "4.21.2", + "@rollup/rollup-linux-arm-gnueabihf": "4.21.2", + "@rollup/rollup-linux-arm-musleabihf": "4.21.2", + "@rollup/rollup-linux-arm64-gnu": "4.21.2", + "@rollup/rollup-linux-arm64-musl": "4.21.2", + "@rollup/rollup-linux-powerpc64le-gnu": "4.21.2", + "@rollup/rollup-linux-riscv64-gnu": "4.21.2", + "@rollup/rollup-linux-s390x-gnu": "4.21.2", + "@rollup/rollup-linux-x64-gnu": "4.21.2", + "@rollup/rollup-linux-x64-musl": "4.21.2", + "@rollup/rollup-win32-arm64-msvc": "4.21.2", + "@rollup/rollup-win32-ia32-msvc": "4.21.2", + "@rollup/rollup-win32-x64-msvc": "4.21.2", + "fsevents": "~2.3.2" + } + }, + "node_modules/search-insights": { + "version": "2.17.0", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/shiki": { + "version": "1.16.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/core": "1.16.1", + "@shikijs/vscode-textmate": "^9.2.0", + "@types/hast": "^3.0.4" + } + }, + "node_modules/source-map-js": { + "version": "1.2.0", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/speakingurl": { + "version": "14.0.1", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/superjson": { + "version": "2.2.1", + "dev": true, + "license": "MIT", + "dependencies": { + "copy-anything": "^3.0.2" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/tabbable": { + "version": "6.2.0", + "dev": true, + "license": "MIT" + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/vite": { + "version": "5.4.2", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.21.3", + "postcss": "^8.4.41", + "rollup": "^4.20.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/vitepress": { + "version": "1.3.4", + "dev": true, + "license": "MIT", + "dependencies": { + "@docsearch/css": "^3.6.1", + "@docsearch/js": "^3.6.1", + "@shikijs/core": "^1.13.0", + "@shikijs/transformers": "^1.13.0", + "@types/markdown-it": "^14.1.2", + "@vitejs/plugin-vue": "^5.1.2", + "@vue/devtools-api": "^7.3.8", + "@vue/shared": "^3.4.38", + "@vueuse/core": "^11.0.0", + "@vueuse/integrations": "^11.0.0", + "focus-trap": "^7.5.4", + "mark.js": "8.11.1", + "minisearch": "^7.1.0", + "shiki": "^1.13.0", + "vite": "^5.4.1", + "vue": "^3.4.38" + }, + "bin": { + "vitepress": "bin/vitepress.js" + }, + "peerDependencies": { + "markdown-it-mathjax3": "^4", + "postcss": "^8" + }, + "peerDependenciesMeta": { + "markdown-it-mathjax3": { + "optional": true + }, + "postcss": { + "optional": true + } + } + }, + "node_modules/vue": { + "version": "3.4.38", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.4.38", + "@vue/compiler-sfc": "3.4.38", + "@vue/runtime-dom": "3.4.38", + "@vue/server-renderer": "3.4.38", + "@vue/shared": "3.4.38" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/vue-demi": { + "version": "0.14.10", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 000000000..29967d6b8 --- /dev/null +++ b/package.json @@ -0,0 +1,11 @@ +{ + "scripts": { + "docs:dev": "vitepress dev docs", + "docs:build": "vitepress build docs", + "docs:preview": "vitepress preview docs" + }, + "devDependencies": { + "vitepress": "^1.3.4", + "vue": "^3.4.38" + } +} \ No newline at end of file diff --git a/pumpkin-core/src/math/vector3.rs b/pumpkin-core/src/math/vector3.rs index 67bc038bc..65da454e6 100644 --- a/pumpkin-core/src/math/vector3.rs +++ b/pumpkin-core/src/math/vector3.rs @@ -98,6 +98,12 @@ impl From<(T, T, T)> for Vector3 { } } +impl From> for (T, T, T) { + fn from(vector: Vector3) -> Self { + (vector.x, vector.y, vector.z) + } +} + pub trait Math: Mul + Neg diff --git a/pumpkin/src/client/mod.rs b/pumpkin/src/client/mod.rs index 131e12df9..c100dae3f 100644 --- a/pumpkin/src/client/mod.rs +++ b/pumpkin/src/client/mod.rs @@ -1,7 +1,6 @@ use std::{ io::{self, Write}, net::SocketAddr, - sync::Arc, }; use crate::{ @@ -71,7 +70,7 @@ pub struct Client { pub connection_state: ConnectionState, pub encryption: bool, pub closed: bool, - pub token: Arc, + pub token: Token, pub connection: TcpStream, pub address: SocketAddr, enc: PacketEncoder, @@ -82,7 +81,7 @@ pub struct Client { } impl Client { - pub fn new(token: Arc, connection: TcpStream, address: SocketAddr) -> Self { + pub fn new(token: Token, connection: TcpStream, address: SocketAddr) -> Self { Self { protocol_version: 0, gameprofile: None, diff --git a/pumpkin/src/client/player_packet.rs b/pumpkin/src/client/player_packet.rs index 76df0811d..ef5604808 100644 --- a/pumpkin/src/client/player_packet.rs +++ b/pumpkin/src/client/player_packet.rs @@ -76,9 +76,7 @@ impl Player { return; } let entity = &mut self.entity; - self.lastx = entity.pos.x; - self.lasty = entity.pos.y; - self.lastz = entity.pos.z; + self.last_position = entity.pos; entity.set_pos( Self::clamp_horizontal(position.x), Self::clamp_vertical(position.feet_y), @@ -89,13 +87,12 @@ impl Player { // send new position to all other players let on_ground = self.on_ground; let entity_id = entity.entity_id; - let (x, lastx) = (entity.pos.x, self.lastx); - let (y, lasty) = (entity.pos.y, self.lasty); - let (z, lastz) = (entity.pos.z, self.lastz); + let (x, y, z) = entity.pos.into(); + let (lastx, lasty, lastz) = self.last_position.into(); let world = self.world.clone(); let world = world.lock().await; world.broadcast_packet( - &[&self.client.token], + &[self.client.token], &CUpdateEntityPos::new( entity_id.into(), (x * 4096.0 - lastx * 4096.0) as i16, @@ -125,9 +122,7 @@ impl Player { } let entity = &mut self.entity; - self.lastx = entity.pos.x; - self.lasty = entity.pos.y; - self.lastz = entity.pos.z; + self.last_position = entity.pos; entity.set_pos( Self::clamp_horizontal(position_rotation.x), Self::clamp_vertical(position_rotation.feet_y), @@ -139,9 +134,8 @@ impl Player { // send new position to all other players let on_ground = self.on_ground; let entity_id = entity.entity_id; - let (x, lastx) = (entity.pos.x, self.lastx); - let (y, lasty) = (entity.pos.y, self.lasty); - let (z, lastz) = (entity.pos.z, self.lastz); + let (x, y, z) = entity.pos.into(); + let (lastx, lasty, lastz) = self.last_position.into(); let yaw = modulus(entity.yaw * 256.0 / 360.0, 256.0); let pitch = modulus(entity.pitch * 256.0 / 360.0, 256.0); // let head_yaw = (entity.head_yaw * 256.0 / 360.0).floor(); @@ -149,7 +143,7 @@ impl Player { let world = world.lock().await; world.broadcast_packet( - &[&self.client.token], + &[self.client.token], &CUpdateEntityPosRot::new( entity_id.into(), (x * 4096.0 - lastx * 4096.0) as i16, @@ -161,7 +155,7 @@ impl Player { ), ); world.broadcast_packet( - &[&self.client.token], + &[self.client.token], &CHeadRot::new(entity_id.into(), yaw as u8), ); @@ -186,10 +180,10 @@ impl Player { let world = self.world.lock().await; let packet = CUpdateEntityRot::new(entity_id.into(), yaw as u8, pitch as u8, on_ground); // self.client.send_packet(&packet); - world.broadcast_packet(&[&self.client.token], &packet); + world.broadcast_packet(&[self.client.token], &packet); let packet = CHeadRot::new(entity_id.into(), yaw as u8); // self.client.send_packet(&packet); - world.broadcast_packet(&[&self.client.token], &packet); + world.broadcast_packet(&[self.client.token], &packet); } pub fn handle_chat_command(&mut self, server: &mut Server, command: SChatCommand) { @@ -248,7 +242,7 @@ impl Player { let id = self.entity_id(); let world = self.world.lock().await; world.broadcast_packet( - &[&self.client.token], + &[self.client.token], &CEntityAnimation::new(id.into(), animation as u8), ) } @@ -272,7 +266,7 @@ impl Player { let world = self.world.lock().await; world.broadcast_packet( - &[&self.client.token], + &[self.client.token], &CPlayerChatMessage::new( pumpkin_protocol::uuid::UUID(gameprofile.id), 1.into(), @@ -340,7 +334,7 @@ impl Player { let world = world.lock().await; let attacked_player = world.get_by_entityid(self, entity_id.0 as EntityId); if let Some(mut player) = attacked_player { - let token = player.client.token.clone(); + let token = player.client.token; let velo = player.velocity; if config.protect_creative && player.gamemode == GameMode::Creative { return; @@ -371,7 +365,7 @@ impl Player { self.client.send_packet(packet); player.client.send_packet(packet); world.broadcast_packet( - &[&self.client.token, &token], + &[self.client.token, token], &CHurtAnimation::new(&entity_id, 10.0), ) } @@ -411,12 +405,12 @@ impl Player { // TODO: currently this is always dirt replace it let world = self.world.lock().await; world.broadcast_packet( - &[&self.client.token], + &[self.client.token], &CWorldEvent::new(2001, &location, 11, false), ); // AIR world.broadcast_packet( - &[&self.client.token], + &[self.client.token], &CBlockUpdate::new(&location, 0.into()), ); } @@ -439,12 +433,12 @@ impl Player { // TODO: currently this is always dirt replace it let world = self.world.lock().await; world.broadcast_packet( - &[&self.client.token], + &[self.client.token], &CWorldEvent::new(2001, &location, 11, false), ); // AIR world.broadcast_packet( - &[&self.client.token], + &[self.client.token], &CBlockUpdate::new(&location, 0.into()), ); // TODO: Send this every tick @@ -491,11 +485,11 @@ impl Player { if let Ok(block_state_id) = BlockId::new(minecraft_id, None) { let world = self.world.lock().await; world.broadcast_packet( - &[&self.client.token], + &[self.client.token], &CBlockUpdate::new(&location, block_state_id.get_id_mojang_repr().into()), ); world.broadcast_packet( - &[&self.client.token], + &[self.client.token], &CBlockUpdate::new( &WorldPosition(location.0 + face.to_offset()), block_state_id.get_id_mojang_repr().into(), diff --git a/pumpkin/src/entity/player.rs b/pumpkin/src/entity/player.rs index eca9aa6cb..3c7b05ee3 100644 --- a/pumpkin/src/entity/player.rs +++ b/pumpkin/src/entity/player.rs @@ -75,9 +75,7 @@ pub struct Player { /// send `send_abilties_update` when changed pub abilities: PlayerAbilities, - pub lastx: f64, - pub lasty: f64, - pub lastz: f64, + pub last_position: Vector3, // Client side value, Should be not trusted pub on_ground: bool, @@ -140,9 +138,7 @@ impl Player { abilities: PlayerAbilities::default(), gamemode, watched_section: Vector3::new(0, 0, 0), - lastx: 0.0, - lasty: 0.0, - lastz: 0.0, + last_position: Vector3::new(0.0, 0.0, 0.0), } } @@ -238,7 +234,7 @@ impl Player { self.world .lock() .await - .broadcast_packet(&[&self.client.token], &packet); + .broadcast_packet(&[self.client.token], &packet); } pub async fn set_pose(&mut self, pose: EntityPose) { @@ -252,7 +248,7 @@ impl Player { self.world .lock() .await - .broadcast_packet(&[&self.client.token], &packet) + .broadcast_packet(&[self.client.token], &packet) } pub fn teleport(&mut self, x: f64, y: f64, z: f64, yaw: f32, pitch: f32) { @@ -263,9 +259,7 @@ impl Player { } let entity = &mut self.entity; entity.set_pos(x, y, z); - self.lastx = x; - self.lasty = y; - self.lastz = z; + self.last_position = entity.pos; entity.yaw = yaw; entity.pitch = pitch; self.awaiting_teleport = Some((self.teleport_id_count.into(), Vector3::new(x, y, z))); @@ -334,7 +328,7 @@ impl Player { }], )); self.world.lock().await.broadcast_packet( - &[&self.client.token], + &[self.client.token], &CPlayerInfoUpdate::new( 0x04, &[pumpkin_protocol::client::play::Player { diff --git a/pumpkin/src/main.rs b/pumpkin/src/main.rs index 8b9d8ef82..18bc812b0 100644 --- a/pumpkin/src/main.rs +++ b/pumpkin/src/main.rs @@ -81,7 +81,7 @@ fn main() -> io::Result<()> { let rcon = ADVANCED_CONFIG.rcon.clone(); let mut clients: HashMap = HashMap::new(); - let mut players: HashMap, Arc>> = HashMap::new(); + let mut players: HashMap>> = HashMap::new(); let server = Arc::new(tokio::sync::Mutex::new(Server::new())); log::info!("Started Server took {}ms", time.elapsed().as_millis()); @@ -150,32 +150,28 @@ fn main() -> io::Result<()> { token, Interest::READABLE.add(Interest::WRITABLE), )?; - let rc_token = Arc::new(token); - let client = Client::new(Arc::clone(&rc_token), connection, addr); + let client = Client::new(token, connection, addr); clients.insert(token, client); }, token => { // Poll Players - let done = if let Some(player) = players.get_mut(&token) { + if let Some(player) = players.get_mut(&token) { let mut player = player.lock().unwrap(); player.client.poll(event).await; if !player.client.closed { let mut server = server.lock().await; player.process_packets(&mut server).await; } - player.client.closed - } else { - false - }; - - if done { - if let Some(player) = players.remove(&token) { - let mut player = player.lock().unwrap(); - player.remove().await; - poll.registry().deregister(&mut player.client.connection)?; + if player.client.closed { + drop(player); + if let Some(player) = players.remove(&token) { + let mut player = player.lock().unwrap(); + player.remove().await; + poll.registry().deregister(&mut player.client.connection)?; + } } - } + }; // Poll current Clients (non players) // Maybe received an event for a TCP connection. @@ -195,10 +191,9 @@ fn main() -> io::Result<()> { if done { poll.registry().deregister(&mut client.connection)?; } else if make_player { - let token = client.token.clone(); + let token = client.token; let mut server = server.lock().await; - let (player, world) = - server.add_player(token.clone(), client).await; + let (player, world) = server.add_player(token, client).await; players.insert(token, player.clone()); let mut world = world.lock().await; world.spawn_player(&BASIC_CONFIG, player).await; diff --git a/pumpkin/src/server.rs b/pumpkin/src/server/mod.rs similarity index 97% rename from pumpkin/src/server.rs rename to pumpkin/src/server/mod.rs index 4d908919e..d540dd40e 100644 --- a/pumpkin/src/server.rs +++ b/pumpkin/src/server/mod.rs @@ -112,7 +112,7 @@ impl Server { pub async fn add_player( &mut self, - token: Arc, + token: Token, client: Client, ) -> (Arc>, Arc>) { let entity_id = self.new_entity_id(); @@ -145,12 +145,12 @@ impl Server { } /// Sends a Packet to all Players in all worlds - pub fn broadcast_packet_all

(&self, expect: &[&Arc], packet: &P) + pub fn broadcast_packet_all

(&self, except: &[Token], packet: &P) where P: ClientPacket, { for world in &self.worlds { - world.blocking_lock().broadcast_packet(expect, packet) + world.blocking_lock().broadcast_packet(except, packet) } } diff --git a/pumpkin/src/world/mod.rs b/pumpkin/src/world/mod.rs index 0761acf0d..fbca46437 100644 --- a/pumpkin/src/world/mod.rs +++ b/pumpkin/src/world/mod.rs @@ -26,7 +26,7 @@ use crate::{client::Client, entity::player::Player}; pub struct World { pub level: Arc>, - pub current_players: HashMap, Arc>>, + pub current_players: HashMap>>, // entities, players... } @@ -39,14 +39,14 @@ impl World { } /// Sends a Packet to all Players, Expect some players. Because we can't lock them twice - pub fn broadcast_packet

(&self, expect: &[&Arc], packet: &P) + pub fn broadcast_packet

(&self, except: &[Token], packet: &P) where P: ClientPacket, { for (_, player) in self .current_players .iter() - .filter(|c| !expect.contains(&c.0)) + .filter(|c| !except.contains(c.0)) { let mut player = player.lock().unwrap(); player.client.send_packet(packet); @@ -118,7 +118,7 @@ impl World { }], )); self.broadcast_packet( - &[&player.client.token], + &[player.client.token], &CPlayerInfoUpdate::new( 0x01 | 0x08, &[pumpkin_protocol::client::play::Player { @@ -139,7 +139,7 @@ impl World { for (_, playerr) in self .current_players .iter() - .filter(|c| c.0 != &player.client.token) + .filter(|(c, _)| **c != player.client.token) { let playerr = playerr.as_ref().lock().unwrap(); let gameprofile = &playerr.gameprofile; @@ -165,7 +165,7 @@ impl World { // spawn player for every client self.broadcast_packet( - &[&player.client.token], + &[player.client.token], // TODO: add velo &CSpawnEntity::new( entity_id.into(), @@ -184,7 +184,7 @@ impl World { ), ); // spawn players for our client - let token = player.client.token.clone(); + let token = player.client.token; for (_, existing_player) in self.current_players.iter().filter(|c| c.0 != &token) { let existing_player = existing_player.as_ref().lock().unwrap(); let entity = &existing_player.entity; @@ -213,7 +213,7 @@ impl World { Metadata::new(17, VarInt(0), config.skin_parts), ); player.client.send_packet(&packet); - self.broadcast_packet(&[&player.client.token], &packet) + self.broadcast_packet(&[player.client.token], &packet) } // Spawn in inital chunks @@ -277,7 +277,7 @@ impl World { None } - pub fn add_player(&mut self, token: Arc, player: Arc>) { + pub fn add_player(&mut self, token: Token, player: Arc>) { self.current_players.insert(token, player); } @@ -288,9 +288,9 @@ impl World { let id = player.entity_id(); let uuid = player.gameprofile.id; self.broadcast_packet( - &[&player.client.token], + &[player.client.token], &CRemovePlayerInfo::new(1.into(), &[UUID(uuid)]), ); - self.broadcast_packet(&[&player.client.token], &CRemoveEntities::new(&[id.into()])) + self.broadcast_packet(&[player.client.token], &CRemoveEntities::new(&[id.into()])) } }