From 6ab167e7dbc9062e3c9c1f237c696ccd460602e5 Mon Sep 17 00:00:00 2001 From: trafficlunar Date: Thu, 23 Jan 2025 19:18:43 +0000 Subject: [PATCH] fix: schematic versions --- src/components/VersionCombobox.tsx | 2 +- src/components/dialogs/OpenSchematic.tsx | 43 ++++++++++++++++-------- src/components/dialogs/SaveLitematic.tsx | 7 ++-- src/components/dialogs/SaveSchem.tsx | 13 ++++--- src/data/versions.json | 16 +++++++++ 5 files changed, 59 insertions(+), 22 deletions(-) create mode 100644 src/data/versions.json diff --git a/src/components/VersionCombobox.tsx b/src/components/VersionCombobox.tsx index 8bedd59..f20bf17 100644 --- a/src/components/VersionCombobox.tsx +++ b/src/components/VersionCombobox.tsx @@ -12,8 +12,8 @@ const versions = [ "1.21.4", "1.21", "1.20", - "1.18", "1.19", + "1.18", "1.17", "1.16", "1.15", diff --git a/src/components/dialogs/OpenSchematic.tsx b/src/components/dialogs/OpenSchematic.tsx index 91813e8..30ad75d 100644 --- a/src/components/dialogs/OpenSchematic.tsx +++ b/src/components/dialogs/OpenSchematic.tsx @@ -7,18 +7,24 @@ import * as nbt from "nbtify"; import { CanvasContext } from "@/context/Canvas"; import { LoadingContext } from "@/context/Loading"; +import { decodeVarint } from "@/utils/varint"; + import { DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from "@/components/ui/dialog"; import { Button } from "@/components/ui/button"; import _blockData from "@/data/blocks/data.json"; const blockData: BlockData = _blockData; +import _versionData from "@/data/versions.json"; +const versionData: Record = _versionData; + interface LitematicaBlockPalette extends nbt.CompoundTagLike { Name: string; Properties?: Record; } interface LitematicNBT extends nbt.ListTagLike { + MinecraftDataVersion: number; Regions: { Image: { BlockStatePalette: LitematicaBlockPalette[]; @@ -34,13 +40,14 @@ interface SpongeNBT extends nbt.ListTagLike { Data: Int8Array; Palette: Record; }; + DataVersion: number; Width: number; Height: number; }; } function OpenSchematic({ close }: DialogProps) { - const { setBlocks } = useContext(CanvasContext); + const { setBlocks, setVersion } = useContext(CanvasContext); const { setLoading } = useContext(LoadingContext); const { acceptedFiles, getRootProps, getInputProps } = useDropzone({ @@ -61,16 +68,20 @@ function OpenSchematic({ close }: DialogProps) { const data = await nbt.read(bytes); if (fileExtension == "litematic") { - const litematicData = (data as nbt.NBTData).data.Regions.Image; + const litematicData = (data as nbt.NBTData).data; + const litematicRegionData = litematicData.Regions.Image; + const litematicVersion = Object.keys(versionData).find((key) => versionData[key] == litematicData.MinecraftDataVersion); - // todo: set version - const requiredBits = Math.max(Math.ceil(Math.log2(litematicData.BlockStatePalette.length)), 2); + // Set version to schematic version. If it doesn't find it in the data, return the latest version + setVersion(parseInt(litematicVersion || Object.keys(versionData)[0])); + + const requiredBits = Math.max(Math.ceil(Math.log2(litematicRegionData.BlockStatePalette.length)), 2); const getPaletteIndex = (index: number): bigint => { - const originalY = Math.floor(index / litematicData.Size.x); - const originalX = index % litematicData.Size.x; - const reversedY = litematicData.Size.y - 1 - originalY; - const reversedIndex = reversedY * litematicData.Size.x + originalX; + const originalY = Math.floor(index / litematicRegionData.Size.x); + const originalX = index % litematicRegionData.Size.x; + const reversedY = litematicRegionData.Size.y - 1 - originalY; + const reversedIndex = reversedY * litematicRegionData.Size.x + originalX; // getAt() implementation - LitematicaBitArray.java const startOffset = reversedIndex * requiredBits; @@ -80,11 +91,12 @@ function OpenSchematic({ close }: DialogProps) { const mask = (1 << requiredBits) - 1; if (startArrayIndex === endArrayIndex) { - return (litematicData.BlockStates[startArrayIndex] >> BigInt(bitOffset)) & BigInt(mask); + return (litematicRegionData.BlockStates[startArrayIndex] >> BigInt(bitOffset)) & BigInt(mask); } else { const endOffset = 64 - bitOffset; return ( - ((litematicData.BlockStates[startArrayIndex] >> BigInt(bitOffset)) | (litematicData.BlockStates[endArrayIndex] << BigInt(endOffset))) & + ((litematicRegionData.BlockStates[startArrayIndex] >> BigInt(bitOffset)) | + (litematicRegionData.BlockStates[endArrayIndex] << BigInt(endOffset))) & BigInt(mask) ); } @@ -94,11 +106,11 @@ function OpenSchematic({ close }: DialogProps) { const blocks: Block[] = []; let index = 0; - for (let y = 0; y < litematicData.Size.y; y++) { - for (let x = 0; x < litematicData.Size.x; x++) { + for (let y = 0; y < litematicRegionData.Size.y; y++) { + for (let x = 0; x < litematicRegionData.Size.x; x++) { const paletteIndex = Number(getPaletteIndex(index)); console.log(paletteIndex); - const paletteBlock = litematicData.BlockStatePalette[paletteIndex]; + const paletteBlock = litematicRegionData.BlockStatePalette[paletteIndex]; index++; if (!paletteBlock) continue; @@ -134,7 +146,10 @@ function OpenSchematic({ close }: DialogProps) { setBlocks(blocks); } else if (fileExtension == "schem") { const spongeData = (data as nbt.NBTData).data.Schematic; - // todo: set version + const schematicVersion = Object.keys(versionData).find((key) => versionData[key] == spongeData.DataVersion); + + // Set version to schematic version. If it doesn't find it in the data, return the latest version + setVersion(parseInt(schematicVersion || Object.keys(versionData)[0])); // Add every block to the canvas const blocks: Block[] = []; diff --git a/src/components/dialogs/SaveLitematic.tsx b/src/components/dialogs/SaveLitematic.tsx index bc013be..f2c584f 100644 --- a/src/components/dialogs/SaveLitematic.tsx +++ b/src/components/dialogs/SaveLitematic.tsx @@ -11,8 +11,11 @@ import { Input } from "@/components/ui/input"; import _blockData from "@/data/blocks/data.json"; const blockData: BlockData = _blockData; +import _versionData from "@/data/versions.json"; +const versionData: Record = _versionData; + function SaveLitematic({ close }: DialogProps) { - const { canvasSize, blocks } = useContext(CanvasContext); + const { canvasSize, blocks, version } = useContext(CanvasContext); const { setLoading } = useContext(LoadingContext); const [fileName, setFileName] = useState("blockmatic"); @@ -92,7 +95,7 @@ function SaveLitematic({ close }: DialogProps) { // Generate NBT data const data = { - MinecraftDataVersion: new nbt.Int32(4189), + MinecraftDataVersion: new nbt.Int32(versionData[version]), Version: new nbt.Int32(7), SubVersion: new nbt.Int32(1), Metadata: { diff --git a/src/components/dialogs/SaveSchem.tsx b/src/components/dialogs/SaveSchem.tsx index 8e3a57d..f9e95ed 100644 --- a/src/components/dialogs/SaveSchem.tsx +++ b/src/components/dialogs/SaveSchem.tsx @@ -13,6 +13,9 @@ import { Input } from "@/components/ui/input"; import _blockData from "@/data/blocks/data.json"; const blockData: BlockData = _blockData; +import _versionData from "@/data/versions.json"; +const versionData: Record = _versionData; + interface BlockEntity { Id: string; Pos: Int32Array; @@ -40,8 +43,8 @@ const blockEntitiesWhitelist = [ "vault", ]; -function SaveLitematic({ close }: DialogProps) { - const { canvasSize, blocks } = useContext(CanvasContext); +function SaveSchem({ close }: DialogProps) { + const { canvasSize, blocks, version } = useContext(CanvasContext); const { setLoading } = useContext(LoadingContext); const [fileName, setFileName] = useState("blockmatic"); @@ -130,7 +133,7 @@ function SaveLitematic({ close }: DialogProps) { // Generate NBT data const data = { Schematic: { - DataVersion: new nbt.Int32(4189), + DataVersion: new nbt.Int32(versionData[version]), Version: new nbt.Int32(3), Width: new nbt.Int16(width), Height: new nbt.Int16(height), @@ -167,7 +170,7 @@ function SaveLitematic({ close }: DialogProps) { Save as .schem - Save your image as a .schem (Sponge) + Save your image as a .schem (Sponge Version 3)
@@ -187,4 +190,4 @@ function SaveLitematic({ close }: DialogProps) { ); } -export default SaveLitematic; +export default SaveSchem; diff --git a/src/data/versions.json b/src/data/versions.json new file mode 100644 index 0000000..4454538 --- /dev/null +++ b/src/data/versions.json @@ -0,0 +1,16 @@ +{ + "1214": 4189, + "1210": 3953, + "1200": 3463, + "1190": 3105, + "1180": 2860, + "1170": 2724, + "1160": 2566, + "1150": 2225, + "1140": 1952, + "1130": 1519, + "1120": 1139, + "1110": 819, + "1000": 510, + "1090": 169 +}