fix: schematic versions
This commit is contained in:
parent
e6788d529a
commit
6ab167e7db
5 changed files with 59 additions and 22 deletions
|
|
@ -12,8 +12,8 @@ const versions = [
|
||||||
"1.21.4",
|
"1.21.4",
|
||||||
"1.21",
|
"1.21",
|
||||||
"1.20",
|
"1.20",
|
||||||
"1.18",
|
|
||||||
"1.19",
|
"1.19",
|
||||||
|
"1.18",
|
||||||
"1.17",
|
"1.17",
|
||||||
"1.16",
|
"1.16",
|
||||||
"1.15",
|
"1.15",
|
||||||
|
|
|
||||||
|
|
@ -7,18 +7,24 @@ import * as nbt from "nbtify";
|
||||||
import { CanvasContext } from "@/context/Canvas";
|
import { CanvasContext } from "@/context/Canvas";
|
||||||
import { LoadingContext } from "@/context/Loading";
|
import { LoadingContext } from "@/context/Loading";
|
||||||
|
|
||||||
|
import { decodeVarint } from "@/utils/varint";
|
||||||
|
|
||||||
import { DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from "@/components/ui/dialog";
|
import { DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from "@/components/ui/dialog";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
|
|
||||||
import _blockData from "@/data/blocks/data.json";
|
import _blockData from "@/data/blocks/data.json";
|
||||||
const blockData: BlockData = _blockData;
|
const blockData: BlockData = _blockData;
|
||||||
|
|
||||||
|
import _versionData from "@/data/versions.json";
|
||||||
|
const versionData: Record<string, number> = _versionData;
|
||||||
|
|
||||||
interface LitematicaBlockPalette extends nbt.CompoundTagLike {
|
interface LitematicaBlockPalette extends nbt.CompoundTagLike {
|
||||||
Name: string;
|
Name: string;
|
||||||
Properties?: Record<string, string>;
|
Properties?: Record<string, string>;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface LitematicNBT extends nbt.ListTagLike {
|
interface LitematicNBT extends nbt.ListTagLike {
|
||||||
|
MinecraftDataVersion: number;
|
||||||
Regions: {
|
Regions: {
|
||||||
Image: {
|
Image: {
|
||||||
BlockStatePalette: LitematicaBlockPalette[];
|
BlockStatePalette: LitematicaBlockPalette[];
|
||||||
|
|
@ -34,13 +40,14 @@ interface SpongeNBT extends nbt.ListTagLike {
|
||||||
Data: Int8Array;
|
Data: Int8Array;
|
||||||
Palette: Record<string, number>;
|
Palette: Record<string, number>;
|
||||||
};
|
};
|
||||||
|
DataVersion: number;
|
||||||
Width: number;
|
Width: number;
|
||||||
Height: number;
|
Height: number;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function OpenSchematic({ close }: DialogProps) {
|
function OpenSchematic({ close }: DialogProps) {
|
||||||
const { setBlocks } = useContext(CanvasContext);
|
const { setBlocks, setVersion } = useContext(CanvasContext);
|
||||||
const { setLoading } = useContext(LoadingContext);
|
const { setLoading } = useContext(LoadingContext);
|
||||||
|
|
||||||
const { acceptedFiles, getRootProps, getInputProps } = useDropzone({
|
const { acceptedFiles, getRootProps, getInputProps } = useDropzone({
|
||||||
|
|
@ -61,16 +68,20 @@ function OpenSchematic({ close }: DialogProps) {
|
||||||
const data = await nbt.read(bytes);
|
const data = await nbt.read(bytes);
|
||||||
|
|
||||||
if (fileExtension == "litematic") {
|
if (fileExtension == "litematic") {
|
||||||
const litematicData = (data as nbt.NBTData<LitematicNBT>).data.Regions.Image;
|
const litematicData = (data as nbt.NBTData<LitematicNBT>).data;
|
||||||
|
const litematicRegionData = litematicData.Regions.Image;
|
||||||
|
const litematicVersion = Object.keys(versionData).find((key) => versionData[key] == litematicData.MinecraftDataVersion);
|
||||||
|
|
||||||
// todo: set version
|
// Set version to schematic version. If it doesn't find it in the data, return the latest version
|
||||||
const requiredBits = Math.max(Math.ceil(Math.log2(litematicData.BlockStatePalette.length)), 2);
|
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 getPaletteIndex = (index: number): bigint => {
|
||||||
const originalY = Math.floor(index / litematicData.Size.x);
|
const originalY = Math.floor(index / litematicRegionData.Size.x);
|
||||||
const originalX = index % litematicData.Size.x;
|
const originalX = index % litematicRegionData.Size.x;
|
||||||
const reversedY = litematicData.Size.y - 1 - originalY;
|
const reversedY = litematicRegionData.Size.y - 1 - originalY;
|
||||||
const reversedIndex = reversedY * litematicData.Size.x + originalX;
|
const reversedIndex = reversedY * litematicRegionData.Size.x + originalX;
|
||||||
|
|
||||||
// getAt() implementation - LitematicaBitArray.java
|
// getAt() implementation - LitematicaBitArray.java
|
||||||
const startOffset = reversedIndex * requiredBits;
|
const startOffset = reversedIndex * requiredBits;
|
||||||
|
|
@ -80,11 +91,12 @@ function OpenSchematic({ close }: DialogProps) {
|
||||||
const mask = (1 << requiredBits) - 1;
|
const mask = (1 << requiredBits) - 1;
|
||||||
|
|
||||||
if (startArrayIndex === endArrayIndex) {
|
if (startArrayIndex === endArrayIndex) {
|
||||||
return (litematicData.BlockStates[startArrayIndex] >> BigInt(bitOffset)) & BigInt(mask);
|
return (litematicRegionData.BlockStates[startArrayIndex] >> BigInt(bitOffset)) & BigInt(mask);
|
||||||
} else {
|
} else {
|
||||||
const endOffset = 64 - bitOffset;
|
const endOffset = 64 - bitOffset;
|
||||||
return (
|
return (
|
||||||
((litematicData.BlockStates[startArrayIndex] >> BigInt(bitOffset)) | (litematicData.BlockStates[endArrayIndex] << BigInt(endOffset))) &
|
((litematicRegionData.BlockStates[startArrayIndex] >> BigInt(bitOffset)) |
|
||||||
|
(litematicRegionData.BlockStates[endArrayIndex] << BigInt(endOffset))) &
|
||||||
BigInt(mask)
|
BigInt(mask)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -94,11 +106,11 @@ function OpenSchematic({ close }: DialogProps) {
|
||||||
const blocks: Block[] = [];
|
const blocks: Block[] = [];
|
||||||
let index = 0;
|
let index = 0;
|
||||||
|
|
||||||
for (let y = 0; y < litematicData.Size.y; y++) {
|
for (let y = 0; y < litematicRegionData.Size.y; y++) {
|
||||||
for (let x = 0; x < litematicData.Size.x; x++) {
|
for (let x = 0; x < litematicRegionData.Size.x; x++) {
|
||||||
const paletteIndex = Number(getPaletteIndex(index));
|
const paletteIndex = Number(getPaletteIndex(index));
|
||||||
console.log(paletteIndex);
|
console.log(paletteIndex);
|
||||||
const paletteBlock = litematicData.BlockStatePalette[paletteIndex];
|
const paletteBlock = litematicRegionData.BlockStatePalette[paletteIndex];
|
||||||
|
|
||||||
index++;
|
index++;
|
||||||
if (!paletteBlock) continue;
|
if (!paletteBlock) continue;
|
||||||
|
|
@ -134,7 +146,10 @@ function OpenSchematic({ close }: DialogProps) {
|
||||||
setBlocks(blocks);
|
setBlocks(blocks);
|
||||||
} else if (fileExtension == "schem") {
|
} else if (fileExtension == "schem") {
|
||||||
const spongeData = (data as nbt.NBTData<SpongeNBT>).data.Schematic;
|
const spongeData = (data as nbt.NBTData<SpongeNBT>).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
|
// Add every block to the canvas
|
||||||
const blocks: Block[] = [];
|
const blocks: Block[] = [];
|
||||||
|
|
|
||||||
|
|
@ -11,8 +11,11 @@ import { Input } from "@/components/ui/input";
|
||||||
import _blockData from "@/data/blocks/data.json";
|
import _blockData from "@/data/blocks/data.json";
|
||||||
const blockData: BlockData = _blockData;
|
const blockData: BlockData = _blockData;
|
||||||
|
|
||||||
|
import _versionData from "@/data/versions.json";
|
||||||
|
const versionData: Record<string, number> = _versionData;
|
||||||
|
|
||||||
function SaveLitematic({ close }: DialogProps) {
|
function SaveLitematic({ close }: DialogProps) {
|
||||||
const { canvasSize, blocks } = useContext(CanvasContext);
|
const { canvasSize, blocks, version } = useContext(CanvasContext);
|
||||||
const { setLoading } = useContext(LoadingContext);
|
const { setLoading } = useContext(LoadingContext);
|
||||||
|
|
||||||
const [fileName, setFileName] = useState("blockmatic");
|
const [fileName, setFileName] = useState("blockmatic");
|
||||||
|
|
@ -92,7 +95,7 @@ function SaveLitematic({ close }: DialogProps) {
|
||||||
|
|
||||||
// Generate NBT data
|
// Generate NBT data
|
||||||
const data = {
|
const data = {
|
||||||
MinecraftDataVersion: new nbt.Int32(4189),
|
MinecraftDataVersion: new nbt.Int32(versionData[version]),
|
||||||
Version: new nbt.Int32(7),
|
Version: new nbt.Int32(7),
|
||||||
SubVersion: new nbt.Int32(1),
|
SubVersion: new nbt.Int32(1),
|
||||||
Metadata: {
|
Metadata: {
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,9 @@ import { Input } from "@/components/ui/input";
|
||||||
import _blockData from "@/data/blocks/data.json";
|
import _blockData from "@/data/blocks/data.json";
|
||||||
const blockData: BlockData = _blockData;
|
const blockData: BlockData = _blockData;
|
||||||
|
|
||||||
|
import _versionData from "@/data/versions.json";
|
||||||
|
const versionData: Record<string, number> = _versionData;
|
||||||
|
|
||||||
interface BlockEntity {
|
interface BlockEntity {
|
||||||
Id: string;
|
Id: string;
|
||||||
Pos: Int32Array;
|
Pos: Int32Array;
|
||||||
|
|
@ -40,8 +43,8 @@ const blockEntitiesWhitelist = [
|
||||||
"vault",
|
"vault",
|
||||||
];
|
];
|
||||||
|
|
||||||
function SaveLitematic({ close }: DialogProps) {
|
function SaveSchem({ close }: DialogProps) {
|
||||||
const { canvasSize, blocks } = useContext(CanvasContext);
|
const { canvasSize, blocks, version } = useContext(CanvasContext);
|
||||||
const { setLoading } = useContext(LoadingContext);
|
const { setLoading } = useContext(LoadingContext);
|
||||||
|
|
||||||
const [fileName, setFileName] = useState("blockmatic");
|
const [fileName, setFileName] = useState("blockmatic");
|
||||||
|
|
@ -130,7 +133,7 @@ function SaveLitematic({ close }: DialogProps) {
|
||||||
// Generate NBT data
|
// Generate NBT data
|
||||||
const data = {
|
const data = {
|
||||||
Schematic: {
|
Schematic: {
|
||||||
DataVersion: new nbt.Int32(4189),
|
DataVersion: new nbt.Int32(versionData[version]),
|
||||||
Version: new nbt.Int32(3),
|
Version: new nbt.Int32(3),
|
||||||
Width: new nbt.Int16(width),
|
Width: new nbt.Int16(width),
|
||||||
Height: new nbt.Int16(height),
|
Height: new nbt.Int16(height),
|
||||||
|
|
@ -167,7 +170,7 @@ function SaveLitematic({ close }: DialogProps) {
|
||||||
<DialogContent>
|
<DialogContent>
|
||||||
<DialogHeader>
|
<DialogHeader>
|
||||||
<DialogTitle>Save as .schem</DialogTitle>
|
<DialogTitle>Save as .schem</DialogTitle>
|
||||||
<DialogDescription>Save your image as a .schem (Sponge)</DialogDescription>
|
<DialogDescription>Save your image as a .schem (Sponge Version 3)</DialogDescription>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
|
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
|
|
@ -187,4 +190,4 @@ function SaveLitematic({ close }: DialogProps) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default SaveLitematic;
|
export default SaveSchem;
|
||||||
|
|
|
||||||
16
src/data/versions.json
Normal file
16
src/data/versions.json
Normal file
|
|
@ -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
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue