Compare commits
No commits in common. "master" and "update/20th-Feb" have entirely different histories.
master
...
update/20t
22
README.md
22
README.md
@ -1,24 +1,4 @@
|
|||||||
# Pumpkin Blog
|
# Nuxt Content Starter
|
||||||
|
|
||||||
## Blog Post Format & YouTube Embeds
|
|
||||||
|
|
||||||
- Posts are regular Markdown files in the `content/` folder and require frontmatter. Example frontmatter:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
---
|
|
||||||
date: yyyy-mm-dd
|
|
||||||
author:
|
|
||||||
name: Me
|
|
||||||
url: https://github.com/Me
|
|
||||||
title: Update - Day Month Year
|
|
||||||
---
|
|
||||||
```
|
|
||||||
|
|
||||||
- To embed YouTube videos use the `Youtube` content component (with 11-character video ID):
|
|
||||||
|
|
||||||
```md
|
|
||||||
<Youtube videoId="Zz6YbXRX7d8"></Youtube>
|
|
||||||
```
|
|
||||||
|
|
||||||
Look at the [Nuxt Content documentation](https://content.nuxt.com) to learn more.
|
Look at the [Nuxt Content documentation](https://content.nuxt.com) to learn more.
|
||||||
|
|
||||||
|
|||||||
@ -1,15 +1,11 @@
|
|||||||
@import "tailwindcss";
|
@import "tailwindcss";
|
||||||
@plugin "@tailwindcss/typography";
|
|
||||||
|
|
||||||
@custom-variant dark (&:where(.dark, .dark *));
|
|
||||||
|
|
||||||
@theme {
|
@theme {
|
||||||
--color-background: #ffffff;
|
--color-background: #0d0d0d;
|
||||||
--color-surface: #f4f4f5;
|
--color-surface: #1a1a1a;
|
||||||
|
|
||||||
--color-foreground: #18181b;
|
--color-foreground: #f0f0f0;
|
||||||
--color-muted: #52525b;
|
--color-muted: #999;
|
||||||
--color-border: #e4e4e7;
|
|
||||||
|
|
||||||
--color-primary: #ff6b2c;
|
--color-primary: #ff6b2c;
|
||||||
--color-blue: #4169e1;
|
--color-blue: #4169e1;
|
||||||
@ -30,34 +26,12 @@
|
|||||||
--radius-none: 0;
|
--radius-none: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@layer theme {
|
|
||||||
.dark {
|
|
||||||
--color-background: #0d0d0d;
|
|
||||||
--color-surface: #1a1a1a;
|
|
||||||
|
|
||||||
--color-foreground: #f0f0f0;
|
|
||||||
--color-muted: #999999;
|
|
||||||
--color-border: #27272a;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.dark {
|
|
||||||
--color-background: #0d0d0d;
|
|
||||||
--color-surface: #1a1a1a;
|
|
||||||
|
|
||||||
--color-foreground: #f0f0f0;
|
|
||||||
--color-muted: #999999;
|
|
||||||
--color-border: #27272a;
|
|
||||||
}
|
|
||||||
|
|
||||||
html {
|
html {
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
color-scheme: light dark;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
font-size: 1.1rem;
|
font-size: 1.1rem;
|
||||||
transition: background-color 0.2s ease, color 0.2s ease;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@layer base {
|
@layer base {
|
||||||
@ -66,11 +40,11 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
h1 { @apply text-5xl font-black mb-10 text-foreground tracking-tight; }
|
h1 { @apply text-5xl font-black mb-10 text-foreground tracking-tight; }
|
||||||
h2 { @apply text-3xl font-bold mt-16 mb-6 text-primary uppercase tracking-widest border-b border-border dark:border-surface pb-2; }
|
h2 { @apply text-3xl font-bold mt-16 mb-6 text-primary uppercase tracking-widest border-b border-surface pb-2; }
|
||||||
h3 { @apply text-2xl font-bold mt-10 mb-4 text-foreground/90; }
|
h3 { @apply text-2xl font-bold mt-10 mb-4 text-foreground/90; }
|
||||||
|
|
||||||
.prose p {
|
.prose p {
|
||||||
@apply mb-8 text-foreground/90 max-w-3xl;
|
@apply mb-8 text-foreground/85 max-w-3xl;
|
||||||
}
|
}
|
||||||
|
|
||||||
.prose a,
|
.prose a,
|
||||||
@ -82,49 +56,14 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.prose p a {
|
.prose p a {
|
||||||
@apply text-primary font-semibold hover:text-foreground transition-colors;
|
@apply text-primary font-semibold hover:text-white;
|
||||||
}
|
}
|
||||||
|
|
||||||
.prose blockquote {
|
.prose blockquote {
|
||||||
@apply border-l-4 border-primary bg-surface/70 py-2 px-6 italic my-10 text-foreground/90;
|
@apply border-l-4 border-primary bg-surface/50 py-2 px-6 italic my-10 text-foreground/90;
|
||||||
}
|
}
|
||||||
|
|
||||||
.prose code {
|
.prose code {
|
||||||
@apply bg-surface text-primary px-1.5 py-0.5 rounded font-mono text-sm border border-border;
|
@apply bg-surface text-primary px-1.5 py-0.5 rounded font-mono text-sm;
|
||||||
}
|
|
||||||
|
|
||||||
.prose pre {
|
|
||||||
@apply border border-border dark:border-white/10;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Shiki dual themes */
|
|
||||||
html.dark .shiki,
|
|
||||||
html.dark .shiki span {
|
|
||||||
color: var(--shiki-dark) !important;
|
|
||||||
background-color: var(--shiki-dark-bg) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
html:not(.dark) .shiki,
|
|
||||||
html:not(.dark) .shiki span {
|
|
||||||
color: var(--shiki-light) !important;
|
|
||||||
background-color: var(--shiki-light-bg) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* responsive container for youtube/video embeds generated by markdown */
|
|
||||||
.embed-responsive {
|
|
||||||
position: relative;
|
|
||||||
width: 100%;
|
|
||||||
padding-bottom: 56.25%;
|
|
||||||
height: 0;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.embed-responsive iframe {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
border: 0;
|
|
||||||
}
|
|
||||||
@ -14,14 +14,14 @@ const { data: posts } = await useAsyncData("blog-posts", () => {
|
|||||||
v-for="post in posts"
|
v-for="post in posts"
|
||||||
:to="post.path"
|
:to="post.path"
|
||||||
:key="post.id"
|
:key="post.id"
|
||||||
class="group no-underline text-inherit block mb-5"
|
class="no-underline text-inherit block mb-5"
|
||||||
>
|
>
|
||||||
<section class="px-5 pt-5 hover:bg-black/5 dark:hover:bg-white/5 bg-inherit rounded-2xl transition-colors duration-150">
|
<section class="px-5 pt-5 hover:bg-white/2 bg-inherit rounded-2xl">
|
||||||
<h2 class="mt-2 text-foreground group-hover:text-primary transition-colors">{{ post.title }}</h2>
|
<h2 class="mt-2">{{ post.title }}</h2>
|
||||||
<p class="text-foreground/80 my-2">{{ post.description }}</p>
|
<p>{{ post.description }}</p>
|
||||||
<div class="text-muted text-sm mb-5">
|
<div class="opacity-60 mb-5">
|
||||||
<span v-if="post.author">{{ post.author.name }}</span>
|
<span>{{ post.author.name }}</span>
|
||||||
<span v-if="post.author" class="mx-2">•</span>
|
<span class="mx-2">•</span>
|
||||||
<span>{{
|
<span>{{
|
||||||
new Date(post.date).toLocaleDateString(undefined, {
|
new Date(post.date).toLocaleDateString(undefined, {
|
||||||
year: "numeric",
|
year: "numeric",
|
||||||
|
|||||||
@ -1,21 +1,15 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts"></script>
|
||||||
const colorMode = useColorMode();
|
|
||||||
|
|
||||||
const toggleTheme = () => {
|
|
||||||
colorMode.preference = colorMode.value === "dark" ? "light" : "dark";
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<header
|
<header
|
||||||
class="flex flex-col space-y-3 sm:space-y-0 sm:grid grid-cols-2 md:flex md:flex-row items-center justify-center md:gap-0 md:justify-between px-8 py-4 bg-surface border-b-primary border-b-[3px] sticky top-0 z-50 transition-colors duration-200"
|
class="flex flex-col space-y-3 sm:space-y-0 sm:grid grid-cols-2 md:flex md:flex-row items-center justify-center md:gap-0 md:justify-between px-8 py-4 bg-surface border-b-primary border-b-[3px] sticky top-0 z-50"
|
||||||
>
|
>
|
||||||
<NuxtLink
|
<NuxtLink
|
||||||
to="/"
|
href="https://pumpkinmc.org/"
|
||||||
class="flex items-center gap-2 no-underline font-extrabold text-2xl flex-shrink-0 text-foreground"
|
class="flex items-center gap-2 no-underline font-extrabold text-2xl flex-shrink-0"
|
||||||
|
external
|
||||||
>
|
>
|
||||||
<NuxtImg class="w-10 h-10 flex-shrink-0" src="/images/icon.svg" alt="" aria-hidden="true" />
|
<NuxtImg class="w-10 h-10" src="images/icon.svg" alt="Pumpkin" />
|
||||||
<span>Pumpkin-Blog</span>
|
<span>pumpkin</span>
|
||||||
</NuxtLink>
|
</NuxtLink>
|
||||||
<nav
|
<nav
|
||||||
class="nav flex gap-1 lg:gap-2 md:order-0 order-2 col-span-2 justify-center"
|
class="nav flex gap-1 lg:gap-2 md:order-0 order-2 col-span-2 justify-center"
|
||||||
@ -28,24 +22,9 @@ const toggleTheme = () => {
|
|||||||
<NuxtLink to="https://pumpkinmc.org/contributors/" external
|
<NuxtLink to="https://pumpkinmc.org/contributors/" external
|
||||||
>Contributors</NuxtLink
|
>Contributors</NuxtLink
|
||||||
>
|
>
|
||||||
<NuxtLink to="/">Blog</NuxtLink>
|
<NuxtLink to="https://blog.pumpkinmc.org/" external>Blog</NuxtLink>
|
||||||
</nav>
|
</nav>
|
||||||
<div class="flex items-center gap-2 justify-end">
|
<div class="flex items-center gap-2 justify-end">
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
class="icon-btn cursor-pointer"
|
|
||||||
:title="colorMode.value === 'dark' ? 'Switch to light mode' : 'Switch to dark mode'"
|
|
||||||
:aria-label="colorMode.value === 'dark' ? 'Switch to light mode' : 'Switch to dark mode'"
|
|
||||||
@click="toggleTheme"
|
|
||||||
>
|
|
||||||
<ClientOnly>
|
|
||||||
<Icon v-if="colorMode.value === 'dark'" name="fa7-solid:sun" />
|
|
||||||
<Icon v-else name="fa7-solid:moon" />
|
|
||||||
<template #fallback>
|
|
||||||
<Icon name="fa7-solid:moon" />
|
|
||||||
</template>
|
|
||||||
</ClientOnly>
|
|
||||||
</button>
|
|
||||||
<a
|
<a
|
||||||
href="https://github.com/Pumpkin-MC/Pumpkin"
|
href="https://github.com/Pumpkin-MC/Pumpkin"
|
||||||
class="icon-btn"
|
class="icon-btn"
|
||||||
@ -61,7 +40,7 @@ const toggleTheme = () => {
|
|||||||
<Icon name="fa7-brands:discord" />
|
<Icon name="fa7-brands:discord" />
|
||||||
</a>
|
</a>
|
||||||
<a
|
<a
|
||||||
href="https://pumpkinmc.org/donate/"
|
href="https://github.com/sponsors/Snowiiii"
|
||||||
class="sponsor-btn"
|
class="sponsor-btn"
|
||||||
title="Sponsor"
|
title="Sponsor"
|
||||||
>
|
>
|
||||||
@ -133,7 +112,7 @@ const toggleTheme = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.icon-btn {
|
.icon-btn {
|
||||||
@apply flex items-center justify-center w-10.5 h-10.5 bg-background text-foreground text-xl no-underline border-[3px] border-foreground shadow-[3px_3px_0_var(--color-foreground)] transition-all duration-100 ease-in-out cursor-pointer;
|
@apply flex items-center justify-center w-10.5 h-10.5 bg-background text-foreground text-xl no-underline border-[3px] border-foreground shadow-[3px_3px_0_var(--color-foreground)] transition-all duration-100 ease-in-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon-btn:hover {
|
.icon-btn:hover {
|
||||||
|
|||||||
@ -1,17 +0,0 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
defineProps<{ videoid: string }>();
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<div class="not-prose mx-auto max-w-3xl w-full aspect-video overflow-hidden rounded-lg">
|
|
||||||
<ClientOnly>
|
|
||||||
<iframe
|
|
||||||
:src="`https://www.youtube.com/embed/${videoid}`"
|
|
||||||
class="h-full w-full"
|
|
||||||
frameborder="0"
|
|
||||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
|
||||||
allowfullscreen
|
|
||||||
/>
|
|
||||||
</ClientOnly>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
@ -1,6 +1,5 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { withoutTrailingSlash } from "ufo";
|
import { withoutTrailingSlash } from "ufo";
|
||||||
import { useHead, useRuntimeConfig } from '#imports';
|
|
||||||
|
|
||||||
definePageMeta({
|
definePageMeta({
|
||||||
documentDriven: true,
|
documentDriven: true,
|
||||||
@ -13,30 +12,6 @@ const { data: page } = await useAsyncData(`blog-${path}`, () => {
|
|||||||
return queryCollection("blog").path(path).first();
|
return queryCollection("blog").path(path).first();
|
||||||
});
|
});
|
||||||
|
|
||||||
if (page.value) {
|
|
||||||
// dynamically set document head for SEO / social previews
|
|
||||||
const title = page.value.title || 'Pumpkin Blog';
|
|
||||||
const description = page.value.description || '';
|
|
||||||
const image = page.value.image || '/images/icon.svg';
|
|
||||||
const url = useRuntimeConfig().public.siteUrl + path;
|
|
||||||
|
|
||||||
useHead({
|
|
||||||
title,
|
|
||||||
meta: [
|
|
||||||
{ name: 'description', content: description },
|
|
||||||
{ property: 'og:title', content: title },
|
|
||||||
{ property: 'og:description', content: description },
|
|
||||||
{ property: 'og:type', content: 'article' },
|
|
||||||
{ property: 'og:url', content: url },
|
|
||||||
{ property: 'og:image', content: image },
|
|
||||||
{ name: 'twitter:card', content: 'summary_large_image' },
|
|
||||||
{ name: 'twitter:title', content: title },
|
|
||||||
{ name: 'twitter:description', content: description },
|
|
||||||
{ name: 'twitter:image', content: image },
|
|
||||||
],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!page.value) {
|
if (!page.value) {
|
||||||
throw createError({
|
throw createError({
|
||||||
statusCode: 404,
|
statusCode: 404,
|
||||||
@ -48,13 +23,13 @@ if (!page.value) {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<article
|
<article
|
||||||
class="prose dark:prose-invert prose-orange m-auto min-h-[70%] max-w-screen-lg px-12 pb-20"
|
class="prose prose-invert prose-orange m-auto min-h-[70%] max-w-screen-lg px-12 pb-20"
|
||||||
>
|
>
|
||||||
<h1 class="pb-0! mb-0! leading-none!" v-if="page?.title">
|
<h1 class="pb-0! mb-0! leading-none!" v-if="page?.title">
|
||||||
{{ page.title }}
|
{{ page.title }}
|
||||||
</h1>
|
</h1>
|
||||||
<div class="text-muted mt-3">
|
<div class="opacity-60">
|
||||||
<a v-if="page?.author" :href="page.author.url" class="hover:text-primary transition-colors">{{
|
<a v-if="page?.author" :href="page.author.url">{{
|
||||||
page.author.name
|
page.author.name
|
||||||
}}</a>
|
}}</a>
|
||||||
<span v-if="page?.author && page?.date" class="mx-2">•</span>
|
<span v-if="page?.author && page?.date" class="mx-2">•</span>
|
||||||
@ -72,8 +47,9 @@ if (!page.value) {
|
|||||||
</article>
|
</article>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style>
|
||||||
@reference "@/assets/css/main.css";
|
@import "tailwindcss";
|
||||||
|
@plugin "@tailwindcss/typography";
|
||||||
|
|
||||||
h1 {
|
h1 {
|
||||||
@apply text-5xl font-extrabold pb-8 pt-12;
|
@apply text-5xl font-extrabold pb-8 pt-12;
|
||||||
|
|||||||
@ -13,8 +13,6 @@ export default defineContentConfig({
|
|||||||
url: z.string().url(),
|
url: z.string().url(),
|
||||||
}),
|
}),
|
||||||
title: z.string(),
|
title: z.string(),
|
||||||
description: z.string().optional(),
|
|
||||||
image: z.string().url().optional(),
|
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
|
|||||||
@ -1,64 +0,0 @@
|
|||||||
---
|
|
||||||
title: "Why We Rewrote Our Plugin API"
|
|
||||||
date: "2026-05-11"
|
|
||||||
author:
|
|
||||||
name: Alexander Medvedev
|
|
||||||
url: https://github.com/Snowiiii
|
|
||||||
description: "A deep dive into our decision to move away from native Rust plugins and embrace WebAssembly for the future of Pumpkin."
|
|
||||||
---
|
|
||||||
|
|
||||||
When we first started building the plugin system for Pumpkin, our goal was simple: provide developers with the fastest, most powerful way to extend the server. Since Pumpkin itself is written in Rust, the most obvious choice was to build a native Rust plugin API.
|
|
||||||
|
|
||||||
In the early days, this worked. Plugins were incredibly fast, and developers had full, unrestricted access to the server's internals. However, as the project grew and more people started experimenting with custom code, the cracks in the native approach began to show.
|
|
||||||
|
|
||||||
We eventually realized that if Pumpkin was going to have a thriving, sustainable ecosystem, we needed to make a radical change. We decided to rewrite the entire plugin system using **WebAssembly (WASM)**.
|
|
||||||
|
|
||||||
Here is the story of why we made that difficult choice, and the problems we left behind.
|
|
||||||
|
|
||||||
### The Problems with Native Rust Plugins
|
|
||||||
|
|
||||||
Native plugins sound great on paper, but in a production server environment, they introduce severe technical and logistical hurdles.
|
|
||||||
|
|
||||||
#### The Unstable ABI
|
|
||||||
|
|
||||||
Rust does not have a stable Application Binary Interface (ABI). This means that the way Rust code is compiled into machine code can change between different versions of the compiler, and even between different compiler flags.
|
|
||||||
|
|
||||||
For plugin developers, this was a nightmare. If a server administrator updated Pumpkin, or if they were running a version compiled with a slightly different Rust toolchain, native plugins would simply refuse to load or worse, cause catastrophic memory corruption. Plugin developers would have to constantly recompile and release new binaries for every single minor Pumpkin update or Rust version bump. It was a maintenance burden that stifled innovation.
|
|
||||||
|
|
||||||
#### Crashing the Entire Server
|
|
||||||
|
|
||||||
Native plugins share the exact same memory space and execution context as the core server. While Rust is famous for its memory safety, it cannot prevent logical panics.
|
|
||||||
|
|
||||||
If a native plugin encountered an unexpected state and called `.unwrap()` on a `None` value, it wouldn't just stop the plugin—it would crash the entire Pumpkin server, disconnecting all players immediately. In a multiplayer environment where uptime is critical, allowing third-party code to take down the main thread is an unacceptable risk. We needed a way to isolate plugins from the core server loop.
|
|
||||||
|
|
||||||
#### The Marketplace Distribution Nightmare
|
|
||||||
|
|
||||||
We have long-term plans to build a decentralized marketplace where server administrators can easily browse, download, and install plugins. With native plugins, distribution is incredibly complex.
|
|
||||||
|
|
||||||
Because native code is tied to specific operating systems and CPU architectures, a plugin developer would have to compile and upload separate binaries for Windows, Linux, macOS, x86, and ARM.
|
|
||||||
|
|
||||||
#### Security Risks
|
|
||||||
|
|
||||||
Furthermore, downloading arbitrary native binaries from the internet and executing them on a host server is a massive security risk. Native plugins have unrestricted access to the host system, meaning a malicious plugin could read files, access the network, or compromise the entire server. We needed a format that was universally portable and inherently secure by design.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### The WebAssembly Solution
|
|
||||||
|
|
||||||
WebAssembly solved every single one of these problems. By moving our Plugin API to WASM (utilizing the WebAssembly Interface Type, or WIT), we completely changed the landscape of Pumpkin development.
|
|
||||||
|
|
||||||
**A Stable, Cross-Language Interface:**
|
|
||||||
WASM and WIT provide a stable contract between the server and the plugin. A plugin compiled today will continue to work on future versions of Pumpkin. Even better, because WASM is language-agnostic, you are no longer forced to write plugins in Rust. You can now use C/C++, Go, Python, or C#.
|
|
||||||
|
|
||||||
**Safe Sandboxing:**
|
|
||||||
WASM executes inside a secure, isolated sandbox. If a WASM plugin encounters a fatal error or panics, the sandbox simply terminates the plugin. The core Pumpkin server continues running flawlessly, and players remain connected.
|
|
||||||
|
|
||||||
**Universal Distribution:**
|
|
||||||
A WASM module is a single `.wasm` file. It runs identically on Windows, Linux, ARM, or any other architecture the server runs on. This makes the dream of a frictionless plugin marketplace a reality. Server admins can download a plugin, knowing it will run safely and exactly as intended on their specific hardware.
|
|
||||||
|
|
||||||
**Custom Plugin Permission System:**
|
|
||||||
To further enhance security, we added a custom plugin permission system alongside WASM. This system allows server administrators to review the specific capabilities a plugin is requesting, giving owners the ability to explicitly accept or decline initial permissions before the plugin is allowed to run.
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
Moving to WASM was a massive undertaking, but looking at the stability and flexibility of the API today, it was undoubtedly the right choice. The future of Pumpkin plugins is safe, portable, and built on WebAssembly.
|
|
||||||
@ -1,207 +0,0 @@
|
|||||||
---
|
|
||||||
title: "From Async to Sync"
|
|
||||||
date: "2026-09-26"
|
|
||||||
author:
|
|
||||||
name: Alexander Medvedev
|
|
||||||
url: https://github.com/Snowiiii
|
|
||||||
description: "Many Rust developers assume async is always faster. In Pumpkin, using Tokio for entity ticking and game logic was one of our biggest early mistakes. Here is why we rewrote the core loop to be synchronous—and how Rayon changed everything."
|
|
||||||
---
|
|
||||||
|
|
||||||
If you spend any time in the modern Rust ecosystem, you will hear a universal gospel preached across every blog post, Reddit thread, and Discord server:
|
|
||||||
|
|
||||||
*"Use Tokio. Make it async. Async Rust is blazingly fast."*
|
|
||||||
|
|
||||||
When we first started building Pumpkin, we fell for this trap hook, line, and sinker. The reasoning felt airtight at the time: Pumpkin is a high-performance Minecraft server written from scratch in Rust. We wanted it to handle thousands of entities, dozens of players, and massive worlds without breaking a sweat. Tokio handles millions of concurrent web connections—so naturally, making everything in Pumpkin `async` had to be the secret sauce for raw performance. Right?
|
|
||||||
|
|
||||||
Wrong. In fact, it was probably the single worst architectural decision we made in the early days of the project.
|
|
||||||
|
|
||||||
Over the last few months, we undertook a massive, grueling, four-part refactor to rip `async` and `.await` completely out of our game loop, our entity ticking, our inventory management, and our commands.
|
|
||||||
|
|
||||||
Here is the honest story of why async game loops are a trap, why Tokio and Rayon solve two completely opposite problems, and how moving from async to synchronous ticking made Pumpkin faster, cleaner, and drastically more stable.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### "Async = Fast"
|
|
||||||
|
|
||||||
The fundamental mistake so many Rust developers make (and the one we made) comes from misunderstanding what `async` is actually designed to do.
|
|
||||||
|
|
||||||
In web backends, microservices, and proxy servers, asynchronous runtimes like Tokio are unbeatable. Why? Because web servers spend 99% of their lifespan doing absolutely nothing. A request comes in, the server fires off a SQL query or reads a file from disk, and then it waits. While waiting on network sockets or disk I/O, the operating system thread doesn't need to sit idle. Tokio uses non-blocking I/O primitives (`epoll` on Linux, `kqueue` on macOS, `io_uring`) so a tiny handful of worker threads can juggle tens of thousands of idle connections concurrently.
|
|
||||||
|
|
||||||
That is **I/O-bound concurrency**.
|
|
||||||
|
|
||||||
A game server, however, is a completely different beast.
|
|
||||||
|
|
||||||
A Minecraft server operates on a fixed heartbeat—20 ticks per second. That gives you exactly **50 milliseconds** per tick to update the entire universe. And here is the crucial realization we completely missed at the beginning:
|
|
||||||
|
|
||||||
**By the time a game tick starts, all network packets are already buffered in memory.**
|
|
||||||
|
|
||||||
During those 50 milliseconds, you aren't making HTTP requests. You aren't waiting on a database query. You aren't waiting on slow network packets. You are:
|
|
||||||
- Looping over hundreds of living mobs.
|
|
||||||
- Computing bounding box collisions.
|
|
||||||
- Running pathfinding algorithms and line-of-sight raycasts.
|
|
||||||
- Updating physics, velocity, and gravity.
|
|
||||||
- Checking crafting recipes and slot states.
|
|
||||||
|
|
||||||
Every single one of these tasks is **100% CPU-bound**.
|
|
||||||
|
|
||||||
When you write CPU-bound simulation code inside Tokio tasks, you aren't doing non-blocking I/O. You are asking an asynchronous event loop to schedule raw computation. And that is where the nightmare begins.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Tokio vs. Rayon
|
|
||||||
|
|
||||||
To understand why this hurt us so badly, you have to look at the architectural difference between **Tokio** and **Rayon**.
|
|
||||||
|
|
||||||
| Aspect | Tokio | Rayon |
|
|
||||||
| :--- | :--- | :--- |
|
|
||||||
| **Primary Goal** | Asynchronous I/O multiplexing | Data-parallel CPU computation |
|
|
||||||
| **Work Unit** | `Future` / Asynchronous Task | Work-stealing task / Iterator chunk |
|
|
||||||
| **Yield Mechanism** | Explicit `.await` on I/O or timers | Work-stealing across physical cores |
|
|
||||||
| **Allocation Cost** | Future state-machines, task queues | Zero allocation across stack slices |
|
|
||||||
| **Ideal Workload** | Sockets, WebSockets, DB queries, Timers | Matrix math, physics, pathfinding, raycasts |
|
|
||||||
|
|
||||||
#### Ticking Entities with Tokio
|
|
||||||
At our worst point, we were literally spawning Tokio tasks for entities:
|
|
||||||
|
|
||||||
```rust
|
|
||||||
// The naive async past: Spawning Tokio tasks per entity
|
|
||||||
for entity in entities_to_tick.iter() {
|
|
||||||
let e = entity.clone();
|
|
||||||
tasks.spawn(async move {
|
|
||||||
e.tick().await;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Think about what this actually does under the hood.
|
|
||||||
|
|
||||||
Every single tick, for every single entity in the world, Tokio has to allocate a `Future` state machine, push it onto a task queue, notify worker threads, and context-switch into it. When an entity finishes updating its coordinates 4 nanoseconds later, Tokio has to clean up that task and coordinate its completion.
|
|
||||||
|
|
||||||
We were spending more CPU cycles inside Tokio's runtime scheduler managing task queues and waking futures than the actual entities spent calculating their physics!
|
|
||||||
|
|
||||||
Even worse: Tokio worker threads rely on tasks voluntarily yielding via `.await`. If an entity pathfinding calculation takes 2 milliseconds of pure CPU crunching without awaiting an I/O event, it **starves the Tokio worker thread**. Other tasks queued on that thread—including reading incoming TCP packets from real players—get blocked behind it!
|
|
||||||
|
|
||||||
#### What Rayon Does Instead
|
|
||||||
Rayon doesn't care about futures, event loops, or `.await`. Rayon is a pure data-parallel work-stealing thread pool.
|
|
||||||
|
|
||||||
Rayon spins up a thread pool that matches your physical CPU cores. When you give it a slice of entities, it divides the slice among available cores:
|
|
||||||
|
|
||||||
```rust
|
|
||||||
// The synchronous present: Straightforward Rayon data parallelism
|
|
||||||
tickable
|
|
||||||
.par_chunks(ENTITY_TICK_BATCH_SIZE)
|
|
||||||
.for_each(|batch| {
|
|
||||||
for (entity, _) in batch {
|
|
||||||
entity.tick(entity.as_ref(), server_ref);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
There are no heap-allocated state machines. There is no runtime polling. There are no yield points. The threads just burn through the batches sequentially on the CPU with fantastic L1/L2 cache locality. If core 3 finishes its chunk of 16 zombies before core 2 finishes its creepers, core 3 instantly steals work from core 2's queue.
|
|
||||||
|
|
||||||
It is direct, unadulterated CPU throughput.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Wrapping Everything in Arc<Mutex>
|
|
||||||
|
|
||||||
The performance penalty of Tokio tasks was bad, but the damage async did to our codebase architecture was even worse.
|
|
||||||
|
|
||||||
In Rust, the borrow checker is your best friend. If you have synchronous code, you can pass a `&mut World` or `&mut Entity` down the stack, update whatever you need, and the compiler guarantees at compile time that nothing else is mutating it. Zero runtime overhead.
|
|
||||||
|
|
||||||
The moment you mark a function as `async`, you lose this superpower.
|
|
||||||
|
|
||||||
Because an `async fn` can yield at an `.await` point and resume on a completely different OS thread, you cannot easily hold a normal mutable reference across that boundary without running into `!Send` compile errors.
|
|
||||||
|
|
||||||
So what do developers do when the compiler screams at them?
|
|
||||||
|
|
||||||
**They wrap everything in `Arc<Mutex<T>>`.**
|
|
||||||
|
|
||||||
It started innocently with `Arc<Mutex<Player>>`. But async is a virus. If player interaction is async, then opening a chest is async. If opening a chest is async, then accessing a slot is async.
|
|
||||||
|
|
||||||
At one point in Pumpkin, we literally had **per-slot `Arc<Mutex<ItemStack>>` in player inventories**.
|
|
||||||
|
|
||||||
Just imagine what happened when a player crafted an item or sorted a chest:
|
|
||||||
1. Lock slot 0 asynchronously.
|
|
||||||
2. Await lock on slot 1.
|
|
||||||
3. Await lock on slot 2.
|
|
||||||
4. Risk lock contention with the main tick thread or another packet handler.
|
|
||||||
5. Pray you don't hit an async deadlock because two tasks acquired slot locks in reverse order.
|
|
||||||
|
|
||||||
It was madness. Reading a simple inventory required locking dozens of individual mutexes across multiple async boundaries. What should have been a 5-nanosecond array lookup turned into a festival of atomic CAS operations, thread parking, and cache line invalidation.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### async_trait, Box<Pin>, and Compile Hell
|
|
||||||
|
|
||||||
It wasn't just runtime performance that suffered—the developer experience became completely miserable.
|
|
||||||
|
|
||||||
For a long time, contributors rightfully complained about how painful it was to work on Pumpkin. Want to add a simple command? Want to implement a new entity goal, or handle a block interaction? You had to wade through thick layers of async boilerplate, confusing lifetime annotations, and compiler errors that stretched across three terminal screens.
|
|
||||||
|
|
||||||
And then came the dynamic dispatch problem. Because Rust didn't support native `async fn` in traits for `dyn Trait` objects, we had to figure out how to make our entity, block, and command traits async.
|
|
||||||
|
|
||||||
1. **First, we slapped `#[async_trait]` on everything.**
|
|
||||||
At first, this felt like an easy fix. But as the codebase grew to hundreds of entities, blocks, and packet types, `#[async_trait]` brought our compile times to their knees. Every single trait method was expanding into proc-macro-generated code, boxing futures behind the scenes, and blowing up LLVM codegen times. Clean builds took an eternity, and incremental compilation ground to a crawl. Contributors were waiting minutes just to see if a tiny one-line change compiled.
|
|
||||||
|
|
||||||
2. **Then, we tried to escape it with manual `Box<Pin<dyn Future<...>>>`.**
|
|
||||||
In a desperate attempt to shave off macro overhead and regain control over compilation times, we started manually desugaring trait return types. Suddenly, almost every trait method in Pumpkin was littered with this hideous monstrosity:
|
|
||||||
```rust
|
|
||||||
fn tick<'a>(&'a mut self, world: &'a World) -> Pin<Box<dyn Future<Output = ()> + Send + 'a>>
|
|
||||||
```
|
|
||||||
If you have ever tried explaining that signature to a new open-source contributor who just wanted to add a simple mob mechanic, you know the feeling of pure despair. Writing new features felt like playing 4D chess against the borrow checker and the type system while blindfolded. New contributors would open a PR, get buried under unreadable lifetime diagnostics and trait bound mismatches, get frustrated, and leave.
|
|
||||||
|
|
||||||
Our architecture was actively driving contributors away. That was our biggest wake-up call: we couldn't just keep patching over it with clever macros or manual pin-boxing. The design was fundamentally broken from the beginning, and async had no business being in those traits.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Four Parts from Async to Sync
|
|
||||||
|
|
||||||
By mid-2026, we stopped making excuses. We realized that no amount of profiling or micro-optimization would fix the fact that our core architecture was fighting the hardware.
|
|
||||||
|
|
||||||
We sat down and systematically dismantled the async loop across four major milestones:
|
|
||||||
|
|
||||||
1. **Part 1: The Core Game Loop (`World::tick`):** We converted the world tick, player ticking, and entity loops from `async fn` to plain, synchronous `fn`.
|
|
||||||
2. **Part 2: Entities & Projectiles:** We refactored all entity goals, AI routines, and projectile movements to synchronous execution. No more `JoinSet` allocations for mob updates.
|
|
||||||
3. **Part 3: Inventories & Commands:** We completely eliminated the per-slot `Arc<Mutex<ItemStack>>` locks. Inventories moved to clean, container-level synchronization with synchronous screen handlers. Commands no longer return futures.
|
|
||||||
4. **Part 4: Block Entities & World Actions:** Furnaces, chests, brewing stands, and hoppers were transitioned to synchronous ticks.
|
|
||||||
|
|
||||||
Alongside this, we made another critical move: **offloading chunk serialization, region compression, and packet encoding completely off Tokio workers and onto dedicated Rayon pools.**
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Where Tokio and Rayon Belong
|
|
||||||
|
|
||||||
We didn't delete Tokio from Pumpkin. Tokio is still an essential, beloved foundation of our server. But we finally drew a firm, uncrossable line between where Tokio belongs and where Rayon belongs:
|
|
||||||
|
|
||||||
#### Tokio at the Edge
|
|
||||||
Tokio handles the raw network connections. It listens on TCP and UDP sockets, negotiates TLS, handles Bedrock RakNet packets, performs Mojang/Bedrock authentication over HTTP, and streams raw bytes. When a packet arrives, Tokio decodes the header and places the raw packet into an in-memory queue.
|
|
||||||
|
|
||||||
#### Rayon in the Game Loop
|
|
||||||
When the dedicated 50ms tick timer fires, the server ticker executes **synchronously**:
|
|
||||||
- It pulls queued packets from memory.
|
|
||||||
- It executes entity ticks in parallel batches of 16 using Rayon's `par_chunks`.
|
|
||||||
- It processes player movements, collisions, block placements, and crafting recipes using plain Rust references (`&` and `&mut`).
|
|
||||||
- Once finished, outgoing packets are pushed to network buffers for Tokio to flush asynchronously to the sockets.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### What We Gained
|
|
||||||
|
|
||||||
The results of this transition blew away even our most optimistic expectations:
|
|
||||||
|
|
||||||
- **Massive Drop in Tick Duration:** Ticking hundreds of entities no longer fluctuates wildly. The scheduler overhead disappeared, reducing baseline entity tick times by several orders of magnitude.
|
|
||||||
- **Zero Mutex Contention:** By moving inventory and entity state to synchronous container-level ownership, we eliminated hundreds of `Arc<Mutex>` locks. Code that used to spend milliseconds waiting on lock contention now executes in nanoseconds.
|
|
||||||
- **Predictable 20 TPS:** The game loop no longer starves when complex pathfinding or physics calculations run. CPU-heavy work is executed across Rayon's worker threads without blocking incoming network packets.
|
|
||||||
- **Saner, Cleaner Code:** We deleted thousands of lines of boilerplate. Gone are the endless `.await` calls, `ArcSwap` acrobatics, and complex async trait wrappers. The codebase looks like idiomatic, clean Rust again.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Don't Cargo-Cult Async
|
|
||||||
|
|
||||||
If you are building a game server, an emulator, a physics engine, or any real-time simulation in Rust, take this as our cautionary tale:
|
|
||||||
|
|
||||||
**Do not cargo-cult async.**
|
|
||||||
|
|
||||||
Async Rust is an extraordinary tool for multiplexing I/O over network sockets and file handles. But the moment you let `async` leak into your core simulation loop, you are paying a massive tax in runtime allocation, scheduler overhead, and lock proliferation for a benefit that doesn't exist.
|
|
||||||
|
|
||||||
Use **Tokio** for the wire. Use **Rayon** for the world. Keep your game loop synchronous, let the CPU do what it does best, and trust the borrow checker.
|
|
||||||
@ -1,43 +0,0 @@
|
|||||||
---
|
|
||||||
date: 2026-03-13
|
|
||||||
author:
|
|
||||||
name: RoosterBooster007
|
|
||||||
url: https://github.com/RoosterBooster007
|
|
||||||
title: Update - 13th March 2026
|
|
||||||
---
|
|
||||||
|
|
||||||
### A Massive Foundation Shift
|
|
||||||
|
|
||||||
Welcome back! If you're looking at the numbers this week and thinking, "Only 15 PRs merged? Is the team sleeping?"—let me stop you right there. While our merge count might look a bit quieter this week, it's because we just landed an absolute behemoth of an update. We've been heavily focused on getting a massive core API change through the pipeline, and we currently have over 55+ PRs sitting in the queue undergoing rigorous review and testing (thanks for being patient, devs).
|
|
||||||
|
|
||||||
This week, we've been making sure that the foundational stuff is rock solid. And trust me, what we merged this week changes the game for Pumpkin entirely.
|
|
||||||
|
|
||||||
### WebAssembly is Here!
|
|
||||||
|
|
||||||
The biggest news of the week: **We got WASM!** Our plugin API is officially migrating to WebAssembly. We made this major architectural shift primarily for two reasons: **improved compatibility and top-tier security**. By sandboxing plugins in WASM, we ensure that server owners have a much safer environment, and developers have a more flexible, cross-language compilation target.
|
|
||||||
|
|
||||||
A massive shout-out is owed to **BjornTheProgrammer**, who led the charge on this monumental task. He implemented the core WASM plugin API ([#1675](https://github.com/Pumpkin-MC/Pumpkin/pull/1675)), created a much cleaner API for registering WASM events ([#1838](https://github.com/Pumpkin-MC/Pumpkin/pull/1838)), and added the ability to register permissions for these new plugins ([#1841](https://github.com/Pumpkin-MC/Pumpkin/pull/1841)). His hard work has laid the groundwork for the future of Pumpkin plugins.
|
|
||||||
|
|
||||||
Other contributors are already jumping on board to flesh out this new ecosystem. illyrius666 quickly stepped in to add context and player APIs, giving developers the ability to use `get_data_folder` and `get_name` right out of the gate ([#1843](https://github.com/Pumpkin-MC/Pumpkin/pull/1843), [#1840](https://github.com/Pumpkin-MC/Pumpkin/pull/1840)).
|
|
||||||
|
|
||||||
If you want to be one of the pioneers building on this new system, go read through our completely updated [Plugin API Documentation](https://docs.pumpkinmc.org/plugin-dev/introduction) to get started!
|
|
||||||
|
|
||||||
### Expanding the World
|
|
||||||
|
|
||||||
Even with the heavy API focus, we still made sure to sprinkle some new content into world generation.
|
|
||||||
|
|
||||||
If you find yourself wandering through a desert, keep your eyes peeled—chocodev11 successfully implemented the Desert Pyramid structure ([#1815](https://github.com/Pumpkin-MC/Pumpkin/pull/1815)). To balance out the dry heat, I spent some time in the water and added the feature generation for underwater magma blocks ([#1747](https://github.com/Pumpkin-MC/Pumpkin/pull/1747)).
|
|
||||||
|
|
||||||
### Squashing Bugs and Polishing Mechanics
|
|
||||||
|
|
||||||
On the mechanical side of things, we knocked out a few annoying bugs that were hindering the vanilla feel of the server:
|
|
||||||
|
|
||||||
- **Redstone & Pistons:** GreenedDev was our resident redstone engineer this week. He fixed an issue where redstone wire would stubbornly stay activated when it shouldn't ([#1855](https://github.com/Pumpkin-MC/Pumpkin/pull/1855)) and corrected a bug that prevented pistons from unextending properly ([#1812](https://github.com/Pumpkin-MC/Pumpkin/pull/1812)).
|
|
||||||
- **Combat & Equipment:** Have you ever broken a tool and noticed the server didn't quite react right? andreisugu fixed this by making sure the server broadcasts the proper `EntityStatus` when equipment breaks ([#1837](https://github.com/Pumpkin-MC/Pumpkin/pull/1837)), so you get that satisfying (or terrifying) visual and audio feedback.
|
|
||||||
- **Server Stability:** yuminstalljoe took care of some backend housekeeping by dropping the receiver correctly on console exit ([#1839](https://github.com/Pumpkin-MC/Pumpkin/pull/1839)), ensuring the server shuts down just a little bit more gracefully.
|
|
||||||
|
|
||||||
### Wrapping Up
|
|
||||||
|
|
||||||
Huge thanks to everyone who contributed this week, and an extra special shout-out to all the developers who are already diving in and trying out the new WASM plugin API early. It's a huge step forward for the project, and we couldn't do it without your testing and feedback.
|
|
||||||
|
|
||||||
With 55+ PRs in the oven, next week is going to be wild. Have a great weekend, start reading those WASM docs, and I'll see you next time! 🧡
|
|
||||||
@ -60,8 +60,7 @@ Pumpkin isn't just about the core server anymore. We've got two new exciting rel
|
|||||||
To top it all off, PumpkinMC officially has a new YouTube channel! We'll be posting updates, showcases, and development logs there. Make sure to subscribe at [@PumpkinServer](https://www.youtube.com/@PumpkinServer).
|
To top it all off, PumpkinMC officially has a new YouTube channel! We'll be posting updates, showcases, and development logs there. Make sure to subscribe at [@PumpkinServer](https://www.youtube.com/@PumpkinServer).
|
||||||
|
|
||||||
Check out our latest video below to see some of the new features in action:
|
Check out our latest video below to see some of the new features in action:
|
||||||
|
https://youtu.be/Zz6YbXRX7d8
|
||||||
<Youtube videoId="Zz6YbXRX7d8"></Youtube>
|
|
||||||
|
|
||||||
This video covers several updates to the Pumpkin server over the last two weeks.
|
This video covers several updates to the Pumpkin server over the last two weeks.
|
||||||
|
|
||||||
|
|||||||
@ -1,61 +0,0 @@
|
|||||||
---
|
|
||||||
date: 2026-02-27
|
|
||||||
author:
|
|
||||||
name: RoosterBooster007
|
|
||||||
url: https://github.com/RoosterBooster007
|
|
||||||
title: Update - 27th February 2026
|
|
||||||
---
|
|
||||||
|
|
||||||
### Quality Over Quantity (But Still Plenty!)
|
|
||||||
|
|
||||||
Hey everyone, RB007 here again. If you’ve been watching our GitHub pulse, you might have noticed the numbers looked a little different this week. We merged **32 pull requests**—which, while slightly lower than our usual "40-something" madness, definitely doesn't mean we're slowing down.
|
|
||||||
|
|
||||||
In fact, the "kitchen" is currently overflowing. We have a **massive** number of PRs currently in the works, undergoing heavy review, or being polished to perfection. Sometimes you have to slow down the "merge" button to make sure the big features land softly. That said, what *did* get into the main branch this week is still pretty beefy. Let’s take a look.
|
|
||||||
|
|
||||||
### Smarter Mobs & Complex Commands
|
|
||||||
|
|
||||||
The world of Pumpkin is getting better and more "vanilla" by the second.
|
|
||||||
|
|
||||||
- **Endermen & Pigs**: Purdze is back at it with more AI! Endermen are now teleporting around (watch your eyes) and Pigs have officially joined the livestock roster ([#1579](https://github.com/Pumpkin-MC/Pumpkin/pull/1579), [#1593](https://github.com/Pumpkin-MC/Pumpkin/pull/1593)).
|
|
||||||
- **The Command Overhaul**: Laptop59 has implemented a brand-new command system ([#1681](https://github.com/Pumpkin-MC/Pumpkin/pull/1681)). This is a huge internal shift that allows us to handle the complex, nested arguments you see in vanilla Minecraft. It’s the groundwork for making things like `/execute` feasible to recreate.
|
|
||||||
- **Monitoring Performance**: We’ve added a `/tps` command so you can see exactly how smooth the Rust engine is purring ([#1669](https://github.com/Pumpkin-MC/Pumpkin/pull/1669)).
|
|
||||||
|
|
||||||
### Support for More Java Edition Versions
|
|
||||||
|
|
||||||
We also extended Java Edition protocol support (>=1.21) in [#1435](https://github.com/Pumpkin-MC/Pumpkin/pull/1435), thanks to topi-banana. This required a large refactor for multi-version packet support and advanced remappings.
|
|
||||||
|
|
||||||
### A World of Color (and Language)
|
|
||||||
|
|
||||||
We’ve had a massive surge in international support this week. It is genuinely awesome to see the community making Pumpkin accessible to everyone. We added more support for **German, Dutch, Albanian, Korean, Romanian, and Traditional Chinese** ([#1629](https://github.com/Pumpkin-MC/Pumpkin/pull/1629), [#1728](https://github.com/Pumpkin-MC/Pumpkin/pull/1728), [#1724](https://github.com/Pumpkin-MC/Pumpkin/pull/1724), etc.).
|
|
||||||
|
|
||||||
On the flora side of things:
|
|
||||||
- **Nether**: Crimson and Warped Fungus blocks are now implemented ([#1693](https://github.com/Pumpkin-MC/Pumpkin/pull/1693) - GreenedDev).
|
|
||||||
- **Ocean & More**: Kelp (generation) and Wither Roses are improved ([#1717](https://github.com/Pumpkin-MC/Pumpkin/pull/1717), [#1692](https://github.com/Pumpkin-MC/Pumpkin/pull/1692)).
|
|
||||||
|
|
||||||
### The "Little Things" That Matter
|
|
||||||
|
|
||||||
You know that annoying flicker when you break a block? Or when the sun doesn't quite move right? We spent a lot of time this week on the "feel" of the server:
|
|
||||||
|
|
||||||
- **Attributes & Effects**: I added an entity attribute system and fixed over a dozen status effects. Mobs now have unique health/speed traits, and effects like Invisibility and Glowing actually work ([#1526](https://github.com/Pumpkin-MC/Pumpkin/pull/1526)).
|
|
||||||
- **Visual Polish**: BraveDevelopment fixed the block-break flickering ([#1683](https://github.com/Pumpkin-MC/Pumpkin/pull/1683)), and I pushed a fix for the visual daylight cycle so the sun actually follows the timeline correctly ([#1684](https://github.com/Pumpkin-MC/Pumpkin/pull/1684)).
|
|
||||||
- **Physics Fixes**: Laptop59 made sure falling blocks keep their state (no more weird resets mid-air) and ensured Armor Stands actually respect gravity ([#1757](https://github.com/Pumpkin-MC/Pumpkin/pull/1757), [#1689](https://github.com/Pumpkin-MC/Pumpkin/pull/1689)).
|
|
||||||
- **Better Bed Behavior**: gula00 fixed the obstruction check so it now accurately checks both the head and foot of the bed. They also added a safety guard to ensure that breaking one half of a bed doesn't accidentally "eat" a non-bed block next to it—super helpful for those weird "half-bed" states ([#1696](https://github.com/Pumpkin-MC/Pumpkin/pull/1696)).
|
|
||||||
- **Spectator Logic**: kyotuca made sure spectators can no longer "accidentally" hoover up items like some kind of ghost-vacuum ([#1699](https://github.com/Pumpkin-MC/Pumpkin/pull/1699)).
|
|
||||||
|
|
||||||
### For the Developers: More Events!
|
|
||||||
|
|
||||||
Our plugin API is growing fast. yunuservices added a whole suite of new events for developers to hook into, including **Fishing, Experience Changes, Main Hand Swaps, Item Holding, and Spawn Changes** ([#1654](https://github.com/Pumpkin-MC/Pumpkin/pull/1654), [#1653](https://github.com/Pumpkin-MC/Pumpkin/pull/1653), [#1647](https://github.com/Pumpkin-MC/Pumpkin/pull/1647), etc.). If you’re building on Pumpkin, your toolbox just got a lot bigger. And, it'll continue to grow over the coming weeks as more features and events are added.
|
|
||||||
|
|
||||||
### Smoother Deployments with Pterodactyl
|
|
||||||
|
|
||||||
For those of you hosting Pumpkin on panels like Pterodactyl or Pelican, deployment just got a whole lot smoother thanks to vyPal ([#1498](https://github.com/Pumpkin-MC/Pumpkin/pull/1498)).
|
|
||||||
|
|
||||||
Rust is a powerhouse, but it can be hungry during the compilation phase. We’ve updated our "egg" configuration to recommend 4GB of RAM (up from 2GB) to prevent build failures. We've also added recommendations for CPU limits and refined how Cargo build jobs are handled to make sure your server compiles as fast as possible.
|
|
||||||
|
|
||||||
### Wrapping Up
|
|
||||||
|
|
||||||
While 32 PRs might look like a "quiet" week compared to our usual breakneck speed, the reality is that the team is deep in the trenches on some of the most complex parts of the engine. There is a mountain of code currently being reviewed that we can't wait to show you.
|
|
||||||
|
|
||||||
Thanks for sticking with us and for all the feedback on the Discord. It’s been a blast seeing you test our latest changes. And to anyone who contributed this week: thank you! Y'all are helping push Pumpkin forward. 💕
|
|
||||||
|
|
||||||
Stay tuned for next week!
|
|
||||||
@ -1,53 +0,0 @@
|
|||||||
---
|
|
||||||
date: 2026-03-06
|
|
||||||
author:
|
|
||||||
name: RoosterBooster007
|
|
||||||
url: https://github.com/RoosterBooster007
|
|
||||||
title: Update - 6th March 2026
|
|
||||||
---
|
|
||||||
|
|
||||||
### Stepping Closer to Vanilla
|
|
||||||
|
|
||||||
Hey everyone! It’s RB, back again to showcase some of the cool recent changes to hit Pumpkin. We've been hard at work merging 40+ pull requests this week, and while the numbers are a bit more focused, the impact on gameplay is massive. We are really starting to bridge the gap between our engine and the vanilla Minecraft experience.
|
|
||||||
|
|
||||||
Before we dive into the details, I highly recommend checking out our newest update video. It covers a lot of the changes we've made recently, and it really puts into perspective how fast things are moving. Give it a watch, like, and subscribe!
|
|
||||||
|
|
||||||
<Youtube videoId="GSaDNkqClZ8"></Youtube>
|
|
||||||
|
|
||||||
### Bringing the World to Life
|
|
||||||
|
|
||||||
World generation got a massive boost this week thanks to mtthidoteu. He implemented a brand new system to handle NBT templates for structures ([#1630](https://github.com/Pumpkin-MC/Pumpkin/pull/1630)). This is a huge deal because it makes porting certain structures over from vanilla significantly easier. Using this new system, he immediately added generation for Igloos and Nether Fossils ([#1631](https://github.com/Pumpkin-MC/Pumpkin/pull/1631), [#1632](https://github.com/Pumpkin-MC/Pumpkin/pull/1632)).
|
|
||||||
|
|
||||||
I also wanted to jump in and help with worldgen, so I wrote up the feature generation code for Geodes and Monster Rooms/Dungeons ([#1697](https://github.com/Pumpkin-MC/Pumpkin/pull/1697), [#1748](https://github.com/Pumpkin-MC/Pumpkin/pull/1748)). On top of that, we finally tracked down and fixed that nasty Nether Portal crash ([#1710](https://github.com/Pumpkin-MC/Pumpkin/pull/1710)), so you can safely traverse dimensions again!
|
|
||||||
|
|
||||||
Last but not least, Purdze and Alex added Nether Fortresses into the mix, improving Stronghold generation in the process.
|
|
||||||
|
|
||||||
### Blocks, Blocks, and More Blocks
|
|
||||||
|
|
||||||
GreenedDev was on an absolute roll this week, bringing a ton of new blocks into the fold. He implemented all types of Lanterns, Copper Torches, Spore Blossoms, and Nether Sprouts ([#1779](https://github.com/Pumpkin-MC/Pumpkin/pull/1779), [#1772](https://github.com/Pumpkin-MC/Pumpkin/pull/1772), [#1735](https://github.com/Pumpkin-MC/Pumpkin/pull/1735), [#1736](https://github.com/Pumpkin-MC/Pumpkin/pull/1736)). But he didn't stop at just adding things; he also fixed a slew of block behaviors. For example, conduits will no longer be forced into a waterlogged state out of nowhere, piston break checks are fixed, and torch block-updates are properly aligned ([#1808](https://github.com/Pumpkin-MC/Pumpkin/pull/1808), [#1787](https://github.com/Pumpkin-MC/Pumpkin/pull/1787), [#1778](https://github.com/Pumpkin-MC/Pumpkin/pull/1778)).
|
|
||||||
|
|
||||||
Other contributors made huge strides in world interaction, too. Rotstein007 added vanilla powder snow behavior, meaning you’ll now take freezing damage when submerged—so watch your step ([#1743](https://github.com/Pumpkin-MC/Pumpkin/pull/1743))! LuciCrack introduced Daylight Detectors, making them successfully output a redstone signal based on the time of day ([#1596](https://github.com/Pumpkin-MC/Pumpkin/pull/1596)). Finally, yuminstalljoe fixed tall plants so they properly place their upper halves when planted, and made sure lava correctly flows when placed above a water block ([#1738](https://github.com/Pumpkin-MC/Pumpkin/pull/1738), [#1737](https://github.com/Pumpkin-MC/Pumpkin/pull/1737)).
|
|
||||||
|
|
||||||
### Mechanics and Under-the-Hood Polish
|
|
||||||
|
|
||||||
If you enjoy smacking zombies around, you'll be happy to know that LegendsOfXania added mob sunburn ([#1767](https://github.com/Pumpkin-MC/Pumpkin/pull/1767)). Undead mobs will now rightfully burn to a crisp during the day. Speaking of entities, yuminstalljoe fixed an issue where dying entities weren't ticking for movement, meaning they now take knockback in death as expected (though they still seem to pathfind for those 20 extra ticks), and he aligned entity water velocity with Java Edition ([#1741](https://github.com/Pumpkin-MC/Pumpkin/pull/1741), [#1739](https://github.com/Pumpkin-MC/Pumpkin/pull/1739)).
|
|
||||||
|
|
||||||
We also squashed a few annoying bugs regarding player mechanics. WCBBEX implemented the `natural_regeneration` gamerule check directly into the hunger manager ([#1764](https://github.com/Pumpkin-MC/Pumpkin/pull/1764)). GroobleDierne swept in to fix some boss bar encoding issues alongside a few effects bugs ([#1766](https://github.com/Pumpkin-MC/Pumpkin/pull/1766)), and chocodev11 fixed an annoying bug where using rotation arguments in a `/tp` command would aggressively force you back into the Overworld ([#1690](https://github.com/Pumpkin-MC/Pumpkin/pull/1690)).
|
|
||||||
|
|
||||||
### Expanding the Developer Toolbox
|
|
||||||
|
|
||||||
Yunuservices has been steadily tackling the massive task of implementing Bukkit-style events. This week, we got `PlayerEggThrowEvent`, `BlockGrowEvent` for crops, and `BlockRedstoneEvent` for pressure plates ([#1753](https://github.com/Pumpkin-MC/Pumpkin/pull/1753), [#1752](https://github.com/Pumpkin-MC/Pumpkin/pull/1752), [#1750](https://github.com/Pumpkin-MC/Pumpkin/pull/1750)).
|
|
||||||
|
|
||||||
On the data and documentation side, SomeYellowGuy added wrapping and unwrapping for NBT lists to and from binary ([#1742](https://github.com/Pumpkin-MC/Pumpkin/pull/1742)). HairlessVillager refactored the `PalettedContainer` for better performance and corrected Y-coordinate checks in light propagation ([#1721](https://github.com/Pumpkin-MC/Pumpkin/pull/1721), [#1791](https://github.com/Pumpkin-MC/Pumpkin/pull/1791)). And because good documentation is the lifeblood of open source, illyrius666 added thorough docs to `pumpkin-macros` and `pumpkin-util` ([#1720](https://github.com/Pumpkin-MC/Pumpkin/pull/1720), [#1719](https://github.com/Pumpkin-MC/Pumpkin/pull/1719)).
|
|
||||||
|
|
||||||
### A Global Community
|
|
||||||
|
|
||||||
We continue to get a ton of love from translators! This week, we expanded our `/pumpkin` command support with Plattdüütsch (nds_de), Polish (pl_PL), Breton (brb), Italian (it_it), and Georgian (ka_ge) ([#1763](https://github.com/Pumpkin-MC/Pumpkin/pull/1763), [#1776](https://github.com/Pumpkin-MC/Pumpkin/pull/1776), [#1727](https://github.com/Pumpkin-MC/Pumpkin/pull/1727), [#1718](https://github.com/Pumpkin-MC/Pumpkin/pull/1718), [#1625](https://github.com/Pumpkin-MC/Pumpkin/pull/1625)). While adding translations works fine on GitHub for now, we’re thinking of moving it to a platform like Crowdin for simplicity soon. Stay tuned for updates on that front.
|
|
||||||
|
|
||||||
### Wrapping Up
|
|
||||||
|
|
||||||
Overall, we’re succeeding in our quest to make Pumpkin the best custom Minecraft server software out there. And speaking of a "quest," Pumpkin was recently spotted running natively on a Meta Quest 2, which is absolutely wild and shows off just how flexible and performant this software is... and how creative our community can be!
|
|
||||||
|
|
||||||
I personally love seeing all of your fixes and new features pour in. We’re incredibly grateful to everyone who has contributed to or supported Pumpkin in any way.
|
|
||||||
|
|
||||||
See you next time! Thank you all for making this possible! 🧡
|
|
||||||
@ -1,264 +0,0 @@
|
|||||||
---
|
|
||||||
title: "Update - 11th May 2026: Entities, Bedrock Magic, and World Generation"
|
|
||||||
date: "2026-05-11"
|
|
||||||
author:
|
|
||||||
name: Alexander Medvedev
|
|
||||||
url: https://github.com/Snowiiii
|
|
||||||
description: "A monumental update spanning 207 commits and 101 pull requests, bringing all missing entities, profound Bedrock improvements, an expanded Plugin API, stunning world generation features, and much more."
|
|
||||||
---
|
|
||||||
|
|
||||||
Welcome to one of the most massive Pumpkin update to date! It has been an incredibly busy and productive couple of weeks since our last major check-in at the end of March. The community and the core team have been working in overdrive to bring you a truly monumental drop of new features, deep technical refactors, bug fixes, and under-the-hood magic.
|
|
||||||
|
|
||||||
To put things into perspective, this update comprises a staggering **207 commits** and **101 merged pull requests**. We have fundamentally transformed how the server handles entities, completely overhauled significant portions of our Bedrock edition support, greatly expanded the capabilities of our WASM-based Plugin API, and introduced gorgeous new world generation features.
|
|
||||||
|
|
||||||
Grab a cup of coffee. This is going to be a long read. Let's dive deep into the highlights, the technical details, and everything in between!
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
#### Entity AI
|
|
||||||
|
|
||||||
- **Dragon AI:** The Ender Dragon now has her proper AI logic and fight sequences implemented, making the End a true boss arena.
|
|
||||||
- **Blaze AI:** Blazes now actively track players, float menacingly, and shoot proper fireballs. We implemented both large and small fireball projectile logic.
|
|
||||||
- **Shulker Logic:** Shulkers now properly open, close, and peek out of their shells ([#2061](https://github.com/Pumpkin-MC/Pumpkin/pull/2061)).
|
|
||||||
|
|
||||||
#### Spawning Mechanics: Populating the World
|
|
||||||
|
|
||||||
Previously, entities would only spawn naturally during server ticks. Because natural tick-based spawning is heavily cap-limited for performance reasons, you may have noticed the world feeling a bit sparse. To fix this, we have introduced **initial mob spawning during chunk generation**! Now, as new chunks are generated, they are immediately populated with a healthy number of mobs.
|
|
||||||
|
|
||||||
Alongside this, we implemented comprehensive mob spawning rules. For instance, monsters will properly check light levels and no longer spawn in well-lit areas, ensuring your torch-lit bases remain safe from the new influx of creatures.
|
|
||||||
|
|
||||||
#### Combat, Interaction, and Mechanics
|
|
||||||
|
|
||||||
We have refined the core mechanics of how entities exist and suffer:
|
|
||||||
|
|
||||||
- **Sun Damage:** Undead mobs (Zombies, Skeletons, Phantoms) now properly burn in daylight. Instead of hardcoding this, we've implemented this cleanly using the `tag::EntityType::MINECRAFT_BURN_IN_DAYLIGHT` tag, making it future-proof for custom entities.
|
|
||||||
- **Drowning and Breath:** We completely rewrote the air depletion, regeneration, and drowning logic. It is now deterministic and clear. Air supply is properly clamped, and dead players no longer process breath ticks ([#2044](https://github.com/Pumpkin-MC/Pumpkin/pull/2044)).
|
|
||||||
- **Elytra Landing:** If you are flying around with an Elytra, you can finally land properly without face-planting into the ground and taking unnecessary kinetic damage ([#1928](https://github.com/Pumpkin-MC/Pumpkin/pull/1928)).
|
|
||||||
- **Experience Orbs:** Entities finally drop experience orbs when defeated, allowing you to mend your gear and enchant your weapons.
|
|
||||||
- **Pathfinding Jump Fixes:** Mobs will no longer get stuck on simple blocks. The pathfinding system has been heavily optimized and tweaked to ensure mobs can navigate terrain smoothly ([#1794](https://github.com/Pumpkin-MC/Pumpkin/pull/1794)).
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Plugin API & WASM Power: The Developer's Dream
|
|
||||||
|
|
||||||
We have always maintained that Pumpkin should be the ultimate playground for developers. Modularity is at our core. In this update, we poured a ton of work into the **Plugin API**, taking our WASM-based system from a promising experiment to a production-ready powerhouse.
|
|
||||||
|
|
||||||
#### Multi-Language Bindings
|
|
||||||
|
|
||||||
Since our Plugin API is built on WebAssembly and WIT (WebAssembly Interface Type), you are no longer restricted to just one language. We have added extensive language bindings! Currently, you can write Pumpkin plugins natively in several languages.
|
|
||||||
|
|
||||||
Supported languages include:
|
|
||||||
|
|
||||||
- [Rust](https://github.com/Pumpkin-MC/Pumpkin)
|
|
||||||
- [C/C++](https://github.com/Pumpkin-MC/pumpkin-api-c)
|
|
||||||
- [Go](https://github.com/Pumpkin-MC/pumpkin-api-go)
|
|
||||||
- [Python](https://github.com/Pumpkin-MC/pumpkin-python)
|
|
||||||
- [C#](https://github.com/Pumpkin-MC/pumpkin-api-cs)
|
|
||||||
|
|
||||||
This breaks down the barriers to entry for server development, and we have many more language bindings planned for the future!
|
|
||||||
|
|
||||||
#### Fine-Grained Permissions
|
|
||||||
|
|
||||||
Security and control are paramount for server administrators. We introduced a comprehensive, fine-grained permission system natively into the Plugin API.
|
|
||||||
|
|
||||||
- You can now require permission confirmation during plugin loading.
|
|
||||||
- Using the new WIT interface, plugins can dynamically call `set-permission`, `unset-permission`, and `has-permission-set` directly on player objects ([#2059](https://github.com/Pumpkin-MC/Pumpkin/pull/2059)).
|
|
||||||
|
|
||||||
#### Hot Reloading
|
|
||||||
|
|
||||||
Developer iteration speed is critical. We added **hot-reloading** support for plugins! You can now compile your WASM module, drop it into the folder, and see your changes instantly without having to restart the entire server.
|
|
||||||
|
|
||||||
#### Expanded Event System
|
|
||||||
|
|
||||||
We drastically expanded the WIT API to expose vital player and server events, giving your plugins unprecedented hooks into the game loop:
|
|
||||||
|
|
||||||
- **Inventory Events:** Track exactly what players are doing with `inventory_interact` and `inventory_close`.
|
|
||||||
- **Movement & Interaction:** Hook into `PlayerToggleFlightEvent` and `PlayerInteractUnknownEntityEvent` ([#1998](https://github.com/Pumpkin-MC/Pumpkin/pull/1998)).
|
|
||||||
- **Entity Flags:** We exposed a myriad of internal entity flags to the WASM host, allowing deep manipulation of entity states.
|
|
||||||
|
|
||||||
#### GUI and Visual Hooks
|
|
||||||
|
|
||||||
Plugins aren't just for background logic; they need to show things to the player.
|
|
||||||
|
|
||||||
- **Bossbars:** Full support for creating, updating, and removing custom bossbars.
|
|
||||||
- **Tablist Manipulation:** You can now set custom tab list headers and footers, as well as override custom tablist names for individual players ([#2077](https://github.com/Pumpkin-MC/Pumpkin/pull/2077)).
|
|
||||||
- **Dependencies:** We added native support for plugin dependencies, ensuring your complex plugin ecosystems load in the correct order.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Bedrock Edition
|
|
||||||
|
|
||||||
Cross-play is a first-class citizen in Pumpkin. Ensuring our Bedrock implementation keeps pace with Java is a massive priority, and this update proves it.
|
|
||||||
|
|
||||||
#### Protocol Updates & Stability
|
|
||||||
|
|
||||||
- **Latest Versions:** We updated the Bedrock protocol to support versions **26.10** ([#2067](https://github.com/Pumpkin-MC/Pumpkin/pull/2067)) and **26.20**, ensuring compatibility with the newest client updates.
|
|
||||||
- **zLib Compression:** We implemented proper zLib packet compression for Bedrock connections. This drastically reduces bandwidth usage and makes connections faster and much more stable.
|
|
||||||
- **RakNet Reliability:** We finalized the RakNet Acks/Nacks logic, solving a huge class of connection drops and packet loss issues.
|
|
||||||
|
|
||||||
#### Feature Parity
|
|
||||||
|
|
||||||
- **Resource Packs:** Bedrock players can now enjoy full resource pack support directly from the server. The race conditions during login have been squashed.
|
|
||||||
- **Command Suggestions:** Typing commands on a controller or touch screen is notoriously painful. We have fully implemented Bedrock command suggestions, feeding the client real-time auto-completion data ([#2096](https://github.com/Pumpkin-MC/Pumpkin/pull/2096)).
|
|
||||||
- **Translations:** We merged tens of thousands of lines of translation data (`en_us_bedrock.lang`). Bedrock clients now get localized text, block names, and system messages perfectly aligned with their Java counterparts.
|
|
||||||
- **Visual Polish:** Health, Title, and Gamemode packets are now properly dispatched. When your gamemode changes, your HUD reacts instantly.
|
|
||||||
- **Block Breaking:** Bedrock block breaking mechanics have been refined and synchronized with the server's authoritative state.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### World Generation
|
|
||||||
|
|
||||||
The world of Pumpkin is looking more beautiful, natural, and complex. We've introduced major architectural changes to how chunks are formed and decorated.
|
|
||||||
|
|
||||||
#### The Carver System & Chunk Blender
|
|
||||||
|
|
||||||
- **Carvers:** Caves and canyons are no longer just accidental air pockets. We implemented a dedicated Carver system. If you venture into the world, you will find sprawling, interconnected cave systems and deep ravines carved seamlessly through the terrain.
|
|
||||||
- **Chunk Blender:** We added a brand new Chunk Blender. When terrain generation algorithms change, or when different biomes meet, the blender ensures smooth, natural transitions rather than jarring cliffs.
|
|
||||||
|
|
||||||
#### New Features
|
|
||||||
|
|
||||||
We added dozens of new configured features to the chunk generation pipeline:
|
|
||||||
|
|
||||||
- **The Deep Dark:** Massive, sprawling **Sculk patches** now generate deep underground.
|
|
||||||
- **The Nether:** **Twisting Vines** ([#1894](https://github.com/Pumpkin-MC/Pumpkin/pull/1894)), **Weeping Vines** ([#1892](https://github.com/Pumpkin-MC/Pumpkin/pull/1892)), and **Basalt Columns** ([#1884](https://github.com/Pumpkin-MC/Pumpkin/pull/1884)) bring the Nether biomes to life.
|
|
||||||
- **The Frozen Wastes:** **Icebergs** ([#1890](https://github.com/Pumpkin-MC/Pumpkin/pull/1890)), **Blue Ice** formations, and **Snow & Ice** surface rules ([#1886](https://github.com/Pumpkin-MC/Pumpkin/pull/1886)) are now fully implemented.
|
|
||||||
- **The Lush Terrain:** **Root Systems**, **Underground Lakes**, **Disk features** ([#1879](https://github.com/Pumpkin-MC/Pumpkin/pull/1879)), **Small and Big Dripleaf** ([#2007](https://github.com/Pumpkin-MC/Pumpkin/pull/2007), [#2009](https://github.com/Pumpkin-MC/Pumpkin/pull/2009)), and **Chorus Blocks** in the End ([#2021](https://github.com/Pumpkin-MC/Pumpkin/pull/2021)).
|
|
||||||
- **Structures:** We laid the groundwork for Jungle Temples ([#2054](https://github.com/Pumpkin-MC/Pumpkin/pull/2054)), End Islands ([#2023](https://github.com/Pumpkin-MC/Pumpkin/pull/2023)), and improved Stronghold references.
|
|
||||||
|
|
||||||
#### Under the Hood: Speed and Safety
|
|
||||||
|
|
||||||
Chunk generation is computationally expensive. We spent significant time optimizing it:
|
|
||||||
|
|
||||||
- We eliminated nasty DAG (Directed Acyclic Graph) deadlocks.
|
|
||||||
- We massively optimized structure references from O(N^2) to O(1), and implemented a global stronghold cache ([#1888](https://github.com/Pumpkin-MC/Pumpkin/pull/1888)).
|
|
||||||
- Height maps have been fixed and optimized using proper bit storage.
|
|
||||||
- We flattened compiled surface rules to avoid recursion at runtime, boosting performance.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Blocks, Items, and Inventories: Crafting the Future
|
|
||||||
|
|
||||||
Combat, exploration, and building got a serious boost with the implementation of complex interactive blocks and functional items.
|
|
||||||
|
|
||||||
#### Weapons and Tools
|
|
||||||
|
|
||||||
- **Crossbow:** Fully implemented, complete with proper loading states, firing mechanics, and arrow velocity calculations.
|
|
||||||
- **Shields & Mace:** You can now block incoming attacks with Shields and crush your foes with the Mace.
|
|
||||||
- **Fishing Rod:** Want to relax? Grab the new Fishing Rod. The fishing bobber projectile logic, water detection, and reeling mechanics are all in.
|
|
||||||
- **Maps:** Map creation is fully supported. We implemented the complex `map_item_data` packets so you can chart your world.
|
|
||||||
|
|
||||||
#### Interactive Blocks & Screens
|
|
||||||
|
|
||||||
We implemented a whole suite of interactive blocks with their accompanying screen handlers:
|
|
||||||
|
|
||||||
- **Enchanting Table:** Added Enchanting Table possibility.
|
|
||||||
- **Anvil:** Added Anvil functionality.
|
|
||||||
- **Stonecutter:** Added Stonecutter functionality.
|
|
||||||
- **Lectern:** Added Lectern functionality.
|
|
||||||
- **Dragon Egg:** Added functional Dragon Egg.
|
|
||||||
|
|
||||||
#### The Economy: Villager Trading
|
|
||||||
|
|
||||||
Villager trading is finally here! We've implemented the Merchant screen handler. You can now interact with villagers, view their generated trades, and exchange your hard-earned emeralds for valuable goods.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Commands, Parsing, and Server Internals
|
|
||||||
|
|
||||||
For the server administrators and command block wizards, the backend has never been stronger.
|
|
||||||
|
|
||||||
#### The SNBT Parser
|
|
||||||
|
|
||||||
We built a powerful, entirely new **SNBT (Stringified NBT) parser** from scratch ([#2088](https://github.com/Pumpkin-MC/Pumpkin/pull/2088)). This custom parser handles complex data tags with incredible reliability, meaning commands that rely on NBT data are now rock solid.
|
|
||||||
|
|
||||||
#### Argument Types Galore
|
|
||||||
|
|
||||||
To support the new commands, we implemented a vast array of argument types:
|
|
||||||
|
|
||||||
- **Entity Selectors:** Full support for `@a`, `@p`, `@e`, `@r`, and `@s` with all their complex filtering options ([#1925](https://github.com/Pumpkin-MC/Pumpkin/pull/1925)).
|
|
||||||
- **Positional Data:** `Vec3` ([#1943](https://github.com/Pumpkin-MC/Pumpkin/pull/1943)), `BlockPos` ([#1994](https://github.com/Pumpkin-MC/Pumpkin/pull/1994)), and local coordinate resolution (`^ ^ ^`).
|
|
||||||
- **Time:** Proper parsing for time strings (e.g., `1d`, `20t`) ([#1941](https://github.com/Pumpkin-MC/Pumpkin/pull/1941)).
|
|
||||||
- **Suggestion Providers:** Greatly improved command auto-completions using our new suggestion providers infrastructure ([#2004](https://github.com/Pumpkin-MC/Pumpkin/pull/2004)).
|
|
||||||
|
|
||||||
#### Infrastructure
|
|
||||||
|
|
||||||
- **Crash Reports:** When things go wrong, they now go wrong gracefully. We added comprehensive crash reports with panic locations and a graceful shutdown sequence ([#1790](https://github.com/Pumpkin-MC/Pumpkin/pull/1790), [#2035](https://github.com/Pumpkin-MC/Pumpkin/pull/2035)).
|
|
||||||
- **The .pump Format:** We introduced the rudimentary `.pump` chunk format, paving the way for faster, custom chunk serialization optimized for Pumpkin.
|
|
||||||
- **Cross-Version Sound IDs:** We implemented a massive lookup table for cross-version sound ID remapping, ensuring clients on older versions still hear the correct sounds ([#2103](https://github.com/Pumpkin-MC/Pumpkin/pull/2103)).
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### The Exhaustive List: Smaller Changes and Fixes
|
|
||||||
|
|
||||||
Because an update of this magnitude is built on hundreds of tiny improvements, here is a massive list of the smaller things that made it into this release:
|
|
||||||
|
|
||||||
- Added base implementation for plugin command list in help menu ([#2076](https://github.com/Pumpkin-MC/Pumpkin/pull/2076)).
|
|
||||||
- Added missing translation files for `lzh` (Literary Chinese) ([#2078](https://github.com/Pumpkin-MC/Pumpkin/pull/2078)).
|
|
||||||
- Updated crates: `crate-ci/typos` bumped to 1.46.1 ([#2125](https://github.com/Pumpkin-MC/Pumpkin/pull/2125)).
|
|
||||||
- Fixed tall plant block update checks ([#2091](https://github.com/Pumpkin-MC/Pumpkin/pull/2091)).
|
|
||||||
- Fixed packet codegen and exported more WIT interfaces ([#2120](https://github.com/Pumpkin-MC/Pumpkin/pull/2120)).
|
|
||||||
- Implemented cross-version sound ID remapping for older clients ([#2103](https://github.com/Pumpkin-MC/Pumpkin/pull/2103)).
|
|
||||||
- Fixed clippy warnings across `pumpkin-data` and generated files ([#2072](https://github.com/Pumpkin-MC/Pumpkin/pull/2072)).
|
|
||||||
- Fixed drowning damage, ensuring air supply decreases correctly and stops when dead ([#2044](https://github.com/Pumpkin-MC/Pumpkin/pull/2044)).
|
|
||||||
- Implemented entity's nearest facing directions using existing logic ([#2039](https://github.com/Pumpkin-MC/Pumpkin/pull/2039)).
|
|
||||||
- Set custom tablist names for players via the Plugin API ([#2077](https://github.com/Pumpkin-MC/Pumpkin/pull/2077)).
|
|
||||||
- Truncated query packet buffers to actual UDP packet length to fix network edge cases ([#2075](https://github.com/Pumpkin-MC/Pumpkin/pull/2075)).
|
|
||||||
- Fixed Jungle Tree trunk generation rules ([#2060](https://github.com/Pumpkin-MC/Pumpkin/pull/2060)).
|
|
||||||
- Exposed `PlayerInteractUnknownEntityEvent` and `PlayerToggleFlightEvent` to WASM ([#1998](https://github.com/Pumpkin-MC/Pumpkin/pull/1998)).
|
|
||||||
- Implemented Shulker entity AI ([#2061](https://github.com/Pumpkin-MC/Pumpkin/pull/2061)).
|
|
||||||
- Added Small Dripleaf ([#2009](https://github.com/Pumpkin-MC/Pumpkin/pull/2009)), Big Dripleaf, and Big Dripleaf Stem blocks ([#2007](https://github.com/Pumpkin-MC/Pumpkin/pull/2007)).
|
|
||||||
- Added entity anchor and rotation argument types to the command parser ([#2038](https://github.com/Pumpkin-MC/Pumpkin/pull/2038)).
|
|
||||||
- Replaced codec and map codec structs with `Encode` and `Decode` traits ([#2051](https://github.com/Pumpkin-MC/Pumpkin/pull/2051)).
|
|
||||||
- Fixed method chaining inside the Plugin API ([#2052](https://github.com/Pumpkin-MC/Pumpkin/pull/2052)).
|
|
||||||
- Added Jungle Temple structure layouts ([#2054](https://github.com/Pumpkin-MC/Pumpkin/pull/2054)).
|
|
||||||
- Added `StoredEnchantments` to data components ([#2042](https://github.com/Pumpkin-MC/Pumpkin/pull/2042)).
|
|
||||||
- Enforced a 256-character limit on UTF-16 characters instead of bytes for text inputs ([#2003](https://github.com/Pumpkin-MC/Pumpkin/pull/2003)).
|
|
||||||
- Reworked the versioning logic in the WASM plugin loader ([#2046](https://github.com/Pumpkin-MC/Pumpkin/pull/2046)).
|
|
||||||
- Added the Identifier argument type ([#2000](https://github.com/Pumpkin-MC/Pumpkin/pull/2000)).
|
|
||||||
- Fixed recipe packets for clients older than version 26 ([#2019](https://github.com/Pumpkin-MC/Pumpkin/pull/2019)).
|
|
||||||
- Fixed ladder placement block updates ([#2030](https://github.com/Pumpkin-MC/Pumpkin/pull/2030)).
|
|
||||||
- Added (small) End Island features ([#2023](https://github.com/Pumpkin-MC/Pumpkin/pull/2023)).
|
|
||||||
- Added Chorus blocks and their respective features ([#2021](https://github.com/Pumpkin-MC/Pumpkin/pull/2021)).
|
|
||||||
- Added Iceberg ([#1890](https://github.com/Pumpkin-MC/Pumpkin/pull/1890)), Ice Spike ([#1887](https://github.com/Pumpkin-MC/Pumpkin/pull/1887)), Snow and Ice ([#1886](https://github.com/Pumpkin-MC/Pumpkin/pull/1886)), and Forest Rock features ([#1885](https://github.com/Pumpkin-MC/Pumpkin/pull/1885)).
|
|
||||||
- Documented the `pumpkin-inventory` crate ([#1993](https://github.com/Pumpkin-MC/Pumpkin/pull/1993)).
|
|
||||||
- Implemented block pos argument type and fixed local coordinate resolution ([#1994](https://github.com/Pumpkin-MC/Pumpkin/pull/1994)).
|
|
||||||
- Fixed the empty command kick bug ([#1814](https://github.com/Pumpkin-MC/Pumpkin/pull/1814)).
|
|
||||||
- Implemented player teleportation and expanded `get-rotation` into two distinct methods ([#1986](https://github.com/Pumpkin-MC/Pumpkin/pull/1986)).
|
|
||||||
- Consolidated hurt sound parity for slimes and shared dispatch families ([#1935](https://github.com/Pumpkin-MC/Pumpkin/pull/1935)).
|
|
||||||
- Fixed a bug where cancelled move events would kick the player ([#1978](https://github.com/Pumpkin-MC/Pumpkin/pull/1978)).
|
|
||||||
- Fixed Redstone Wire block updates ([#1984](https://github.com/Pumpkin-MC/Pumpkin/pull/1984)).
|
|
||||||
- Fixed Nether noise sampling logic ([#1982](https://github.com/Pumpkin-MC/Pumpkin/pull/1982), [#1983](https://github.com/Pumpkin-MC/Pumpkin/pull/1983)).
|
|
||||||
- Implemented the `ConsumedArgs::get_value` trait for WASM plugin commands ([#1979](https://github.com/Pumpkin-MC/Pumpkin/pull/1979)).
|
|
||||||
- Implemented Bows and Arrows mechanics ([#1594](https://github.com/Pumpkin-MC/Pumpkin/pull/1594)).
|
|
||||||
- Added the Golden Dandelion block ([#1964](https://github.com/Pumpkin-MC/Pumpkin/pull/1964)).
|
|
||||||
- Fixed a major Piston crash ([#1970](https://github.com/Pumpkin-MC/Pumpkin/pull/1970)).
|
|
||||||
- Implemented range argument types for commands ([#1969](https://github.com/Pumpkin-MC/Pumpkin/pull/1969)).
|
|
||||||
- Optimized the pathfinding system drastically ([#1794](https://github.com/Pumpkin-MC/Pumpkin/pull/1794)).
|
|
||||||
- Implemented the `Vec3` argument type ([#1943](https://github.com/Pumpkin-MC/Pumpkin/pull/1943)).
|
|
||||||
- Added `register_permission_or_panic` helper methods for plugins ([#1948](https://github.com/Pumpkin-MC/Pumpkin/pull/1948)).
|
|
||||||
- Server console now uses local time instead of UTC ([#1956](https://github.com/Pumpkin-MC/Pumpkin/pull/1956)).
|
|
||||||
- Fixed `get_data_folder()` returning the wrong path in the Plugin API ([#1961](https://github.com/Pumpkin-MC/Pumpkin/pull/1961)).
|
|
||||||
- Implemented the Cactus Flower Block ([#1954](https://github.com/Pumpkin-MC/Pumpkin/pull/1954)).
|
|
||||||
- Fixed offline player support for commands utilizing the usercache ([#1793](https://github.com/Pumpkin-MC/Pumpkin/pull/1793)).
|
|
||||||
- Preserved the lit state when adding candles to an already lit candle ([#1936](https://github.com/Pumpkin-MC/Pumpkin/pull/1936)).
|
|
||||||
- Implemented Weeping Vines block ([#1892](https://github.com/Pumpkin-MC/Pumpkin/pull/1892)).
|
|
||||||
- Added "either" codecs to the protocol parser ([#1900](https://github.com/Pumpkin-MC/Pumpkin/pull/1900)).
|
|
||||||
- Expanded the player WIT API significantly ([#1921](https://github.com/Pumpkin-MC/Pumpkin/pull/1921)).
|
|
||||||
- Added missing licenses to all `Cargo.toml` files ([#1927](https://github.com/Pumpkin-MC/Pumpkin/pull/1927)).
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Support Development
|
|
||||||
|
|
||||||
We have also added a brand new [Donate page](https://pumpkinmc.org/donate/)! This is now the preferred way to support the project. Donating through this new page guarantees there is no USD to EUR conversion loss, meaning more of your contribution goes directly towards development. If you or your company would like to help us keep pushing out massive updates like this, please consider making a donation.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
That wraps up this update. The volume of changes in this release is a testament to the dedication of our contributors and community.
|
|
||||||
|
|
||||||
Stay tuned for more updates.
|
|
||||||
|
|
||||||
### Join the Team
|
|
||||||
|
|
||||||
We are currently looking for someone to help us make Pumpkin weekly or monthly update videos! If you are interested in creating content and helping showcase our progress, please let us know in our Discord server.
|
|
||||||
|
|
||||||
@ -2,46 +2,21 @@ import tailwindcss from "@tailwindcss/vite";
|
|||||||
|
|
||||||
// https://nuxt.com/docs/api/configuration/nuxt-config
|
// https://nuxt.com/docs/api/configuration/nuxt-config
|
||||||
export default defineNuxtConfig({
|
export default defineNuxtConfig({
|
||||||
modules: ["@nuxtjs/color-mode", "@nuxt/content", "@nuxt/fonts", "@nuxt/image", "@nuxt/icon"],
|
modules: ["@nuxt/content", "@nuxt/fonts", "@nuxt/image", "@nuxt/icon"],
|
||||||
colorMode: {
|
|
||||||
classSuffix: "",
|
|
||||||
preference: "system",
|
|
||||||
fallback: "dark",
|
|
||||||
},
|
|
||||||
devtools: { enabled: true },
|
devtools: { enabled: true },
|
||||||
compatibilityDate: "2024-04-03",
|
compatibilityDate: "2024-04-03",
|
||||||
css: ["~/assets/css/main.css"],
|
css: ["./assets/css/main.css"],
|
||||||
vite: {
|
vite: {
|
||||||
plugins: [tailwindcss()],
|
plugins: [tailwindcss()],
|
||||||
},
|
},
|
||||||
runtimeConfig: {
|
|
||||||
public: {
|
|
||||||
siteUrl: 'https://blog.pumpkinmc.org',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
app: {
|
app: {
|
||||||
head: {
|
head: {
|
||||||
titleTemplate: '%s | Pumpkin Blog',
|
|
||||||
meta: [
|
|
||||||
{ charset: 'utf-8' },
|
|
||||||
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
|
|
||||||
{ name: 'description', content: 'Thoughts, updates, and more from Pumpkin-MC.' },
|
|
||||||
{ property: 'og:site_name', content: 'Pumpkin Blog' },
|
|
||||||
{ name: 'twitter:card', content: 'summary_large_image' },
|
|
||||||
// any other site‑wide defaults
|
|
||||||
],
|
|
||||||
link: [
|
link: [
|
||||||
{
|
{
|
||||||
rel: "icon",
|
rel: "icon",
|
||||||
type: "image/svg+xml",
|
type: "image/svg+xml",
|
||||||
href: "/images/icon.svg",
|
href: "/images/icon.svg",
|
||||||
},
|
},
|
||||||
{
|
|
||||||
rel: "alternate",
|
|
||||||
type: "application/rss+xml",
|
|
||||||
title: "Pumpkin Blog RSS Feed",
|
|
||||||
href: "/feed.xml",
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -58,7 +33,7 @@ export default defineNuxtConfig({
|
|||||||
prerender: {
|
prerender: {
|
||||||
ignore: ["/developers", "/contributors", "/download"],
|
ignore: ["/developers", "/contributors", "/download"],
|
||||||
crawlLinks: true,
|
crawlLinks: true,
|
||||||
routes: ["/", "/feed.xml"],
|
routes: ["/"],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
9710
package-lock.json
generated
9710
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
25
package.json
25
package.json
@ -9,21 +9,18 @@
|
|||||||
"preview": "nuxt preview"
|
"preview": "nuxt preview"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@nuxt/content": "^3.16.1",
|
"@nuxt/content": "^3.11.0",
|
||||||
"@nuxt/fonts": "^0.14.0",
|
"@nuxt/fonts": "^0.13.0",
|
||||||
"@nuxt/icon": "^2.5.1",
|
"@nuxt/icon": "^2.2.1",
|
||||||
"@nuxt/image": "^2.1.0",
|
"@nuxt/image": "^2.0.0",
|
||||||
"@nuxtjs/color-mode": "^4.0.1",
|
"@tailwindcss/vite": "^4.1.18",
|
||||||
"@tailwindcss/vite": "^4.3.3",
|
"better-sqlite3": "^12.6.2",
|
||||||
"better-sqlite3": "^13.0.3",
|
"nuxt": "^4.3.0",
|
||||||
"feed": "^6.0.0",
|
"tailwindcss": "^4.1.18",
|
||||||
"nuxt": "^4.5.2",
|
"ufo": "^1.6.3",
|
||||||
"or": "^0.2.0",
|
"zod": "^4.3.6"
|
||||||
"tailwindcss": "^4.3.3",
|
|
||||||
"ufo": "^1.6.4",
|
|
||||||
"zod": "^4.6.5"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@tailwindcss/typography": "^0.5.20"
|
"@tailwindcss/typography": "^0.5.19"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 202 KiB |
@ -1,34 +0,0 @@
|
|||||||
import { Feed } from "feed";
|
|
||||||
|
|
||||||
export default defineEventHandler(async (event) => {
|
|
||||||
const { siteUrl } = useRuntimeConfig(event).public;
|
|
||||||
const site = new URL(siteUrl);
|
|
||||||
const feedUrl = new URL("/feed.xml", site).href;
|
|
||||||
const posts = await queryCollection(event, "blog")
|
|
||||||
.select("title", "description", "date", "path")
|
|
||||||
.where("path", "<>", "/")
|
|
||||||
.order("date", "DESC")
|
|
||||||
.all();
|
|
||||||
const updated = posts[0] ? new Date(posts[0].date) : new Date();
|
|
||||||
const feed = new Feed({
|
|
||||||
title: "Pumpkin Blog",
|
|
||||||
description: "Thoughts, updates, and more from Pumpkin-MC.",
|
|
||||||
id: site.href,
|
|
||||||
link: site.href,
|
|
||||||
updated,
|
|
||||||
feedLinks: { rss: feedUrl },
|
|
||||||
});
|
|
||||||
|
|
||||||
for (const post of posts) {
|
|
||||||
feed.addItem({
|
|
||||||
title: post.title,
|
|
||||||
id: new URL(post.path, site).href,
|
|
||||||
link: new URL(post.path, site).href,
|
|
||||||
description: post.description,
|
|
||||||
date: new Date(post.date),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
setResponseHeader(event, "content-type", "application/rss+xml; charset=utf-8");
|
|
||||||
return feed.rss2();
|
|
||||||
});
|
|
||||||
@ -1,3 +0,0 @@
|
|||||||
{
|
|
||||||
"extends": "../.nuxt/tsconfig.server.json"
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue
Block a user