diff --git a/core/src/main/java/com/volmit/iris/core/commands/CommandDeveloper.java b/core/src/main/java/com/volmit/iris/core/commands/CommandDeveloper.java index da46c93f4..81473b45f 100644 --- a/core/src/main/java/com/volmit/iris/core/commands/CommandDeveloper.java +++ b/core/src/main/java/com/volmit/iris/core/commands/CommandDeveloper.java @@ -47,6 +47,7 @@ import com.volmit.iris.util.math.Spiraler; import com.volmit.iris.util.math.Vector3d; import com.volmit.iris.util.nbt.mca.MCAFile; import com.volmit.iris.util.nbt.mca.MCAUtil; +import com.volmit.iris.util.parallel.MultiBurst; import com.volmit.iris.util.plugin.VolmitSender; import io.lumine.mythic.bukkit.adapters.BukkitEntity; import net.jpountz.lz4.LZ4BlockInputStream; @@ -206,6 +207,23 @@ public class CommandDeveloper implements DecreeExecutor { } + @Decree + public void objects(@Param(defaultValue = "overworld") IrisDimension dimension) { + var loader = dimension.getLoader().getObjectLoader(); + var sender = sender(); + var keys = loader.getPossibleKeys(); + var burst = MultiBurst.burst.burst(keys.length); + AtomicInteger failed = new AtomicInteger(); + for (String key : keys) { + burst.queue(() -> { + if (loader.load(key) == null) + failed.incrementAndGet(); + }); + } + burst.complete(); + sender.sendMessage(C.RED + "Failed to load " + failed.get() + " of " + keys.length + " objects"); + } + @Decree(description = "Test", aliases = {"ip"}) public void network() { try { diff --git a/core/src/main/java/com/volmit/iris/core/loader/ObjectResourceLoader.java b/core/src/main/java/com/volmit/iris/core/loader/ObjectResourceLoader.java index 37f3f43b5..3fa92bc46 100644 --- a/core/src/main/java/com/volmit/iris/core/loader/ObjectResourceLoader.java +++ b/core/src/main/java/com/volmit/iris/core/loader/ObjectResourceLoader.java @@ -50,10 +50,10 @@ public class ObjectResourceLoader extends ResourceLoader { try { PrecisionStopwatch p = PrecisionStopwatch.start(); IrisObject t = new IrisObject(0, 0, 0); - t.read(j); t.setLoadKey(name); t.setLoader(manager); t.setLoadFile(j); + t.read(j); logLoad(j, t); tlt.addAndGet(p.getMilliseconds()); return t; diff --git a/core/src/main/java/com/volmit/iris/engine/mantle/EngineMantle.java b/core/src/main/java/com/volmit/iris/engine/mantle/EngineMantle.java index 4b6e334c6..d8969636b 100644 --- a/core/src/main/java/com/volmit/iris/engine/mantle/EngineMantle.java +++ b/core/src/main/java/com/volmit/iris/engine/mantle/EngineMantle.java @@ -108,7 +108,7 @@ public interface EngineMantle extends IObjectPlacer { @Override default void setTile(int x, int y, int z, TileData d) { - getMantle().set(x, y, z, d); + getMantle().set(x, y, z, new TileWrapper(d)); } @Override diff --git a/core/src/main/java/com/volmit/iris/engine/object/IrisObject.java b/core/src/main/java/com/volmit/iris/engine/object/IrisObject.java index bed5dac35..0866ee63f 100644 --- a/core/src/main/java/com/volmit/iris/engine/object/IrisObject.java +++ b/core/src/main/java/com/volmit/iris/engine/object/IrisObject.java @@ -385,14 +385,14 @@ public class IrisObject extends IrisRegistrant { } public void read(File file) throws IOException { - FileInputStream fin = new FileInputStream(file); + var fin = new BufferedInputStream(new FileInputStream(file)); try { read(fin); fin.close(); } catch (Throwable e) { Iris.reportError(e); fin.close(); - fin = new FileInputStream(file); + fin = new BufferedInputStream(new FileInputStream(file)); readLegacy(fin); fin.close(); } diff --git a/core/src/main/java/com/volmit/iris/engine/object/LegacyTileData.java b/core/src/main/java/com/volmit/iris/engine/object/LegacyTileData.java new file mode 100644 index 000000000..255a0b4d0 --- /dev/null +++ b/core/src/main/java/com/volmit/iris/engine/object/LegacyTileData.java @@ -0,0 +1,139 @@ +package com.volmit.iris.engine.object; + +import com.volmit.iris.Iris; +import com.volmit.iris.util.collection.KList; +import com.volmit.iris.util.scheduling.J; +import org.bukkit.DyeColor; +import org.bukkit.block.*; +import org.bukkit.block.banner.Pattern; +import org.bukkit.block.banner.PatternType; +import org.bukkit.entity.EntityType; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.util.List; +import java.util.Map; + +public class LegacyTileData extends TileData { + private static final Map legacy = Map.of( + (short) 0, new SignHandler(), + (short) 1, new SpawnerHandler(), + (short) 2, new BannerHandler()); + private final short id; + private final KList properties; + + public LegacyTileData(DataInputStream in) throws IOException { + id = in.readShort(); + var handler = legacy.get(id); + if (handler == null) + throw new IOException("Unknown tile type: " + id); + properties = handler.read(in); + } + + @Override + public void toBukkit(Block block) { + var handler = legacy.get(id); + J.s(() -> handler.toBukkit(properties, block)); + } + + @Override + public void toBinary(DataOutputStream out) throws IOException { + out.writeShort(id); + legacy.get(id).toBinary(properties, out); + } + + private interface Handler { + KList read(DataInputStream in) throws IOException; + void toBinary(KList list, DataOutputStream out) throws IOException; + void toBukkit(KList list, Block block); + } + + private static class SignHandler implements Handler { + @Override + public KList read(DataInputStream in) throws IOException { + return new KList<>() + .qadd(in.readUTF()) + .qadd(in.readUTF()) + .qadd(in.readUTF()) + .qadd(in.readUTF()) + .qadd(DyeColor.values()[in.readByte()]); + } + + @Override + public void toBinary(KList list, DataOutputStream out) throws IOException { + out.writeUTF((String) list.get(0)); + out.writeUTF((String) list.get(1)); + out.writeUTF((String) list.get(2)); + out.writeUTF((String) list.get(3)); + out.writeByte(((DyeColor) list.get(4)).ordinal()); + } + + @Override + public void toBukkit(KList list, Block block) { + Sign sign = (Sign) block.getState(); + sign.setLine(0, (String) list.get(0)); + sign.setLine(1, (String) list.get(1)); + sign.setLine(2, (String) list.get(2)); + sign.setLine(3, (String) list.get(3)); + sign.setColor((DyeColor) list.get(4)); + sign.update(); + } + } + + private static class SpawnerHandler implements Handler { + @Override + public KList read(DataInputStream in) throws IOException { + return new KList<>().qadd(EntityType.values()[in.readShort()]); + } + + @Override + public void toBinary(KList list, DataOutputStream out) throws IOException { + out.writeShort(((EntityType) list.get(0)).ordinal()); + } + + @Override + public void toBukkit(KList list, Block block) { + CreatureSpawner spawner = (CreatureSpawner) block.getState(); + spawner.setSpawnedType((EntityType) list.get(0)); + spawner.update(); + } + } + + private static class BannerHandler implements Handler { + @Override + public KList read(DataInputStream in) throws IOException { + KList list = new KList<>(); + list.add(DyeColor.values()[in.readByte()]); + int listSize = in.readByte(); + var patterns = new KList<>(); + + for (int i = 0; i < listSize; i++) { + DyeColor color = DyeColor.values()[in.readByte()]; + PatternType type = PatternType.values()[in.readByte()]; + patterns.add(new Pattern(color, type)); + } + + list.add(patterns); + return list; + } + + @Override + public void toBinary(KList list, DataOutputStream out) throws IOException { + out.writeByte(((DyeColor) list.get(0)).ordinal()); + out.writeByte(((List) list.get(1)).size()); + for (Pattern i : (List) list.get(1)) { + out.writeByte(i.getColor().ordinal()); + out.writeByte(i.getPattern().ordinal()); + } + } + + @Override + public void toBukkit(KList list, Block block) { + Banner banner = (Banner) block.getState(); + banner.setBaseColor((DyeColor) list.get(0)); + banner.setPatterns((List) list.get(1)); + banner.update(); + } + } +} diff --git a/core/src/main/java/com/volmit/iris/engine/object/TileData.java b/core/src/main/java/com/volmit/iris/engine/object/TileData.java index a8d94f7da..9bab31df8 100644 --- a/core/src/main/java/com/volmit/iris/engine/object/TileData.java +++ b/core/src/main/java/com/volmit/iris/engine/object/TileData.java @@ -31,6 +31,7 @@ import org.bukkit.block.BlockState; import org.bukkit.block.TileState; import org.bukkit.block.data.BlockData; +import java.io.BufferedInputStream; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; @@ -57,10 +58,24 @@ public class TileData implements Cloneable { } public static TileData read(DataInputStream in) throws IOException { - TileData d = new TileData(); - d.material = Material.matchMaterial(in.readUTF()); - d.properties = gson.fromJson(in.readUTF(), KMap.class); - return d; + if (!in.markSupported()) + throw new IOException("Mark not supported"); + in.mark(Integer.MAX_VALUE); + try { + TileData d = new TileData(); + var material = in.readUTF(); + d.material = Material.matchMaterial(material); + if (d.material == null) throw new IOException("Unknown material: " + material); + var properties = in.readUTF(); + d.properties = gson.fromJson(properties, KMap.class); + if (d.properties == null) throw new IOException("Invalid properties: " + properties); + return d; + } catch (Throwable e) { + in.reset(); + return new LegacyTileData(in); + } finally { + in.mark(0); + } } public boolean isApplicable(BlockData data) { diff --git a/core/src/main/java/com/volmit/iris/util/mantle/TectonicPlate.java b/core/src/main/java/com/volmit/iris/util/mantle/TectonicPlate.java index 6f3cd0f35..044e1f745 100644 --- a/core/src/main/java/com/volmit/iris/util/mantle/TectonicPlate.java +++ b/core/src/main/java/com/volmit/iris/util/mantle/TectonicPlate.java @@ -86,10 +86,10 @@ public class TectonicPlate { DataInputStream din; if (file.getName().endsWith("ttp.lz4b")) { LZ4BlockInputStream lz4 = new LZ4BlockInputStream(fin); - din = new DataInputStream(lz4); + din = new DataInputStream(new BufferedInputStream(lz4)); } else { GZIPInputStream gzi = new GZIPInputStream(fin); - din = new DataInputStream(gzi); + din = new DataInputStream(new BufferedInputStream(gzi)); } TectonicPlate p = new TectonicPlate(worldHeight, din); din.close(); diff --git a/core/src/main/java/com/volmit/iris/util/matter/TileWrapper.java b/core/src/main/java/com/volmit/iris/util/matter/TileWrapper.java new file mode 100644 index 000000000..0fa14eab6 --- /dev/null +++ b/core/src/main/java/com/volmit/iris/util/matter/TileWrapper.java @@ -0,0 +1,27 @@ +/* + * Iris is a World Generator for Minecraft Bukkit Servers + * Copyright (c) 2024 Arcane Arts (Volmit Software) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.volmit.iris.util.matter; + +import com.volmit.iris.engine.object.TileData; +import lombok.Data; + +@Data +public class TileWrapper { + private final TileData data; +} diff --git a/core/src/main/java/com/volmit/iris/util/matter/WorldMatter.java b/core/src/main/java/com/volmit/iris/util/matter/WorldMatter.java index 0061d7f05..40ff187d0 100644 --- a/core/src/main/java/com/volmit/iris/util/matter/WorldMatter.java +++ b/core/src/main/java/com/volmit/iris/util/matter/WorldMatter.java @@ -34,8 +34,8 @@ public class WorldMatter { matter.slice(MatterEntityGroup.class).writeInto(at); } - if (matter.hasSlice(TileData.class)) { - matter.slice(TileData.class).writeInto(at); + if (matter.hasSlice(TileWrapper.class)) { + matter.slice(TileWrapper.class).writeInto(at); } } @@ -46,7 +46,7 @@ public class WorldMatter { s.getHeader().setAuthor(author); s.slice(BlockData.class).readFrom(c.getLowerNE()); s.slice(MatterEntityGroup.class).readFrom(c.getLowerNE()); - s.slice(TileData.class).readFrom(c.getLowerNE()); + s.slice(TileWrapper.class).readFrom(c.getLowerNE()); s.trimSlices(); return s; diff --git a/core/src/main/java/com/volmit/iris/util/matter/slices/TileMatter.java b/core/src/main/java/com/volmit/iris/util/matter/slices/TileMatter.java index 47a1b9e1d..25e46a831 100644 --- a/core/src/main/java/com/volmit/iris/util/matter/slices/TileMatter.java +++ b/core/src/main/java/com/volmit/iris/util/matter/slices/TileMatter.java @@ -21,6 +21,7 @@ package com.volmit.iris.util.matter.slices; import com.volmit.iris.engine.object.TileData; import com.volmit.iris.util.data.palette.Palette; import com.volmit.iris.util.matter.Sliced; +import com.volmit.iris.util.matter.TileWrapper; import org.bukkit.Location; import org.bukkit.World; @@ -30,28 +31,28 @@ import java.io.IOException; @SuppressWarnings("rawtypes") @Sliced -public class TileMatter extends RawMatter { +public class TileMatter extends RawMatter { public TileMatter() { this(1, 1, 1); } public TileMatter(int width, int height, int depth) { - super(width, height, depth, TileData.class); - registerWriter(World.class, (w, d, x, y, z) -> TileData.setTileState(w.getBlockAt(new Location(w, x, y, z)), d)); - registerReader(World.class, (w, x, y, z) -> TileData.getTileState(w.getBlockAt(new Location(w, x, y, z)))); + super(width, height, depth, TileWrapper.class); + registerWriter(World.class, (w, d, x, y, z) -> TileData.setTileState(w.getBlockAt(new Location(w, x, y, z)), d.getData())); + registerReader(World.class, (w, x, y, z) -> new TileWrapper(TileData.getTileState(w.getBlockAt(new Location(w, x, y, z))))); } @Override - public Palette getGlobalPalette() { + public Palette getGlobalPalette() { return null; } - public void writeNode(TileData b, DataOutputStream dos) throws IOException { - b.toBinary(dos); + public void writeNode(TileWrapper b, DataOutputStream dos) throws IOException { + b.getData().toBinary(dos); } - public TileData readNode(DataInputStream din) throws IOException { - return TileData.read(din); + public TileWrapper readNode(DataInputStream din) throws IOException { + return new TileWrapper(TileData.read(din)); } }