From 14d61a32b4b4e8f414ba4be749ef28bfa280b64b Mon Sep 17 00:00:00 2001 From: smell-of-curry <75345244+smell-of-curry@users.noreply.github.com> Date: Sun, 21 Jun 2026 22:28:22 -0400 Subject: [PATCH 1/3] leveldat/data.go: Add 1.26 editor level.dat fields Worlds opened in Bedrock 1.26.x editor can write allowAnonymousBlockDropsInEditorWorlds, playerwaypoints, and serverEditorConnectionPolicy into level.dat. Dragonfly's strict NBT decoder rejected these unknown tags and failed to open the world. --- server/world/mcdb/leveldat/data.go | 3 +++ server/world/mcdb/leveldat/data_test.go | 33 +++++++++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 server/world/mcdb/leveldat/data_test.go diff --git a/server/world/mcdb/leveldat/data.go b/server/world/mcdb/leveldat/data.go index 05fd50744..47ac35c2c 100644 --- a/server/world/mcdb/leveldat/data.go +++ b/server/world/mcdb/leveldat/data.go @@ -151,6 +151,9 @@ type Data struct { HasUncompleteWorldFileOnDisk bool `nbt:"HasUncompleteWorldFileOnDisk"` PlayerHasDied bool `nbt:"PlayerHasDied"` UseAllowList bool `nbt:"UseAllowList"` + AllowAnonymousBlockDropsInEditorWorlds bool `nbt:"allowAnonymousBlockDropsInEditorWorlds"` + PlayerWaypoints int32 `nbt:"playerwaypoints"` + ServerEditorConnectionPolicy int32 `nbt:"serverEditorConnectionPolicy"` } // FillDefault fills out d with all the default level.dat values. diff --git a/server/world/mcdb/leveldat/data_test.go b/server/world/mcdb/leveldat/data_test.go new file mode 100644 index 000000000..219fee75b --- /dev/null +++ b/server/world/mcdb/leveldat/data_test.go @@ -0,0 +1,33 @@ +package leveldat + +import ( + "testing" + + "github.com/sandertv/gophertunnel/minecraft/nbt" +) + +func TestDataUnmarshalEditorWorldTags(t *testing.T) { + payload, err := nbt.MarshalEncoding(map[string]any{ + "LevelName": "World", + "allowAnonymousBlockDropsInEditorWorlds": true, + "playerwaypoints": int32(2), + "serverEditorConnectionPolicy": int32(1), + }, nbt.LittleEndian) + if err != nil { + t.Fatalf("marshal fixture: %v", err) + } + + var got Data + if err = nbt.UnmarshalEncoding(payload, &got, nbt.LittleEndian); err != nil { + t.Fatalf("unmarshal data: %v", err) + } + if !got.AllowAnonymousBlockDropsInEditorWorlds { + t.Fatal("expected allowAnonymousBlockDropsInEditorWorlds=true") + } + if got.PlayerWaypoints != 2 { + t.Fatalf("playerwaypoints: got %d, want 2", got.PlayerWaypoints) + } + if got.ServerEditorConnectionPolicy != 1 { + t.Fatalf("serverEditorConnectionPolicy: got %d, want 1", got.ServerEditorConnectionPolicy) + } +} From a08a249ff3d8be5e51670e2ff70ae33a6dcf69a7 Mon Sep 17 00:00:00 2001 From: Smell of curry <75345244+smell-of-curry@users.noreply.github.com> Date: Sun, 21 Jun 2026 22:30:03 -0400 Subject: [PATCH 2/3] Delete server/world/mcdb/leveldat/data_test.go --- server/world/mcdb/leveldat/data_test.go | 33 ------------------------- 1 file changed, 33 deletions(-) delete mode 100644 server/world/mcdb/leveldat/data_test.go diff --git a/server/world/mcdb/leveldat/data_test.go b/server/world/mcdb/leveldat/data_test.go deleted file mode 100644 index 219fee75b..000000000 --- a/server/world/mcdb/leveldat/data_test.go +++ /dev/null @@ -1,33 +0,0 @@ -package leveldat - -import ( - "testing" - - "github.com/sandertv/gophertunnel/minecraft/nbt" -) - -func TestDataUnmarshalEditorWorldTags(t *testing.T) { - payload, err := nbt.MarshalEncoding(map[string]any{ - "LevelName": "World", - "allowAnonymousBlockDropsInEditorWorlds": true, - "playerwaypoints": int32(2), - "serverEditorConnectionPolicy": int32(1), - }, nbt.LittleEndian) - if err != nil { - t.Fatalf("marshal fixture: %v", err) - } - - var got Data - if err = nbt.UnmarshalEncoding(payload, &got, nbt.LittleEndian); err != nil { - t.Fatalf("unmarshal data: %v", err) - } - if !got.AllowAnonymousBlockDropsInEditorWorlds { - t.Fatal("expected allowAnonymousBlockDropsInEditorWorlds=true") - } - if got.PlayerWaypoints != 2 { - t.Fatalf("playerwaypoints: got %d, want 2", got.PlayerWaypoints) - } - if got.ServerEditorConnectionPolicy != 1 { - t.Fatalf("serverEditorConnectionPolicy: got %d, want 1", got.ServerEditorConnectionPolicy) - } -} From 25cfe26fc1e48ab5ab46635a77a45f0e20408a52 Mon Sep 17 00:00:00 2001 From: smell-of-curry <75345244+smell-of-curry@users.noreply.github.com> Date: Tue, 23 Jun 2026 21:25:42 -0400 Subject: [PATCH 3/3] go fmt server/world/mcdb/leveldat/data.go Co-authored-by: Cursor --- server/world/mcdb/leveldat/data.go | 160 ++++++++++++++--------------- 1 file changed, 80 insertions(+), 80 deletions(-) diff --git a/server/world/mcdb/leveldat/data.go b/server/world/mcdb/leveldat/data.go index 47ac35c2c..68f45038c 100644 --- a/server/world/mcdb/leveldat/data.go +++ b/server/world/mcdb/leveldat/data.go @@ -74,86 +74,86 @@ type Data struct { WalkSpeed float32 `nbt:"walkSpeed"` VerticalFlySpeed float32 `nbt:"verticalFlySpeed"` } `nbt:"abilities"` - BonusChestEnabled bool `nbt:"bonusChestEnabled"` - BonusChestSpawned bool `nbt:"bonusChestSpawned"` - CommandBlockOutput bool `nbt:"commandblockoutput"` - CommandBlocksEnabled bool `nbt:"commandblocksenabled"` - CommandsEnabled bool `nbt:"commandsEnabled"` - CurrentTick int64 `nbt:"currentTick"` - DoDayLightCycle bool `nbt:"dodaylightcycle"` - DoEntityDrops bool `nbt:"doentitydrops"` - DoFireTick bool `nbt:"dofiretick"` - DoImmediateRespawn bool `nbt:"doimmediaterespawn"` - DoInsomnia bool `nbt:"doinsomnia"` - DoMobLoot bool `nbt:"domobloot"` - DoMobSpawning bool `nbt:"domobspawning"` - DoTileDrops bool `nbt:"dotiledrops"` - DoWeatherCycle bool `nbt:"doweathercycle"` - DrowningDamage bool `nbt:"drowningdamage"` - EduLevel bool `nbt:"eduLevel"` - EducationFeaturesEnabled bool `nbt:"educationFeaturesEnabled"` - ExperimentalGamePlay bool `nbt:"experimentalgameplay"` - FallDamage bool `nbt:"falldamage"` - FireDamage bool `nbt:"firedamage"` - FunctionCommandLimit int32 `nbt:"functioncommandlimit"` - HasBeenLoadedInCreative bool `nbt:"hasBeenLoadedInCreative"` - HasLockedBehaviourPack bool `nbt:"hasLockedBehaviorPack"` - HasLockedResourcePack bool `nbt:"hasLockedResourcePack"` - ImmutableWorld bool `nbt:"immutableWorld"` - IsCreatedInEditor bool `nbt:"isCreatedInEditor"` - IsExportedFromEditor bool `nbt:"isExportedFromEditor"` - IsFromLockedTemplate bool `nbt:"isFromLockedTemplate"` - IsFromWorldTemplate bool `nbt:"isFromWorldTemplate"` - IsWorldTemplateOptionLocked bool `nbt:"isWorldTemplateOptionLocked"` - KeepInventory bool `nbt:"keepinventory"` - LastOpenedWithVersion []int32 `nbt:"lastOpenedWithVersion"` - LightningLevel float32 `nbt:"lightningLevel"` - LightningTime int32 `nbt:"lightningTime"` - MaxCommandChainLength int32 `nbt:"maxcommandchainlength"` - MobGriefing bool `nbt:"mobgriefing"` - NaturalRegeneration bool `nbt:"naturalregeneration"` - PRID string `nbt:"prid"` - PVP bool `nbt:"pvp"` - RainLevel float32 `nbt:"rainLevel"` - RainTime int32 `nbt:"rainTime"` - RandomTickSpeed int32 `nbt:"randomtickspeed"` - RequiresCopiedPackRemovalCheck bool `nbt:"requiresCopiedPackRemovalCheck"` - SendCommandFeedback bool `nbt:"sendcommandfeedback"` - ServerChunkTickRange int32 `nbt:"serverChunkTickRange"` - ShowCoordinates bool `nbt:"showcoordinates"` - ShowDeathMessages bool `nbt:"showdeathmessages"` - SpawnMobs bool `nbt:"spawnMobs"` - SpawnRadius int32 `nbt:"spawnradius"` - StartWithMapEnabled bool `nbt:"startWithMapEnabled"` - TexturePacksRequired bool `nbt:"texturePacksRequired"` - TNTExplodes bool `nbt:"tntexplodes"` - UseMSAGamerTagsOnly bool `nbt:"useMsaGamertagsOnly"` - WorldStartCount int64 `nbt:"worldStartCount"` - Experiments map[string]any `nbt:"experiments"` - FreezeDamage bool `nbt:"freezedamage"` - WorldPolicies map[string]any `nbt:"world_policies"` - WorldVersion int32 `nbt:"WorldVersion"` - RespawnBlocksExplode bool `nbt:"respawnblocksexplode"` - ShowBorderEffect bool `nbt:"showbordereffect"` - PermissionsLevel int32 `nbt:"permissionsLevel"` - PlayerPermissionsLevel int32 `nbt:"playerPermissionsLevel"` - IsRandomSeedAllowed bool `nbt:"isRandomSeedAllowed"` - DoLimitedCrafting bool `nbt:"dolimitedcrafting"` - EditorWorldType int32 `nbt:"editorWorldType"` - PlayersSleepingPercentage int32 `nbt:"playerssleepingpercentage"` - RecipesUnlock bool `nbt:"recipesunlock"` - NaturalGeneration bool `nbt:"naturalgeneration"` - ProjectilesCanBreakBlocks bool `nbt:"projectilescanbreakblocks"` - ShowRecipeMessages bool `nbt:"showrecipemessages"` - IsHardcore bool `nbt:"IsHardcore"` - ShowDaysPlayed bool `nbt:"showdaysplayed"` - TNTExplosionDropDecay bool `nbt:"tntexplosiondropdecay"` - HasUncompleteWorldFileOnDisk bool `nbt:"HasUncompleteWorldFileOnDisk"` - PlayerHasDied bool `nbt:"PlayerHasDied"` - UseAllowList bool `nbt:"UseAllowList"` - AllowAnonymousBlockDropsInEditorWorlds bool `nbt:"allowAnonymousBlockDropsInEditorWorlds"` - PlayerWaypoints int32 `nbt:"playerwaypoints"` - ServerEditorConnectionPolicy int32 `nbt:"serverEditorConnectionPolicy"` + BonusChestEnabled bool `nbt:"bonusChestEnabled"` + BonusChestSpawned bool `nbt:"bonusChestSpawned"` + CommandBlockOutput bool `nbt:"commandblockoutput"` + CommandBlocksEnabled bool `nbt:"commandblocksenabled"` + CommandsEnabled bool `nbt:"commandsEnabled"` + CurrentTick int64 `nbt:"currentTick"` + DoDayLightCycle bool `nbt:"dodaylightcycle"` + DoEntityDrops bool `nbt:"doentitydrops"` + DoFireTick bool `nbt:"dofiretick"` + DoImmediateRespawn bool `nbt:"doimmediaterespawn"` + DoInsomnia bool `nbt:"doinsomnia"` + DoMobLoot bool `nbt:"domobloot"` + DoMobSpawning bool `nbt:"domobspawning"` + DoTileDrops bool `nbt:"dotiledrops"` + DoWeatherCycle bool `nbt:"doweathercycle"` + DrowningDamage bool `nbt:"drowningdamage"` + EduLevel bool `nbt:"eduLevel"` + EducationFeaturesEnabled bool `nbt:"educationFeaturesEnabled"` + ExperimentalGamePlay bool `nbt:"experimentalgameplay"` + FallDamage bool `nbt:"falldamage"` + FireDamage bool `nbt:"firedamage"` + FunctionCommandLimit int32 `nbt:"functioncommandlimit"` + HasBeenLoadedInCreative bool `nbt:"hasBeenLoadedInCreative"` + HasLockedBehaviourPack bool `nbt:"hasLockedBehaviorPack"` + HasLockedResourcePack bool `nbt:"hasLockedResourcePack"` + ImmutableWorld bool `nbt:"immutableWorld"` + IsCreatedInEditor bool `nbt:"isCreatedInEditor"` + IsExportedFromEditor bool `nbt:"isExportedFromEditor"` + IsFromLockedTemplate bool `nbt:"isFromLockedTemplate"` + IsFromWorldTemplate bool `nbt:"isFromWorldTemplate"` + IsWorldTemplateOptionLocked bool `nbt:"isWorldTemplateOptionLocked"` + KeepInventory bool `nbt:"keepinventory"` + LastOpenedWithVersion []int32 `nbt:"lastOpenedWithVersion"` + LightningLevel float32 `nbt:"lightningLevel"` + LightningTime int32 `nbt:"lightningTime"` + MaxCommandChainLength int32 `nbt:"maxcommandchainlength"` + MobGriefing bool `nbt:"mobgriefing"` + NaturalRegeneration bool `nbt:"naturalregeneration"` + PRID string `nbt:"prid"` + PVP bool `nbt:"pvp"` + RainLevel float32 `nbt:"rainLevel"` + RainTime int32 `nbt:"rainTime"` + RandomTickSpeed int32 `nbt:"randomtickspeed"` + RequiresCopiedPackRemovalCheck bool `nbt:"requiresCopiedPackRemovalCheck"` + SendCommandFeedback bool `nbt:"sendcommandfeedback"` + ServerChunkTickRange int32 `nbt:"serverChunkTickRange"` + ShowCoordinates bool `nbt:"showcoordinates"` + ShowDeathMessages bool `nbt:"showdeathmessages"` + SpawnMobs bool `nbt:"spawnMobs"` + SpawnRadius int32 `nbt:"spawnradius"` + StartWithMapEnabled bool `nbt:"startWithMapEnabled"` + TexturePacksRequired bool `nbt:"texturePacksRequired"` + TNTExplodes bool `nbt:"tntexplodes"` + UseMSAGamerTagsOnly bool `nbt:"useMsaGamertagsOnly"` + WorldStartCount int64 `nbt:"worldStartCount"` + Experiments map[string]any `nbt:"experiments"` + FreezeDamage bool `nbt:"freezedamage"` + WorldPolicies map[string]any `nbt:"world_policies"` + WorldVersion int32 `nbt:"WorldVersion"` + RespawnBlocksExplode bool `nbt:"respawnblocksexplode"` + ShowBorderEffect bool `nbt:"showbordereffect"` + PermissionsLevel int32 `nbt:"permissionsLevel"` + PlayerPermissionsLevel int32 `nbt:"playerPermissionsLevel"` + IsRandomSeedAllowed bool `nbt:"isRandomSeedAllowed"` + DoLimitedCrafting bool `nbt:"dolimitedcrafting"` + EditorWorldType int32 `nbt:"editorWorldType"` + PlayersSleepingPercentage int32 `nbt:"playerssleepingpercentage"` + RecipesUnlock bool `nbt:"recipesunlock"` + NaturalGeneration bool `nbt:"naturalgeneration"` + ProjectilesCanBreakBlocks bool `nbt:"projectilescanbreakblocks"` + ShowRecipeMessages bool `nbt:"showrecipemessages"` + IsHardcore bool `nbt:"IsHardcore"` + ShowDaysPlayed bool `nbt:"showdaysplayed"` + TNTExplosionDropDecay bool `nbt:"tntexplosiondropdecay"` + HasUncompleteWorldFileOnDisk bool `nbt:"HasUncompleteWorldFileOnDisk"` + PlayerHasDied bool `nbt:"PlayerHasDied"` + UseAllowList bool `nbt:"UseAllowList"` + AllowAnonymousBlockDropsInEditorWorlds bool `nbt:"allowAnonymousBlockDropsInEditorWorlds"` + PlayerWaypoints int32 `nbt:"playerwaypoints"` + ServerEditorConnectionPolicy int32 `nbt:"serverEditorConnectionPolicy"` } // FillDefault fills out d with all the default level.dat values.