From fa6b729b6e02c8a23860d995a3c9e8c4bfb769f7 Mon Sep 17 00:00:00 2001 From: CatMoe Date: Wed, 13 Apr 2022 06:31:36 +0000 Subject: [PATCH 01/27] Implement sign marker for fabric 1.16 --- .../dynmap/fabric_1_16_4/FabricServer.java | 5 +++ .../fabric_1_16_4/event/BlockEvents.java | 17 +++++++++ .../mixin/ServerPlayNetworkHandlerMixin.java | 36 +++++++++++++++++++ 3 files changed, 58 insertions(+) diff --git a/fabric-1.16.4/src/main/java/org/dynmap/fabric_1_16_4/FabricServer.java b/fabric-1.16.4/src/main/java/org/dynmap/fabric_1_16_4/FabricServer.java index 9c0844f3..1a4e1ef3 100644 --- a/fabric-1.16.4/src/main/java/org/dynmap/fabric_1_16_4/FabricServer.java +++ b/fabric-1.16.4/src/main/java/org/dynmap/fabric_1_16_4/FabricServer.java @@ -27,6 +27,7 @@ import org.dynmap.common.DynmapListenerManager; import org.dynmap.common.DynmapPlayer; import org.dynmap.common.DynmapServerInterface; import org.dynmap.fabric_1_16_4.event.ServerChatEvents; +import org.dynmap.fabric_1_16_4.event.BlockEvents; import org.dynmap.utils.MapChunkCache; import org.dynmap.utils.VisibilityLimit; @@ -283,6 +284,10 @@ public class FabricServer extends DynmapServerInterface { } }, DynmapPlugin.this); */ + BlockEvents.SIGN_CHANGE_EVENT.register((world, pos, lines, material, player) -> { + plugin.core.processSignChange("fabric", FabricWorld.getWorldName(plugin, world), + pos.getX(), pos.getY(), pos.getZ(), lines, player.getName().asString()); + }); break; default: diff --git a/fabric-1.16.4/src/main/java/org/dynmap/fabric_1_16_4/event/BlockEvents.java b/fabric-1.16.4/src/main/java/org/dynmap/fabric_1_16_4/event/BlockEvents.java index 564f2587..b937f894 100644 --- a/fabric-1.16.4/src/main/java/org/dynmap/fabric_1_16_4/event/BlockEvents.java +++ b/fabric-1.16.4/src/main/java/org/dynmap/fabric_1_16_4/event/BlockEvents.java @@ -5,6 +5,11 @@ import net.fabricmc.fabric.api.event.EventFactory; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.math.BlockPos; +import net.minecraft.block.Material; +import net.minecraft.server.network.ServerPlayerEntity; + public class BlockEvents { private BlockEvents() { } @@ -17,7 +22,19 @@ public class BlockEvents { } ); + public static Event SIGN_CHANGE_EVENT = EventFactory.createArrayBacked(SignChangeCallback.class, + (listeners) -> (world, pos, lines, material, player) -> { + for (SignChangeCallback callback : listeners) { + callback.onSignChange(world, pos, lines, material, player); + } + } + ); + public interface BlockCallback { void onBlockEvent(World world, BlockPos pos); } + + public interface SignChangeCallback { + void onSignChange(ServerWorld world, BlockPos pos, String[] lines, Material material, ServerPlayerEntity player); + } } diff --git a/fabric-1.16.4/src/main/java/org/dynmap/fabric_1_16_4/mixin/ServerPlayNetworkHandlerMixin.java b/fabric-1.16.4/src/main/java/org/dynmap/fabric_1_16_4/mixin/ServerPlayNetworkHandlerMixin.java index d103962b..d838d9b7 100644 --- a/fabric-1.16.4/src/main/java/org/dynmap/fabric_1_16_4/mixin/ServerPlayNetworkHandlerMixin.java +++ b/fabric-1.16.4/src/main/java/org/dynmap/fabric_1_16_4/mixin/ServerPlayNetworkHandlerMixin.java @@ -2,12 +2,23 @@ package org.dynmap.fabric_1_16_4.mixin; import net.minecraft.server.network.ServerPlayNetworkHandler; import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.math.BlockPos; +import net.minecraft.block.BlockState; +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.block.entity.SignBlockEntity; +import net.minecraft.network.packet.c2s.play.UpdateSignC2SPacket; +import net.minecraft.text.LiteralText; import org.dynmap.fabric_1_16_4.event.ServerChatEvents; +import org.dynmap.fabric_1_16_4.event.BlockEvents; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.LocalCapture; + +import java.util.List; @Mixin(ServerPlayNetworkHandler.class) public abstract class ServerPlayNetworkHandlerMixin { @@ -25,4 +36,29 @@ public abstract class ServerPlayNetworkHandlerMixin { public void onGameMessage(String string, CallbackInfo info) { ServerChatEvents.EVENT.invoker().onChatMessage(player, string); } + + @Inject( + method = "method_31282", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/block/entity/SignBlockEntity;markDirty()V", + shift = At.Shift.BEFORE + ), + locals = LocalCapture.CAPTURE_FAILHARD + ) + public void onSignUpdate(UpdateSignC2SPacket packet, List signText, CallbackInfo info, + ServerWorld serverWorld, BlockPos blockPos, BlockState blockState, BlockEntity blockEntity, SignBlockEntity signBlockEntity) + { + // Pull the raw text from the input. + String[] rawTexts = new String[4]; + for (int i=0; i Date: Fri, 6 May 2022 16:48:04 +0200 Subject: [PATCH 02/27] add fabric-permission-api provider --- fabric-1.18.2/build.gradle | 6 ++ .../dynmap/fabric_1_18_2/DynmapPlugin.java | 68 ++++++++++++------- .../permissions/FabricPermissions.java | 50 ++++++++++++++ 3 files changed, 98 insertions(+), 26 deletions(-) create mode 100644 fabric-1.18.2/src/main/java/org/dynmap/fabric_1_18_2/permissions/FabricPermissions.java diff --git a/fabric-1.18.2/build.gradle b/fabric-1.18.2/build.gradle index b839b315..ed2622e5 100644 --- a/fabric-1.18.2/build.gradle +++ b/fabric-1.18.2/build.gradle @@ -17,6 +17,10 @@ configurations { implementation.extendsFrom(shadow) } +repositories { + maven { url 'https://oss.sonatype.org/content/repositories/snapshots' } +} + dependencies { minecraft "com.mojang:minecraft:${project.minecraft_version}" mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2" @@ -26,6 +30,8 @@ dependencies { compileOnly group: 'com.google.code.findbugs', name: 'jsr305', version: '3.0.2' shadow project(path: ':DynmapCore', configuration: 'shadow') + + modCompileOnly "me.lucko:fabric-permissions-api:0.1-SNAPSHOT" } processResources { diff --git a/fabric-1.18.2/src/main/java/org/dynmap/fabric_1_18_2/DynmapPlugin.java b/fabric-1.18.2/src/main/java/org/dynmap/fabric_1_18_2/DynmapPlugin.java index 49a1955b..818e9ed9 100644 --- a/fabric-1.18.2/src/main/java/org/dynmap/fabric_1_18_2/DynmapPlugin.java +++ b/fabric-1.18.2/src/main/java/org/dynmap/fabric_1_18_2/DynmapPlugin.java @@ -7,6 +7,7 @@ import net.fabricmc.fabric.api.event.lifecycle.v1.ServerChunkEvents; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerWorldEvents; +import net.fabricmc.loader.api.FabricLoader; import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.block.FluidBlock; @@ -48,6 +49,7 @@ import org.dynmap.fabric_1_18_2.event.CustomServerChunkEvents; import org.dynmap.fabric_1_18_2.event.CustomServerLifecycleEvents; import org.dynmap.fabric_1_18_2.event.PlayerEvents; import org.dynmap.fabric_1_18_2.mixin.BiomeEffectsAccessor; +import org.dynmap.fabric_1_18_2.permissions.FabricPermissions; import org.dynmap.fabric_1_18_2.permissions.FilePermissions; import org.dynmap.fabric_1_18_2.permissions.OpPermissions; import org.dynmap.fabric_1_18_2.permissions.PermissionProvider; @@ -137,13 +139,13 @@ public class DynmapPlugin { int baseidx = 0; Iterator iter = bsids.iterator(); - DynmapBlockState.Builder bld = new DynmapBlockState.Builder(); + DynmapBlockState.Builder bld = new DynmapBlockState.Builder(); while (iter.hasNext()) { BlockState bs = iter.next(); int idx = bsids.getRawId(bs); if (idx >= stateByID.length) { int plen = stateByID.length; - stateByID = Arrays.copyOf(stateByID, idx*11/10); // grow array by 10% + stateByID = Arrays.copyOf(stateByID, idx * 11 / 10); // grow array by 10% Arrays.fill(stateByID, plen, stateByID.length, DynmapBlockState.AIR); } Block b = bs.getBlock(); @@ -173,16 +175,26 @@ public class DynmapPlugin { //Log.info("statename=" + bn + "[" + statename + "], lightAtten=" + lightAtten); // Fill in base attributes bld.setBaseState(basebs).setStateIndex(idx - baseidx).setBlockName(bn).setStateName(statename).setMaterial(mat.toString()).setLegacyBlockID(idx).setAttenuatesLight(lightAtten); - if (mat.isSolid()) { bld.setSolid(); } - if (mat == Material.AIR) { bld.setAir(); } - if (mat == Material.WOOD) { bld.setLog(); } - if (mat == Material.LEAVES) { bld.setLeaves(); } - if ((!bs.getFluidState().isEmpty()) && !(bs.getBlock() instanceof FluidBlock)) { - bld.setWaterlogged(); - } + if (mat.isSolid()) { + bld.setSolid(); + } + if (mat == Material.AIR) { + bld.setAir(); + } + if (mat == Material.WOOD) { + bld.setLog(); + } + if (mat == Material.LEAVES) { + bld.setLeaves(); + } + if ((!bs.getFluidState().isEmpty()) && !(bs.getBlock() instanceof FluidBlock)) { + bld.setWaterlogged(); + } DynmapBlockState dbs = bld.build(); // Build state stateByID[idx] = dbs; - if (basebs == null) { basebs = dbs; } + if (basebs == null) { + basebs = dbs; + } } } // for (int gidx = 0; gidx < DynmapBlockState.getGlobalIndexMax(); gidx++) { @@ -348,18 +360,16 @@ public class DynmapPlugin { Log.verboseinfo("biome[" + i + "]: hum=" + hum + ", tmp=" + tmp + ", mult=" + Integer.toHexString(watermult)); BiomeMap bmap = BiomeMap.NULL; - if (rl != null) { // If resource location, lookup by this - bmap = BiomeMap.byBiomeResourceLocation(rl); - } - else { - bmap = BiomeMap.byBiomeID(i); + if (rl != null) { // If resource location, lookup by this + bmap = BiomeMap.byBiomeResourceLocation(rl); + } else { + bmap = BiomeMap.byBiomeID(i); } if (bmap.isDefault() || (bmap == BiomeMap.NULL)) { bmap = new BiomeMap((rl != null) ? BiomeMap.NO_INDEX : i, id, tmp, hum, rl); Log.verboseinfo("Add custom biome [" + bmap.toString() + "] (" + i + ")"); cnt++; - } - else { + } else { bmap.setTemperature(tmp); bmap.setRainfall(hum); } @@ -395,11 +405,17 @@ public class DynmapPlugin { /* Set up player login/quit event handler */ registerPlayerLoginListener(); - /* Initialize permissions handler */ - permissions = FilePermissions.create(); - if (permissions == null) { - permissions = new OpPermissions(new String[]{"webchat", "marker.icons", "marker.list", "webregister", "stats", "hide.self", "show.self"}); + if (FabricLoader.getInstance().isModLoaded("fabric-permissions-api-v0")) { + Log.info("Using fabric-permissions-api for access control"); + permissions = new FabricPermissions(); + } else { + /* Initialize permissions handler */ + permissions = FilePermissions.create(); + if (permissions == null) { + permissions = new OpPermissions(new String[]{"webchat", "marker.icons", "marker.list", "webregister", "stats", "hide.self", "show.self"}); + } } + /* Get and initialize data folder */ File dataDirectory = new File("dynmap"); @@ -628,14 +644,14 @@ public class DynmapPlugin { FabricWorld fw = getWorld(world, false); ChunkPos chunkPos = chunk.getPos(); - int ymax = Integer.MIN_VALUE; - int ymin = Integer.MAX_VALUE; + int ymax = Integer.MIN_VALUE; + int ymin = Integer.MAX_VALUE; ChunkSection[] sections = chunk.getSectionArray(); for (int i = 0; i < sections.length; i++) { if ((sections[i] != null) && (!sections[i].isEmpty())) { - int sy = sections[i].getYOffset(); - if (sy < ymin) ymin = sy; - if ((sy+16) > ymax) ymax = sy + 16; + int sy = sections[i].getYOffset(); + if (sy < ymin) ymin = sy; + if ((sy + 16) > ymax) ymax = sy + 16; } } if (ymax != Integer.MIN_VALUE) { diff --git a/fabric-1.18.2/src/main/java/org/dynmap/fabric_1_18_2/permissions/FabricPermissions.java b/fabric-1.18.2/src/main/java/org/dynmap/fabric_1_18_2/permissions/FabricPermissions.java new file mode 100644 index 00000000..8cd65ece --- /dev/null +++ b/fabric-1.18.2/src/main/java/org/dynmap/fabric_1_18_2/permissions/FabricPermissions.java @@ -0,0 +1,50 @@ +package org.dynmap.fabric_1_18_2.permissions; + +import me.lucko.fabric.api.permissions.v0.Permissions; +import net.minecraft.entity.player.PlayerEntity; +import org.dynmap.DynmapCore; +import org.dynmap.Log; +import org.dynmap.fabric_1_18_2.DynmapMod; +import org.dynmap.fabric_1_18_2.DynmapPlugin; + +import java.util.Set; +import java.util.stream.Collectors; + +public class FabricPermissions implements PermissionProvider { + + private String permissionKey(String perm) { + return "dynmap." + perm; + } + + @Override + public Set hasOfflinePermissions(String player, Set perms) { + Log.info("Requesting offline permissions: " + String.join(",", perms) + " for " + player); + return perms.stream() + .filter(perm -> hasOfflinePermission(player, perm)) + .collect(Collectors.toSet()); + } + + @Override + public boolean hasOfflinePermission(String player, String perm) { + Log.info("Requesting offline permission: " + perm + " for " + player); + return DynmapPlugin.plugin.isOp(player.toLowerCase()); + } + + @Override + public boolean has(PlayerEntity player, String permission) { + Log.info("Requesting privilege: " + permission); + return player != null && Permissions.check(player, permissionKey(permission)); + } + + @Override + public boolean hasPermissionNode(PlayerEntity player, String permission) { + if (player != null) { + String name = player.getName().getString().toLowerCase(); + Log.info("Requesting permission node: " + permission + " for " + name); + return DynmapPlugin.plugin.isOp(name); + } + Log.info("Requesting permission node: " + permission); + return false; + } + +} From b2a072c45cc61ecdd43f8908376af7763d2633a8 Mon Sep 17 00:00:00 2001 From: PssbleTrngle Date: Fri, 6 May 2022 19:55:28 +0200 Subject: [PATCH 03/27] LuckPerms permission provider for offline support --- fabric-1.18.2/build.gradle | 2 + .../dynmap/fabric_1_18_2/DynmapPlugin.java | 11 +- .../permissions/FabricPermissions.java | 5 +- .../permissions/LuckPermissions.java | 105 ++++++++++++++++++ 4 files changed, 116 insertions(+), 7 deletions(-) create mode 100644 fabric-1.18.2/src/main/java/org/dynmap/fabric_1_18_2/permissions/LuckPermissions.java diff --git a/fabric-1.18.2/build.gradle b/fabric-1.18.2/build.gradle index ed2622e5..c5e0e773 100644 --- a/fabric-1.18.2/build.gradle +++ b/fabric-1.18.2/build.gradle @@ -18,6 +18,7 @@ configurations { } repositories { + mavenCentral() maven { url 'https://oss.sonatype.org/content/repositories/snapshots' } } @@ -32,6 +33,7 @@ dependencies { shadow project(path: ':DynmapCore', configuration: 'shadow') modCompileOnly "me.lucko:fabric-permissions-api:0.1-SNAPSHOT" + compileOnly 'net.luckperms:api:5.4' } processResources { diff --git a/fabric-1.18.2/src/main/java/org/dynmap/fabric_1_18_2/DynmapPlugin.java b/fabric-1.18.2/src/main/java/org/dynmap/fabric_1_18_2/DynmapPlugin.java index 818e9ed9..f75589c0 100644 --- a/fabric-1.18.2/src/main/java/org/dynmap/fabric_1_18_2/DynmapPlugin.java +++ b/fabric-1.18.2/src/main/java/org/dynmap/fabric_1_18_2/DynmapPlugin.java @@ -49,10 +49,7 @@ import org.dynmap.fabric_1_18_2.event.CustomServerChunkEvents; import org.dynmap.fabric_1_18_2.event.CustomServerLifecycleEvents; import org.dynmap.fabric_1_18_2.event.PlayerEvents; import org.dynmap.fabric_1_18_2.mixin.BiomeEffectsAccessor; -import org.dynmap.fabric_1_18_2.permissions.FabricPermissions; -import org.dynmap.fabric_1_18_2.permissions.FilePermissions; -import org.dynmap.fabric_1_18_2.permissions.OpPermissions; -import org.dynmap.fabric_1_18_2.permissions.PermissionProvider; +import org.dynmap.fabric_1_18_2.permissions.*; import org.dynmap.permissions.PermissionsHandler; import org.dynmap.renderer.DynmapBlockState; @@ -405,7 +402,11 @@ public class DynmapPlugin { /* Set up player login/quit event handler */ registerPlayerLoginListener(); - if (FabricLoader.getInstance().isModLoaded("fabric-permissions-api-v0")) { + if (FabricLoader.getInstance().isModLoaded("luckperms")) { + Log.info("Using luckperms for access control"); + permissions = new LuckPermissions(); + } + else if (FabricLoader.getInstance().isModLoaded("fabric-permissions-api-v0")) { Log.info("Using fabric-permissions-api for access control"); permissions = new FabricPermissions(); } else { diff --git a/fabric-1.18.2/src/main/java/org/dynmap/fabric_1_18_2/permissions/FabricPermissions.java b/fabric-1.18.2/src/main/java/org/dynmap/fabric_1_18_2/permissions/FabricPermissions.java index 8cd65ece..feb58ac2 100644 --- a/fabric-1.18.2/src/main/java/org/dynmap/fabric_1_18_2/permissions/FabricPermissions.java +++ b/fabric-1.18.2/src/main/java/org/dynmap/fabric_1_18_2/permissions/FabricPermissions.java @@ -2,16 +2,17 @@ package org.dynmap.fabric_1_18_2.permissions; import me.lucko.fabric.api.permissions.v0.Permissions; import net.minecraft.entity.player.PlayerEntity; -import org.dynmap.DynmapCore; import org.dynmap.Log; -import org.dynmap.fabric_1_18_2.DynmapMod; import org.dynmap.fabric_1_18_2.DynmapPlugin; +import org.dynmap.json.simple.parser.JSONParser; import java.util.Set; import java.util.stream.Collectors; public class FabricPermissions implements PermissionProvider { + private final JSONParser parser = new JSONParser(); + private String permissionKey(String perm) { return "dynmap." + perm; } diff --git a/fabric-1.18.2/src/main/java/org/dynmap/fabric_1_18_2/permissions/LuckPermissions.java b/fabric-1.18.2/src/main/java/org/dynmap/fabric_1_18_2/permissions/LuckPermissions.java new file mode 100644 index 00000000..f98fd208 --- /dev/null +++ b/fabric-1.18.2/src/main/java/org/dynmap/fabric_1_18_2/permissions/LuckPermissions.java @@ -0,0 +1,105 @@ +package org.dynmap.fabric_1_18_2.permissions; + +import me.lucko.fabric.api.permissions.v0.Permissions; +import net.luckperms.api.LuckPerms; +import net.luckperms.api.LuckPermsProvider; +import net.luckperms.api.cacheddata.CachedPermissionData; +import net.luckperms.api.model.user.User; +import net.luckperms.api.util.Tristate; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.server.MinecraftServer; +import org.dynmap.Log; +import org.dynmap.fabric_1_18_2.DynmapPlugin; +import org.dynmap.json.simple.JSONArray; +import org.dynmap.json.simple.JSONObject; +import org.dynmap.json.simple.parser.JSONParser; +import org.dynmap.json.simple.parser.ParseException; + +import java.io.BufferedReader; +import java.io.FileReader; +import java.io.IOException; +import java.util.Optional; +import java.util.Set; +import java.util.UUID; +import java.util.stream.Collectors; + +public class LuckPermissions implements PermissionProvider { + + private final JSONParser parser = new JSONParser(); + private LuckPerms api = null; + + private Optional getApi() { + if (api != null) return Optional.of(api); + try { + api = LuckPermsProvider.get(); + return Optional.of(api); + } catch (Exception ex) { + Log.warning("Trying to access LuckPerms before it has loaded"); + return Optional.empty(); + } + } + + private Optional cachedUUID(String username) { + try { + BufferedReader reader = new BufferedReader(new FileReader(MinecraftServer.USER_CACHE_FILE)); + JSONArray cache = (JSONArray) parser.parse(reader); + for (Object it : cache) { + JSONObject user = (JSONObject) it; + if (user.get("name").toString().equalsIgnoreCase(username)) { + String uuid = user.get("uuid").toString(); + Log.info("Found cached UUID for " + username + ": " + uuid); + return Optional.of(UUID.fromString(uuid)); + } + } + + reader.close(); + } catch (IOException | ParseException ex) { + Log.warning("Unable to read usercache.json"); + } + + return Optional.empty(); + } + + private String permissionKey(String perm) { + return "dynmap." + perm; + } + + @Override + public Set hasOfflinePermissions(String player, Set perms) { + Log.info("Requesting offline permissions: " + String.join(",", perms) + " for " + player); + return perms.stream() + .filter(perm -> hasOfflinePermission(player, perm)) + .collect(Collectors.toSet()); + } + + @Override + public boolean hasOfflinePermission(String player, String perm) { + Log.info("Requesting offline permission: " + perm + " for " + player); + if (DynmapPlugin.plugin.isOp(player.toLowerCase())) return true; + Optional api = getApi(); + Optional uuid = cachedUUID(player); + if (!uuid.isPresent() || !api.isPresent()) return false; + User user = api.get().getUserManager().loadUser(uuid.get()).join(); + CachedPermissionData permissions = user.getCachedData().getPermissionData(); + Tristate state = permissions.checkPermission(permissionKey(perm)); + return state.asBoolean(); + } + + @Override + public boolean has(PlayerEntity player, String permission) { + Log.info("Requesting privilege: " + permission); + return player != null && Permissions.check(player, permissionKey(permission)); + } + + @Override + public boolean hasPermissionNode(PlayerEntity player, String permission) { + if (player != null) { + String name = player.getName().getString().toLowerCase(); + Log.info("Requesting permission node: " + permission + " for " + name); + return DynmapPlugin.plugin.isOp(name); + } + Log.info("Requesting permission node: " + permission); + return false; + } + +} From 8763ad91e4a4404640648e7f36068749fe3ebca3 Mon Sep 17 00:00:00 2001 From: PssbleTrngle Date: Fri, 6 May 2022 20:02:19 +0200 Subject: [PATCH 04/27] allow op players --- .../dynmap/fabric_1_18_2/permissions/FabricPermissions.java | 5 ++++- .../dynmap/fabric_1_18_2/permissions/LuckPermissions.java | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/fabric-1.18.2/src/main/java/org/dynmap/fabric_1_18_2/permissions/FabricPermissions.java b/fabric-1.18.2/src/main/java/org/dynmap/fabric_1_18_2/permissions/FabricPermissions.java index feb58ac2..a957d6b8 100644 --- a/fabric-1.18.2/src/main/java/org/dynmap/fabric_1_18_2/permissions/FabricPermissions.java +++ b/fabric-1.18.2/src/main/java/org/dynmap/fabric_1_18_2/permissions/FabricPermissions.java @@ -34,7 +34,10 @@ public class FabricPermissions implements PermissionProvider { @Override public boolean has(PlayerEntity player, String permission) { Log.info("Requesting privilege: " + permission); - return player != null && Permissions.check(player, permissionKey(permission)); + if (player == null) return false; + String name = player.getName().getString().toLowerCase(); + if (DynmapPlugin.plugin.isOp(name)) return true; + return Permissions.check(player, permissionKey(permission)); } @Override diff --git a/fabric-1.18.2/src/main/java/org/dynmap/fabric_1_18_2/permissions/LuckPermissions.java b/fabric-1.18.2/src/main/java/org/dynmap/fabric_1_18_2/permissions/LuckPermissions.java index f98fd208..a893563d 100644 --- a/fabric-1.18.2/src/main/java/org/dynmap/fabric_1_18_2/permissions/LuckPermissions.java +++ b/fabric-1.18.2/src/main/java/org/dynmap/fabric_1_18_2/permissions/LuckPermissions.java @@ -88,7 +88,10 @@ public class LuckPermissions implements PermissionProvider { @Override public boolean has(PlayerEntity player, String permission) { Log.info("Requesting privilege: " + permission); - return player != null && Permissions.check(player, permissionKey(permission)); + if (player == null) return false; + String name = player.getName().getString().toLowerCase(); + if (DynmapPlugin.plugin.isOp(name)) return true; + return Permissions.check(player, permissionKey(permission)); } @Override From a2951b798d0bbf12f53082a95eb5bb4a5103a8a8 Mon Sep 17 00:00:00 2001 From: PssbleTrngle Date: Thu, 12 May 2022 15:38:48 +0200 Subject: [PATCH 05/27] remove debug logging --- .../fabric_1_18_2/permissions/FabricPermissions.java | 7 ------- .../dynmap/fabric_1_18_2/permissions/LuckPermissions.java | 6 ------ 2 files changed, 13 deletions(-) diff --git a/fabric-1.18.2/src/main/java/org/dynmap/fabric_1_18_2/permissions/FabricPermissions.java b/fabric-1.18.2/src/main/java/org/dynmap/fabric_1_18_2/permissions/FabricPermissions.java index a957d6b8..c572acc4 100644 --- a/fabric-1.18.2/src/main/java/org/dynmap/fabric_1_18_2/permissions/FabricPermissions.java +++ b/fabric-1.18.2/src/main/java/org/dynmap/fabric_1_18_2/permissions/FabricPermissions.java @@ -11,15 +11,12 @@ import java.util.stream.Collectors; public class FabricPermissions implements PermissionProvider { - private final JSONParser parser = new JSONParser(); - private String permissionKey(String perm) { return "dynmap." + perm; } @Override public Set hasOfflinePermissions(String player, Set perms) { - Log.info("Requesting offline permissions: " + String.join(",", perms) + " for " + player); return perms.stream() .filter(perm -> hasOfflinePermission(player, perm)) .collect(Collectors.toSet()); @@ -27,13 +24,11 @@ public class FabricPermissions implements PermissionProvider { @Override public boolean hasOfflinePermission(String player, String perm) { - Log.info("Requesting offline permission: " + perm + " for " + player); return DynmapPlugin.plugin.isOp(player.toLowerCase()); } @Override public boolean has(PlayerEntity player, String permission) { - Log.info("Requesting privilege: " + permission); if (player == null) return false; String name = player.getName().getString().toLowerCase(); if (DynmapPlugin.plugin.isOp(name)) return true; @@ -44,10 +39,8 @@ public class FabricPermissions implements PermissionProvider { public boolean hasPermissionNode(PlayerEntity player, String permission) { if (player != null) { String name = player.getName().getString().toLowerCase(); - Log.info("Requesting permission node: " + permission + " for " + name); return DynmapPlugin.plugin.isOp(name); } - Log.info("Requesting permission node: " + permission); return false; } diff --git a/fabric-1.18.2/src/main/java/org/dynmap/fabric_1_18_2/permissions/LuckPermissions.java b/fabric-1.18.2/src/main/java/org/dynmap/fabric_1_18_2/permissions/LuckPermissions.java index a893563d..829c8a80 100644 --- a/fabric-1.18.2/src/main/java/org/dynmap/fabric_1_18_2/permissions/LuckPermissions.java +++ b/fabric-1.18.2/src/main/java/org/dynmap/fabric_1_18_2/permissions/LuckPermissions.java @@ -47,7 +47,6 @@ public class LuckPermissions implements PermissionProvider { JSONObject user = (JSONObject) it; if (user.get("name").toString().equalsIgnoreCase(username)) { String uuid = user.get("uuid").toString(); - Log.info("Found cached UUID for " + username + ": " + uuid); return Optional.of(UUID.fromString(uuid)); } } @@ -66,7 +65,6 @@ public class LuckPermissions implements PermissionProvider { @Override public Set hasOfflinePermissions(String player, Set perms) { - Log.info("Requesting offline permissions: " + String.join(",", perms) + " for " + player); return perms.stream() .filter(perm -> hasOfflinePermission(player, perm)) .collect(Collectors.toSet()); @@ -74,7 +72,6 @@ public class LuckPermissions implements PermissionProvider { @Override public boolean hasOfflinePermission(String player, String perm) { - Log.info("Requesting offline permission: " + perm + " for " + player); if (DynmapPlugin.plugin.isOp(player.toLowerCase())) return true; Optional api = getApi(); Optional uuid = cachedUUID(player); @@ -87,7 +84,6 @@ public class LuckPermissions implements PermissionProvider { @Override public boolean has(PlayerEntity player, String permission) { - Log.info("Requesting privilege: " + permission); if (player == null) return false; String name = player.getName().getString().toLowerCase(); if (DynmapPlugin.plugin.isOp(name)) return true; @@ -98,10 +94,8 @@ public class LuckPermissions implements PermissionProvider { public boolean hasPermissionNode(PlayerEntity player, String permission) { if (player != null) { String name = player.getName().getString().toLowerCase(); - Log.info("Requesting permission node: " + permission + " for " + name); return DynmapPlugin.plugin.isOp(name); } - Log.info("Requesting permission node: " + permission); return false; } From 505d78a8e0a8f3c1d6fb4d660ea5aafd9fb84bb5 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin Date: Thu, 12 May 2022 19:59:32 +0300 Subject: [PATCH 06/27] fix: support special symbols in world names Fix #3755 --- DynmapCore/src/main/resources/extracted/web/js/map.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DynmapCore/src/main/resources/extracted/web/js/map.js b/DynmapCore/src/main/resources/extracted/web/js/map.js index 0bbcd9f7..a0ec24b6 100644 --- a/DynmapCore/src/main/resources/extracted/web/js/map.js +++ b/DynmapCore/src/main/resources/extracted/web/js/map.js @@ -74,7 +74,7 @@ DynMap.prototype = { formatUrl: function(name, options) { var url = this.options.url[name]; $.each(options, function(n,v) { - url = url.replace("{" + n + "}", v); + url = url.replace("{" + n + "}", encodeURIComponent(v)); }); return url; }, From bf4f31c3807d39397ac822db0303a418ddad6155 Mon Sep 17 00:00:00 2001 From: Kosma Moczek Date: Sun, 29 May 2022 12:23:33 +0200 Subject: [PATCH 07/27] gradle: update to 7.4.2 --- gradle/wrapper/gradle-wrapper.jar | Bin 56177 -> 59536 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 286 ++++++++++++++--------- gradlew.bat | 43 ++-- 4 files changed, 199 insertions(+), 132 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 29953ea141f55e3b8fc691d31b5ca8816d89fa87..7454180f2ae8848c63b8b4dea2cb829da983f2fa 100644 GIT binary patch delta 51385 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

8j~^e*5P?UYQ`^~!nLb#D_{DdBU_KYFbP>Bi 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%0A}15$O#mvChbGF@eh4Ar%3syAIE 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�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 \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null + +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` +APP_BASE_NAME=${0##*/} # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" +MAX_FD=maximum warn () { echo "$*" -} +} >&2 die () { echo echo "$*" echo exit 1 -} +} >&2 # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACMD=$JAVA_HOME/jre/sh/java else - JAVACMD="$JAVA_HOME/bin/java" + JAVACMD=$JAVA_HOME/bin/java fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME @@ -81,7 +132,7 @@ Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else - JAVACMD="java" + JAVACMD=java which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the @@ -89,84 +140,95 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi -fi - -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi - -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi - # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" - fi - i=$((i+1)) - done - case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" esac fi -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=$(save "$@") +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) -# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong -if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then - cd "$(dirname "$0")" + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done fi +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat index e95643d6..ac1b06f9 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -1,3 +1,19 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + @if "%DEBUG%" == "" @echo off @rem ########################################################################## @rem @@ -13,15 +29,18 @@ if "%DIRNAME%" == "" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init +if "%ERRORLEVEL%" == "0" goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -35,7 +54,7 @@ goto fail set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe -if exist "%JAVA_EXE%" goto init +if exist "%JAVA_EXE%" goto execute echo. echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% @@ -45,28 +64,14 @@ echo location of your Java installation. goto fail -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* - :execute @rem Setup the command line set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* :end @rem End local scope for the variables with windows NT shell From 16b30ee40fce5fa751c00226fcc63051d2cfaf93 Mon Sep 17 00:00:00 2001 From: Kosma Moczek Date: Thu, 19 May 2022 17:11:13 +0200 Subject: [PATCH 08/27] fabric-1.19: copy from fabric-1.18.2 --- fabric-1.19/.gitignore | 32 + fabric-1.19/build.gradle | 59 ++ fabric-1.19/gradle.properties | 4 + .../org/dynmap/fabric_1_18_2/DynmapMod.java | 50 ++ .../dynmap/fabric_1_18_2/DynmapPlugin.java | 794 ++++++++++++++++++ .../dynmap/fabric_1_18_2/FabricAdapter.java | 13 + .../fabric_1_18_2/FabricCommandSender.java | 47 ++ .../dynmap/fabric_1_18_2/FabricLogger.java | 49 ++ .../fabric_1_18_2/FabricMapChunkCache.java | 103 +++ .../dynmap/fabric_1_18_2/FabricPlayer.java | 252 ++++++ .../dynmap/fabric_1_18_2/FabricServer.java | 609 ++++++++++++++ .../org/dynmap/fabric_1_18_2/FabricWorld.java | 229 +++++ .../java/org/dynmap/fabric_1_18_2/NBT.java | 126 +++ .../org/dynmap/fabric_1_18_2/TaskRecord.java | 38 + .../dynmap/fabric_1_18_2/VersionCheck.java | 98 +++ .../access/ProtoChunkAccessor.java | 5 + .../fabric_1_18_2/command/DmapCommand.java | 9 + .../fabric_1_18_2/command/DmarkerCommand.java | 9 + .../fabric_1_18_2/command/DynmapCommand.java | 9 + .../command/DynmapCommandExecutor.java | 63 ++ .../command/DynmapExpCommand.java | 9 + .../fabric_1_18_2/event/BlockEvents.java | 40 + .../event/CustomServerChunkEvents.java | 21 + .../event/CustomServerLifecycleEvents.java | 14 + .../fabric_1_18_2/event/PlayerEvents.java | 62 ++ .../fabric_1_18_2/event/ServerChatEvents.java | 23 + .../mixin/BiomeEffectsAccessor.java | 11 + .../mixin/MinecraftServerMixin.java | 16 + .../mixin/PlayerManagerMixin.java | 29 + .../fabric_1_18_2/mixin/ProtoChunkMixin.java | 30 + .../mixin/ServerPlayNetworkHandlerMixin.java | 66 ++ .../mixin/ServerPlayerEntityMixin.java | 30 + .../mixin/ThreadedAnvilChunkStorageMixin.java | 32 + .../fabric_1_18_2/mixin/WorldChunkMixin.java | 25 + .../permissions/FilePermissions.java | 103 +++ .../permissions/OpPermissions.java | 52 ++ .../permissions/PermissionProvider.java | 16 + .../src/main/resources/assets/dynmap/icon.png | Bin 0 -> 34043 bytes .../src/main/resources/configuration.txt | 491 +++++++++++ .../src/main/resources/dynmap.mixins.json | 19 + .../src/main/resources/fabric.mod.json | 33 + .../main/resources/permissions.yml.example | 27 + 42 files changed, 3747 insertions(+) create mode 100644 fabric-1.19/.gitignore create mode 100644 fabric-1.19/build.gradle create mode 100644 fabric-1.19/gradle.properties create mode 100644 fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/DynmapMod.java create mode 100644 fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/DynmapPlugin.java create mode 100644 fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/FabricAdapter.java create mode 100644 fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/FabricCommandSender.java create mode 100644 fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/FabricLogger.java create mode 100644 fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/FabricMapChunkCache.java create mode 100644 fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/FabricPlayer.java create mode 100644 fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/FabricServer.java create mode 100644 fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/FabricWorld.java create mode 100644 fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/NBT.java create mode 100644 fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/TaskRecord.java create mode 100644 fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/VersionCheck.java create mode 100644 fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/access/ProtoChunkAccessor.java create mode 100644 fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/command/DmapCommand.java create mode 100644 fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/command/DmarkerCommand.java create mode 100644 fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/command/DynmapCommand.java create mode 100644 fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/command/DynmapCommandExecutor.java create mode 100644 fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/command/DynmapExpCommand.java create mode 100644 fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/event/BlockEvents.java create mode 100644 fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/event/CustomServerChunkEvents.java create mode 100644 fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/event/CustomServerLifecycleEvents.java create mode 100644 fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/event/PlayerEvents.java create mode 100644 fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/event/ServerChatEvents.java create mode 100644 fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/mixin/BiomeEffectsAccessor.java create mode 100644 fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/mixin/MinecraftServerMixin.java create mode 100644 fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/mixin/PlayerManagerMixin.java create mode 100644 fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/mixin/ProtoChunkMixin.java create mode 100644 fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/mixin/ServerPlayNetworkHandlerMixin.java create mode 100644 fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/mixin/ServerPlayerEntityMixin.java create mode 100644 fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/mixin/ThreadedAnvilChunkStorageMixin.java create mode 100644 fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/mixin/WorldChunkMixin.java create mode 100644 fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/permissions/FilePermissions.java create mode 100644 fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/permissions/OpPermissions.java create mode 100644 fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/permissions/PermissionProvider.java create mode 100644 fabric-1.19/src/main/resources/assets/dynmap/icon.png create mode 100644 fabric-1.19/src/main/resources/configuration.txt create mode 100644 fabric-1.19/src/main/resources/dynmap.mixins.json create mode 100644 fabric-1.19/src/main/resources/fabric.mod.json create mode 100644 fabric-1.19/src/main/resources/permissions.yml.example diff --git a/fabric-1.19/.gitignore b/fabric-1.19/.gitignore new file mode 100644 index 00000000..8b87af68 --- /dev/null +++ b/fabric-1.19/.gitignore @@ -0,0 +1,32 @@ +# gradle + +.gradle/ +build/ +out/ +classes/ + +# eclipse + +*.launch + +# idea + +.idea/ +*.iml +*.ipr +*.iws + +# vscode + +.settings/ +.vscode/ +bin/ +.classpath +.project + +# fabric + +run/ + +# other +*.log diff --git a/fabric-1.19/build.gradle b/fabric-1.19/build.gradle new file mode 100644 index 00000000..570efaf4 --- /dev/null +++ b/fabric-1.19/build.gradle @@ -0,0 +1,59 @@ +plugins { + id 'fabric-loom' version '0.11-SNAPSHOT' +} + +archivesBaseName = "Dynmap" +version = parent.version +group = parent.group + +eclipse { + project { + name = "Dynmap(Fabric-1.19)" + } +} + +configurations { + shadow + implementation.extendsFrom(shadow) +} + +dependencies { + minecraft "com.mojang:minecraft:${project.minecraft_version}" + mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2" + modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" + modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" + + compileOnly group: 'com.google.code.findbugs', name: 'jsr305', version: '3.0.2' + + shadow project(path: ':DynmapCore', configuration: 'shadow') +} + +processResources { + filesMatching('fabric.mod.json') { + expand "version": project.version + } +} + +java { + // Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task + // if it is present. + // If you remove this line, sources will not be generated. + withSourcesJar() +} + +jar { + from "LICENSE" + from { + configurations.shadow.collect { it.toString().contains("guava") ? null : it.isDirectory() ? it : zipTree(it) } + } +} + +remapJar { + archiveFileName = "${archivesBaseName}-${project.version}-fabric-${project.minecraft_version}.jar" + destinationDirectory = file '../target' +} + +remapJar.doLast { + task -> + ant.checksum file: task.archivePath +} diff --git a/fabric-1.19/gradle.properties b/fabric-1.19/gradle.properties new file mode 100644 index 00000000..bdb66d3a --- /dev/null +++ b/fabric-1.19/gradle.properties @@ -0,0 +1,4 @@ +minecraft_version=1.18.2 +yarn_mappings=1.18.2+build.1 +loader_version=0.13.3 +fabric_version=0.47.8+1.18.2 diff --git a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/DynmapMod.java b/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/DynmapMod.java new file mode 100644 index 00000000..db446234 --- /dev/null +++ b/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/DynmapMod.java @@ -0,0 +1,50 @@ +package org.dynmap.fabric_1_18_2; + +import net.fabricmc.api.ModInitializer; +import net.fabricmc.loader.api.FabricLoader; +import net.fabricmc.loader.api.ModContainer; +import org.dynmap.DynmapCore; +import org.dynmap.Log; + +import java.io.File; +import java.net.URISyntaxException; +import java.nio.file.Path; +import java.nio.file.Paths; + +public class DynmapMod implements ModInitializer { + private static final String MODID = "dynmap"; + private static final ModContainer MOD_CONTAINER = FabricLoader.getInstance().getModContainer(MODID) + .orElseThrow(() -> new RuntimeException("Failed to get mod container: " + MODID)); + // The instance of your mod that Fabric uses. + public static DynmapMod instance; + + public static DynmapPlugin plugin; + public static File jarfile; + public static String ver; + public static boolean useforcedchunks; + + @Override + public void onInitialize() { + instance = this; + + Path path = MOD_CONTAINER.getRootPath(); + try { + jarfile = new File(DynmapCore.class.getProtectionDomain().getCodeSource().getLocation().toURI()); + } catch (URISyntaxException e) { + Log.severe("Unable to get DynmapCore jar path", e); + } + + if (path.getFileSystem().provider().getScheme().equals("jar")) { + path = Paths.get(path.getFileSystem().toString()); + jarfile = path.toFile(); + } + + ver = MOD_CONTAINER.getMetadata().getVersion().getFriendlyString(); + + Log.setLogger(new FabricLogger()); + org.dynmap.modsupport.ModSupportImpl.init(); + + // Initialize the plugin, we will enable it fully when the server starts. + plugin = new DynmapPlugin(); + } +} diff --git a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/DynmapPlugin.java b/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/DynmapPlugin.java new file mode 100644 index 00000000..49a1955b --- /dev/null +++ b/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/DynmapPlugin.java @@ -0,0 +1,794 @@ +package org.dynmap.fabric_1_18_2; + +import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import net.fabricmc.fabric.api.command.v1.CommandRegistrationCallback; +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerChunkEvents; +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents; +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerWorldEvents; +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.block.FluidBlock; +import net.minecraft.block.Material; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.Item; +import net.minecraft.network.ClientConnection; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.server.network.ServerPlayNetworkHandler; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.Identifier; +import net.minecraft.util.collection.IdList; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.ChunkPos; +import net.minecraft.util.registry.Registry; +import net.minecraft.world.EmptyBlockView; +import net.minecraft.world.World; +import net.minecraft.world.WorldAccess; +import net.minecraft.world.biome.Biome; +import net.minecraft.world.chunk.Chunk; +import net.minecraft.world.chunk.ChunkSection; +import net.minecraft.world.chunk.ChunkStatus; +import net.minecraft.world.chunk.WorldChunk; + +import org.dynmap.*; +import org.dynmap.common.BiomeMap; +import org.dynmap.common.DynmapCommandSender; +import org.dynmap.common.DynmapListenerManager; +import org.dynmap.common.DynmapPlayer; +import org.dynmap.common.chunk.GenericChunkCache; +import org.dynmap.fabric_1_18_2.command.DmapCommand; +import org.dynmap.fabric_1_18_2.command.DmarkerCommand; +import org.dynmap.fabric_1_18_2.command.DynmapCommand; +import org.dynmap.fabric_1_18_2.command.DynmapExpCommand; +import org.dynmap.fabric_1_18_2.event.BlockEvents; +import org.dynmap.fabric_1_18_2.event.CustomServerChunkEvents; +import org.dynmap.fabric_1_18_2.event.CustomServerLifecycleEvents; +import org.dynmap.fabric_1_18_2.event.PlayerEvents; +import org.dynmap.fabric_1_18_2.mixin.BiomeEffectsAccessor; +import org.dynmap.fabric_1_18_2.permissions.FilePermissions; +import org.dynmap.fabric_1_18_2.permissions.OpPermissions; +import org.dynmap.fabric_1_18_2.permissions.PermissionProvider; +import org.dynmap.permissions.PermissionsHandler; +import org.dynmap.renderer.DynmapBlockState; + +import java.io.File; +import java.util.*; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.regex.Pattern; + +public class DynmapPlugin { + // FIXME: Fix package-private fields after splitting is done + DynmapCore core; + private PermissionProvider permissions; + private boolean core_enabled; + public GenericChunkCache sscache; + public PlayerList playerList; + MapManager mapManager; + /** + * Server is set when running and unset at shutdown. + */ + private net.minecraft.server.MinecraftServer server; + public static DynmapPlugin plugin; + ChatHandler chathandler; + private HashMap sortWeights = new HashMap(); + private HashMap worlds = new HashMap(); + private WorldAccess last_world; + private FabricWorld last_fworld; + private Map players = new HashMap(); + private FabricServer fserver; + private boolean tickregistered = false; + // TPS calculator + double tps; + long lasttick; + long avgticklen; + // Per tick limit, in nsec + long perTickLimit = (50000000); // 50 ms + private boolean useSaveFolder = true; + + private static final String[] TRIGGER_DEFAULTS = {"blockupdate", "chunkpopulate", "chunkgenerate"}; + + static final Pattern patternControlCode = Pattern.compile("(?i)\\u00A7[0-9A-FK-OR]"); + + DynmapPlugin() { + plugin = this; + // Fabric events persist between server instances + ServerLifecycleEvents.SERVER_STARTING.register(this::serverStart); + CommandRegistrationCallback.EVENT.register((dispatcher, dedicated) -> registerCommands(dispatcher)); + CustomServerLifecycleEvents.SERVER_STARTED_PRE_WORLD_LOAD.register(this::serverStarted); + ServerLifecycleEvents.SERVER_STOPPING.register(this::serverStop); + } + + int getSortWeight(String name) { + return sortWeights.getOrDefault(name, 0); + } + + void setSortWeight(String name, int wt) { + sortWeights.put(name, wt); + } + + void dropSortWeight(String name) { + sortWeights.remove(name); + } + + public static class BlockUpdateRec { + WorldAccess w; + String wid; + int x, y, z; + } + + ConcurrentLinkedQueue blockupdatequeue = new ConcurrentLinkedQueue(); + + public static DynmapBlockState[] stateByID; + + /** + * Initialize block states (org.dynmap.blockstate.DynmapBlockState) + */ + public void initializeBlockStates() { + stateByID = new DynmapBlockState[512 * 32]; // Simple map - scale as needed + Arrays.fill(stateByID, DynmapBlockState.AIR); // Default to air + + IdList bsids = Block.STATE_IDS; + + DynmapBlockState basebs = null; + Block baseb = null; + int baseidx = 0; + + Iterator iter = bsids.iterator(); + DynmapBlockState.Builder bld = new DynmapBlockState.Builder(); + while (iter.hasNext()) { + BlockState bs = iter.next(); + int idx = bsids.getRawId(bs); + if (idx >= stateByID.length) { + int plen = stateByID.length; + stateByID = Arrays.copyOf(stateByID, idx*11/10); // grow array by 10% + Arrays.fill(stateByID, plen, stateByID.length, DynmapBlockState.AIR); + } + Block b = bs.getBlock(); + // If this is new block vs last, it's the base block state + if (b != baseb) { + basebs = null; + baseidx = idx; + baseb = b; + } + + Identifier ui = Registry.BLOCK.getId(b); + if (ui == null) { + continue; + } + String bn = ui.getNamespace() + ":" + ui.getPath(); + // Only do defined names, and not "air" + if (!bn.equals(DynmapBlockState.AIR_BLOCK)) { + Material mat = bs.getMaterial(); + String statename = ""; + for (net.minecraft.state.property.Property p : bs.getProperties()) { + if (statename.length() > 0) { + statename += ","; + } + statename += p.getName() + "=" + bs.get(p).toString(); + } + int lightAtten = bs.isOpaqueFullCube(EmptyBlockView.INSTANCE, BlockPos.ORIGIN) ? 15 : (bs.isTranslucent(EmptyBlockView.INSTANCE, BlockPos.ORIGIN) ? 0 : 1); + //Log.info("statename=" + bn + "[" + statename + "], lightAtten=" + lightAtten); + // Fill in base attributes + bld.setBaseState(basebs).setStateIndex(idx - baseidx).setBlockName(bn).setStateName(statename).setMaterial(mat.toString()).setLegacyBlockID(idx).setAttenuatesLight(lightAtten); + if (mat.isSolid()) { bld.setSolid(); } + if (mat == Material.AIR) { bld.setAir(); } + if (mat == Material.WOOD) { bld.setLog(); } + if (mat == Material.LEAVES) { bld.setLeaves(); } + if ((!bs.getFluidState().isEmpty()) && !(bs.getBlock() instanceof FluidBlock)) { + bld.setWaterlogged(); + } + DynmapBlockState dbs = bld.build(); // Build state + stateByID[idx] = dbs; + if (basebs == null) { basebs = dbs; } + } + } +// for (int gidx = 0; gidx < DynmapBlockState.getGlobalIndexMax(); gidx++) { +// DynmapBlockState bs = DynmapBlockState.getStateByGlobalIndex(gidx); +// Log.info(gidx + ":" + bs.toString() + ", gidx=" + bs.globalStateIndex + ", sidx=" + bs.stateIndex); +// } + } + + public static final Item getItemByID(int id) { + return Item.byRawId(id); + } + + public static final ClientConnection getNetworkManager(ServerPlayNetworkHandler nh) { + return nh.connection; + } + + FabricPlayer getOrAddPlayer(ServerPlayerEntity player) { + String name = player.getName().getString(); + FabricPlayer fp = players.get(name); + if (fp != null) { + fp.player = player; + } else { + fp = new FabricPlayer(this, player); + players.put(name, fp); + } + return fp; + } + + static class ChatMessage { + String message; + ServerPlayerEntity sender; + } + + ConcurrentLinkedQueue msgqueue = new ConcurrentLinkedQueue(); + + public static class ChatHandler { + private final DynmapPlugin plugin; + + ChatHandler(DynmapPlugin plugin) { + this.plugin = plugin; + } + + public void handleChat(ServerPlayerEntity player, String message) { + if (!message.startsWith("/")) { + ChatMessage cm = new ChatMessage(); + cm.message = message; + cm.sender = player; + plugin.msgqueue.add(cm); + } + } + } + + public FabricServer getFabricServer() { + return fserver; + } + + private void serverStart(MinecraftServer server) { + // Set the server so we don't NPE during setup + this.server = server; + this.fserver = new FabricServer(this, server); + this.onEnable(); + } + + private void serverStarted(MinecraftServer server) { + this.onStart(); + if (core != null) { + core.serverStarted(); + } + } + + private void serverStop(MinecraftServer server) { + this.onDisable(); + this.server = null; + } + + public boolean isOp(String player) { + String[] ops = server.getPlayerManager().getOpList().getNames(); + + for (String op : ops) { + if (op.equalsIgnoreCase(player)) { + return true; + } + } + + // TODO: Consider whether cheats are enabled for integrated server + return server.isSingleplayer() && player.equalsIgnoreCase(server.getSinglePlayerName()); + } + + boolean hasPerm(PlayerEntity psender, String permission) { + PermissionsHandler ph = PermissionsHandler.getHandler(); + if ((ph != null) && (psender != null) && ph.hasPermission(psender.getName().getString(), permission)) { + return true; + } + return permissions.has(psender, permission); + } + + boolean hasPermNode(PlayerEntity psender, String permission) { + PermissionsHandler ph = PermissionsHandler.getHandler(); + if ((ph != null) && (psender != null) && ph.hasPermissionNode(psender.getName().getString(), permission)) { + return true; + } + return permissions.hasPermissionNode(psender, permission); + } + + Set hasOfflinePermissions(String player, Set perms) { + Set rslt = null; + PermissionsHandler ph = PermissionsHandler.getHandler(); + if (ph != null) { + rslt = ph.hasOfflinePermissions(player, perms); + } + Set rslt2 = hasOfflinePermissions(player, perms); + if ((rslt != null) && (rslt2 != null)) { + Set newrslt = new HashSet(rslt); + newrslt.addAll(rslt2); + rslt = newrslt; + } else if (rslt2 != null) { + rslt = rslt2; + } + return rslt; + } + + boolean hasOfflinePermission(String player, String perm) { + PermissionsHandler ph = PermissionsHandler.getHandler(); + if (ph != null) { + if (ph.hasOfflinePermission(player, perm)) { + return true; + } + } + return permissions.hasOfflinePermission(player, perm); + } + + void setChatHandler(ChatHandler chatHandler) { + plugin.chathandler = chatHandler; + } + + public class TexturesPayload { + public long timestamp; + public String profileId; + public String profileName; + public boolean isPublic; + public Map textures; + + } + + public class ProfileTexture { + public String url; + } + + public void loadExtraBiomes(String mcver) { + int cnt = 0; + BiomeMap.loadWellKnownByVersion(mcver); + + Registry biomeRegistry = getFabricServer().getBiomeRegistry(); + Biome[] list = getFabricServer().getBiomeList(biomeRegistry); + + for (int i = 0; i < list.length; i++) { + Biome bb = list[i]; + if (bb != null) { + String id = biomeRegistry.getId(bb).getPath(); + String rl = biomeRegistry.getId(bb).toString(); + float tmp = bb.getTemperature(), hum = bb.getDownfall(); + int watermult = ((BiomeEffectsAccessor) bb.getEffects()).getWaterColor(); + Log.verboseinfo("biome[" + i + "]: hum=" + hum + ", tmp=" + tmp + ", mult=" + Integer.toHexString(watermult)); + + BiomeMap bmap = BiomeMap.NULL; + if (rl != null) { // If resource location, lookup by this + bmap = BiomeMap.byBiomeResourceLocation(rl); + } + else { + bmap = BiomeMap.byBiomeID(i); + } + if (bmap.isDefault() || (bmap == BiomeMap.NULL)) { + bmap = new BiomeMap((rl != null) ? BiomeMap.NO_INDEX : i, id, tmp, hum, rl); + Log.verboseinfo("Add custom biome [" + bmap.toString() + "] (" + i + ")"); + cnt++; + } + else { + bmap.setTemperature(tmp); + bmap.setRainfall(hum); + } + if (watermult != -1) { + bmap.setWaterColorMultiplier(watermult); + Log.verboseinfo("Set watercolormult for " + bmap.toString() + " (" + i + ") to " + Integer.toHexString(watermult)); + } + } + } + if (cnt > 0) + Log.info("Added " + cnt + " custom biome mappings"); + } + + private String[] getBiomeNames() { + Registry biomeRegistry = getFabricServer().getBiomeRegistry(); + Biome[] list = getFabricServer().getBiomeList(biomeRegistry); + String[] lst = new String[list.length]; + for (int i = 0; i < list.length; i++) { + Biome bb = list[i]; + if (bb != null) { + lst[i] = biomeRegistry.getId(bb).getPath(); + } + } + return lst; + } + + public void onEnable() { + /* Get MC version */ + String mcver = server.getVersion(); + + /* Load extra biomes */ + loadExtraBiomes(mcver); + /* Set up player login/quit event handler */ + registerPlayerLoginListener(); + + /* Initialize permissions handler */ + permissions = FilePermissions.create(); + if (permissions == null) { + permissions = new OpPermissions(new String[]{"webchat", "marker.icons", "marker.list", "webregister", "stats", "hide.self", "show.self"}); + } + /* Get and initialize data folder */ + File dataDirectory = new File("dynmap"); + + if (!dataDirectory.exists()) { + dataDirectory.mkdirs(); + } + + /* Instantiate core */ + if (core == null) { + core = new DynmapCore(); + } + + /* Inject dependencies */ + core.setPluginJarFile(DynmapMod.jarfile); + core.setPluginVersion(DynmapMod.ver); + core.setMinecraftVersion(mcver); + core.setDataFolder(dataDirectory); + core.setServer(fserver); + core.setTriggerDefault(TRIGGER_DEFAULTS); + core.setBiomeNames(getBiomeNames()); + + if (!core.initConfiguration(null)) { + return; + } + // Extract default permission example, if needed + File filepermexample = new File(core.getDataFolder(), "permissions.yml.example"); + core.createDefaultFileFromResource("/permissions.yml.example", filepermexample); + + DynmapCommonAPIListener.apiInitialized(core); + } + + private DynmapCommand dynmapCmd; + private DmapCommand dmapCmd; + private DmarkerCommand dmarkerCmd; + private DynmapExpCommand dynmapexpCmd; + + public void registerCommands(CommandDispatcher cd) { + dynmapCmd = new DynmapCommand(this); + dmapCmd = new DmapCommand(this); + dmarkerCmd = new DmarkerCommand(this); + dynmapexpCmd = new DynmapExpCommand(this); + dynmapCmd.register(cd); + dmapCmd.register(cd); + dmarkerCmd.register(cd); + dynmapexpCmd.register(cd); + + Log.info("Register commands"); + } + + public void onStart() { + initializeBlockStates(); + /* Enable core */ + if (!core.enableCore(null)) { + return; + } + core_enabled = true; + VersionCheck.runCheck(core); + // Get per tick time limit + perTickLimit = core.getMaxTickUseMS() * 1000000; + // Prep TPS + lasttick = System.nanoTime(); + tps = 20.0; + + /* Register tick handler */ + if (!tickregistered) { + ServerTickEvents.END_SERVER_TICK.register(server -> fserver.tickEvent(server)); + tickregistered = true; + } + + playerList = core.playerList; + sscache = new GenericChunkCache(core.getSnapShotCacheSize(), core.useSoftRefInSnapShotCache()); + /* Get map manager from core */ + mapManager = core.getMapManager(); + + /* Load saved world definitions */ + loadWorlds(); + + for (FabricWorld w : worlds.values()) { + if (core.processWorldLoad(w)) { /* Have core process load first - fire event listeners if good load after */ + if (w.isLoaded()) { + core.listenerManager.processWorldEvent(DynmapListenerManager.EventType.WORLD_LOAD, w); + } + } + } + core.updateConfigHashcode(); + + /* Register our update trigger events */ + registerEvents(); + Log.info("Register events"); + + //DynmapCommonAPIListener.apiInitialized(core); + + Log.info("Enabled"); + } + + public void onDisable() { + DynmapCommonAPIListener.apiTerminated(); + + //if (metrics != null) { + // metrics.stop(); + // metrics = null; + //} + /* Save worlds */ + saveWorlds(); + + /* Purge tick queue */ + fserver.clearTaskQueue(); + + /* Disable core */ + core.disableCore(); + core_enabled = false; + + if (sscache != null) { + sscache.cleanup(); + sscache = null; + } + + Log.info("Disabled"); + } + + // TODO: Clean a bit + public void handleCommand(ServerCommandSource commandSource, String cmd, String[] args) throws CommandSyntaxException { + DynmapCommandSender dsender; + ServerPlayerEntity psender = null; + + // getPlayer throws a CommandSyntaxException, so getEntity and instanceof for safety + if (commandSource.getEntity() instanceof ServerPlayerEntity) { + psender = commandSource.getPlayer(); + } + + if (psender != null) { + // FIXME: New Player? Why not query the current player list. + dsender = new FabricPlayer(this, psender); + } else { + dsender = new FabricCommandSender(commandSource); + } + + core.processCommand(dsender, cmd, cmd, args); + } + + public class PlayerTracker { + public void onPlayerLogin(ServerPlayerEntity player) { + if (!core_enabled) return; + final DynmapPlayer dp = getOrAddPlayer(player); + /* This event can be called from off server thread, so push processing there */ + core.getServer().scheduleServerTask(new Runnable() { + public void run() { + core.listenerManager.processPlayerEvent(DynmapListenerManager.EventType.PLAYER_JOIN, dp); + } + }, 2); + } + + public void onPlayerLogout(ServerPlayerEntity player) { + if (!core_enabled) return; + final DynmapPlayer dp = getOrAddPlayer(player); + final String name = player.getName().getString(); + /* This event can be called from off server thread, so push processing there */ + core.getServer().scheduleServerTask(new Runnable() { + public void run() { + core.listenerManager.processPlayerEvent(DynmapListenerManager.EventType.PLAYER_QUIT, dp); + players.remove(name); + } + }, 0); + } + + public void onPlayerChangedDimension(ServerPlayerEntity player) { + if (!core_enabled) return; + getOrAddPlayer(player); // Freshen player object reference + } + + public void onPlayerRespawn(ServerPlayerEntity player) { + if (!core_enabled) return; + getOrAddPlayer(player); // Freshen player object reference + } + } + + private PlayerTracker playerTracker = null; + + private void registerPlayerLoginListener() { + if (playerTracker == null) { + playerTracker = new PlayerTracker(); + PlayerEvents.PLAYER_LOGGED_IN.register(player -> playerTracker.onPlayerLogin(player)); + PlayerEvents.PLAYER_LOGGED_OUT.register(player -> playerTracker.onPlayerLogout(player)); + PlayerEvents.PLAYER_CHANGED_DIMENSION.register(player -> playerTracker.onPlayerChangedDimension(player)); + PlayerEvents.PLAYER_RESPAWN.register(player -> playerTracker.onPlayerRespawn(player)); + } + } + + public class WorldTracker { + public void handleWorldLoad(MinecraftServer server, ServerWorld world) { + if (!core_enabled) return; + + final FabricWorld fw = getWorld(world); + // This event can be called from off server thread, so push processing there + core.getServer().scheduleServerTask(new Runnable() { + public void run() { + if (core.processWorldLoad(fw)) // Have core process load first - fire event listeners if good load after + core.listenerManager.processWorldEvent(DynmapListenerManager.EventType.WORLD_LOAD, fw); + } + }, 0); + } + + public void handleWorldUnload(MinecraftServer server, ServerWorld world) { + if (!core_enabled) return; + + final FabricWorld fw = getWorld(world); + if (fw != null) { + // This event can be called from off server thread, so push processing there + core.getServer().scheduleServerTask(new Runnable() { + public void run() { + core.listenerManager.processWorldEvent(DynmapListenerManager.EventType.WORLD_UNLOAD, fw); + core.processWorldUnload(fw); + } + }, 0); + // Set world unloaded (needs to be immediate, since it may be invalid after event) + fw.setWorldUnloaded(); + // Clean up tracker + //WorldUpdateTracker wut = updateTrackers.remove(fw.getName()); + //if(wut != null) wut.world = null; + } + } + + public void handleChunkGenerate(ServerWorld world, Chunk chunk) { + if (!onchunkgenerate) return; + + FabricWorld fw = getWorld(world, false); + ChunkPos chunkPos = chunk.getPos(); + + int ymax = Integer.MIN_VALUE; + int ymin = Integer.MAX_VALUE; + ChunkSection[] sections = chunk.getSectionArray(); + for (int i = 0; i < sections.length; i++) { + if ((sections[i] != null) && (!sections[i].isEmpty())) { + int sy = sections[i].getYOffset(); + if (sy < ymin) ymin = sy; + if ((sy+16) > ymax) ymax = sy + 16; + } + } + if (ymax != Integer.MIN_VALUE) { + mapManager.touchVolume(fw.getName(), + chunkPos.getStartX(), ymin, chunkPos.getStartZ(), + chunkPos.getEndX(), ymax, chunkPos.getEndZ(), + "chunkgenerate"); + //Log.info("New generated chunk detected at %s[%s]".formatted(fw.getName(), chunkPos.getStartPos())); + } + } + + public void handleBlockEvent(World world, BlockPos pos) { + if (!core_enabled) return; + if (!onblockchange) return; + if (!(world instanceof ServerWorld)) return; + + BlockUpdateRec r = new BlockUpdateRec(); + r.w = world; + FabricWorld fw = getWorld(world, false); + if (fw == null) return; + r.wid = fw.getName(); + r.x = pos.getX(); + r.y = pos.getY(); + r.z = pos.getZ(); + blockupdatequeue.add(r); + } + } + + private WorldTracker worldTracker = null; + private boolean onblockchange = false; + private boolean onchunkpopulate = false; + private boolean onchunkgenerate = false; + boolean onblockchange_with_id = false; + + private void registerEvents() { + // To trigger rendering. + onblockchange = core.isTrigger("blockupdate"); + onchunkpopulate = core.isTrigger("chunkpopulate"); + onchunkgenerate = core.isTrigger("chunkgenerate"); + onblockchange_with_id = core.isTrigger("blockupdate-with-id"); + if (onblockchange_with_id) + onblockchange = true; + if (worldTracker == null) + worldTracker = new WorldTracker(); + if (onchunkpopulate || onchunkgenerate) { + CustomServerChunkEvents.CHUNK_GENERATE.register((world, chunk) -> worldTracker.handleChunkGenerate(world, chunk)); + } + if (onblockchange) { + BlockEvents.BLOCK_EVENT.register((world, pos) -> worldTracker.handleBlockEvent(world, pos)); + } + + ServerWorldEvents.LOAD.register((server, world) -> worldTracker.handleWorldLoad(server, world)); + ServerWorldEvents.UNLOAD.register((server, world) -> worldTracker.handleWorldUnload(server, world)); + } + + FabricWorld getWorldByName(String name) { + return worlds.get(name); + } + + FabricWorld getWorld(World w) { + return getWorld(w, true); + } + + private FabricWorld getWorld(World w, boolean add_if_not_found) { + if (last_world == w) { + return last_fworld; + } + String wname = FabricWorld.getWorldName(this, w); + + for (FabricWorld fw : worlds.values()) { + if (fw.getRawName().equals(wname)) { + last_world = w; + last_fworld = fw; + if (!fw.isLoaded()) { + fw.setWorldLoaded(w); + } + fw.updateWorld(w); + return fw; + } + } + FabricWorld fw = null; + if (add_if_not_found) { + /* Add to list if not found */ + fw = new FabricWorld(this, w); + worlds.put(fw.getName(), fw); + } + last_world = w; + last_fworld = fw; + return fw; + } + + private void saveWorlds() { + File f = new File(core.getDataFolder(), FabricWorld.SAVED_WORLDS_FILE); + ConfigurationNode cn = new ConfigurationNode(f); + ArrayList> lst = new ArrayList>(); + for (DynmapWorld fw : core.mapManager.getWorlds()) { + HashMap vals = new HashMap(); + vals.put("name", fw.getRawName()); + vals.put("height", fw.worldheight); + vals.put("miny", fw.minY); + vals.put("sealevel", fw.sealevel); + vals.put("nether", fw.isNether()); + vals.put("the_end", ((FabricWorld) fw).isTheEnd()); + vals.put("title", fw.getTitle()); + lst.add(vals); + } + cn.put("worlds", lst); + cn.put("useSaveFolderAsName", useSaveFolder); + cn.put("maxWorldHeight", FabricWorld.getMaxWorldHeight()); + + cn.save(); + } + + private void loadWorlds() { + File f = new File(core.getDataFolder(), FabricWorld.SAVED_WORLDS_FILE); + if (f.canRead() == false) { + useSaveFolder = true; + return; + } + ConfigurationNode cn = new ConfigurationNode(f); + cn.load(); + // If defined, use maxWorldHeight + FabricWorld.setMaxWorldHeight(cn.getInteger("maxWorldHeight", 256)); + + // If setting defined, use it + if (cn.containsKey("useSaveFolderAsName")) { + useSaveFolder = cn.getBoolean("useSaveFolderAsName", useSaveFolder); + } + List> lst = cn.getMapList("worlds"); + if (lst == null) { + Log.warning(String.format("Discarding bad %s", FabricWorld.SAVED_WORLDS_FILE)); + return; + } + + for (Map world : lst) { + try { + String name = (String) world.get("name"); + int height = (Integer) world.get("height"); + Integer miny = (Integer) world.get("miny"); + int sealevel = (Integer) world.get("sealevel"); + boolean nether = (Boolean) world.get("nether"); + boolean theend = (Boolean) world.get("the_end"); + String title = (String) world.get("title"); + if (name != null) { + FabricWorld fw = new FabricWorld(this, name, height, sealevel, nether, theend, title, (miny != null) ? miny : 0); + fw.setWorldUnloaded(); + core.processWorldLoad(fw); + worlds.put(fw.getName(), fw); + } + } catch (Exception x) { + Log.warning(String.format("Unable to load saved worlds from %s", FabricWorld.SAVED_WORLDS_FILE)); + return; + } + } + } +} \ No newline at end of file diff --git a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/FabricAdapter.java b/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/FabricAdapter.java new file mode 100644 index 00000000..ee3d9a3a --- /dev/null +++ b/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/FabricAdapter.java @@ -0,0 +1,13 @@ +package org.dynmap.fabric_1_18_2; + +import net.minecraft.server.world.ServerWorld; +import org.dynmap.DynmapLocation; + +public final class FabricAdapter { + public static DynmapLocation toDynmapLocation(DynmapPlugin plugin, ServerWorld world, double x, double y, double z) { + return new DynmapLocation(plugin.getWorld(world).getName(), x, y, z); + } + + private FabricAdapter() { + } +} diff --git a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/FabricCommandSender.java b/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/FabricCommandSender.java new file mode 100644 index 00000000..1280ccc9 --- /dev/null +++ b/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/FabricCommandSender.java @@ -0,0 +1,47 @@ +package org.dynmap.fabric_1_18_2; + +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.text.LiteralText; +import net.minecraft.text.Text; +import org.dynmap.common.DynmapCommandSender; + +/* Handler for generic console command sender */ +public class FabricCommandSender implements DynmapCommandSender { + private ServerCommandSource sender; + + protected FabricCommandSender() { + sender = null; + } + + public FabricCommandSender(ServerCommandSource send) { + sender = send; + } + + @Override + public boolean hasPrivilege(String privid) { + return true; + } + + @Override + public void sendMessage(String msg) { + if (sender != null) { + Text ichatcomponent = new LiteralText(msg); + sender.sendFeedback(ichatcomponent, false); + } + } + + @Override + public boolean isConnected() { + return false; + } + + @Override + public boolean isOp() { + return true; + } + + @Override + public boolean hasPermissionNode(String node) { + return true; + } +} diff --git a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/FabricLogger.java b/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/FabricLogger.java new file mode 100644 index 00000000..4253fc89 --- /dev/null +++ b/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/FabricLogger.java @@ -0,0 +1,49 @@ +package org.dynmap.fabric_1_18_2; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.dynmap.utils.DynmapLogger; + +public class FabricLogger implements DynmapLogger { + Logger log; + public static final String DM = "[Dynmap] "; + + FabricLogger() { + log = LogManager.getLogger("Dynmap"); + } + + @Override + public void info(String s) { + log.info(DM + s); + } + + @Override + public void severe(Throwable t) { + log.fatal(t); + } + + @Override + public void severe(String s) { + log.fatal(DM + s); + } + + @Override + public void severe(String s, Throwable t) { + log.fatal(DM + s, t); + } + + @Override + public void verboseinfo(String s) { + log.info(DM + s); + } + + @Override + public void warning(String s) { + log.warn(DM + s); + } + + @Override + public void warning(String s, Throwable t) { + log.warn(DM + s, t); + } +} \ No newline at end of file diff --git a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/FabricMapChunkCache.java b/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/FabricMapChunkCache.java new file mode 100644 index 00000000..f7394767 --- /dev/null +++ b/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/FabricMapChunkCache.java @@ -0,0 +1,103 @@ +package org.dynmap.fabric_1_18_2; + +import net.minecraft.nbt.*; +import net.minecraft.server.world.ServerChunkManager; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.server.world.ThreadedAnvilChunkStorage; +import net.minecraft.util.collection.PackedIntegerArray; +import net.minecraft.util.math.ChunkPos; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.WordPackedArray; +import net.minecraft.util.registry.Registry; +import net.minecraft.world.ChunkSerializer; +import net.minecraft.world.World; +import net.minecraft.world.biome.Biome; +import net.minecraft.world.chunk.ChunkManager; +import net.minecraft.world.chunk.ChunkStatus; + +import org.dynmap.DynmapChunk; +import org.dynmap.DynmapCore; +import org.dynmap.DynmapWorld; +import org.dynmap.Log; +import org.dynmap.common.BiomeMap; +import org.dynmap.common.chunk.GenericChunk; +import org.dynmap.common.chunk.GenericChunkSection; +import org.dynmap.common.chunk.GenericMapChunkCache; +import org.dynmap.hdmap.HDBlockModels; +import org.dynmap.renderer.DynmapBlockState; +import org.dynmap.renderer.RenderPatchFactory; +import org.dynmap.utils.*; + +import java.lang.reflect.Field; +import java.util.*; + +/** + * Container for managing chunks - dependent upon using chunk snapshots, since rendering is off server thread + */ +public class FabricMapChunkCache extends GenericMapChunkCache { + private World w; + private ServerChunkManager cps; + + /** + * Construct empty cache + */ + public FabricMapChunkCache(DynmapPlugin plugin) { + super(plugin.sscache); + } + + public void setChunks(FabricWorld dw, List chunks) { + this.w = dw.getWorld(); + if (dw.isLoaded()) { + /* Check if world's provider is ServerChunkManager */ + ChunkManager cp = this.w.getChunkManager(); + + if (cp instanceof ServerChunkManager) { + cps = (ServerChunkManager) cp; + } else { + Log.severe("Error: world " + dw.getName() + " has unsupported chunk provider"); + } + } + super.setChunks(dw, chunks); + } + + // Load generic chunk from existing and already loaded chunk + protected GenericChunk getLoadedChunk(DynmapChunk chunk) { + GenericChunk gc = null; + if (cps.isChunkLoaded(chunk.x, chunk.z)) { + NbtCompound nbt = null; + try { + nbt = ChunkSerializer.serialize((ServerWorld) w, cps.getWorldChunk(chunk.x, chunk.z, false)); + } catch (NullPointerException e) { + // TODO: find out why this is happening and why it only seems to happen since 1.16.2 + Log.severe("ChunkSerializer.serialize threw a NullPointerException", e); + } + if (nbt != null) { + gc = parseChunkFromNBT(new NBT.NBTCompound(nbt)); + } + } + return gc; + } + + private NbtCompound readChunk(int x, int z) { + try { + ThreadedAnvilChunkStorage acl = cps.threadedAnvilChunkStorage; + + ChunkPos coord = new ChunkPos(x, z); + return acl.getNbt(coord); + } catch (Exception exc) { + Log.severe(String.format("Error reading chunk: %s,%d,%d", dw.getName(), x, z), exc); + return null; + } + } + + // Load generic chunk from unloaded chunk + protected GenericChunk loadChunk(DynmapChunk chunk) { + GenericChunk gc = null; + NbtCompound nbt = readChunk(chunk.x, chunk.z); + // If read was good + if (nbt != null) { + gc = parseChunkFromNBT(new NBT.NBTCompound(nbt)); + } + return gc; + } +} diff --git a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/FabricPlayer.java b/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/FabricPlayer.java new file mode 100644 index 00000000..8655569c --- /dev/null +++ b/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/FabricPlayer.java @@ -0,0 +1,252 @@ +package org.dynmap.fabric_1_18_2; + +import com.google.common.collect.Iterables; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonParseException; +import com.mojang.authlib.GameProfile; +import com.mojang.authlib.properties.Property; + +import net.minecraft.network.packet.s2c.play.SubtitleS2CPacket; +import net.minecraft.network.packet.s2c.play.TitleFadeS2CPacket; +import net.minecraft.network.packet.s2c.play.TitleS2CPacket; +import net.minecraft.server.network.ServerPlayNetworkHandler; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.text.LiteralText; +import net.minecraft.text.Text; +import net.minecraft.util.Util; +import net.minecraft.util.math.Vec3d; +import org.dynmap.DynmapLocation; +import org.dynmap.common.DynmapPlayer; + +import java.net.InetSocketAddress; +import java.net.SocketAddress; +import java.nio.charset.StandardCharsets; +import java.util.Base64; +import java.util.UUID; + +/** + * Player access abstraction class + */ +public class FabricPlayer extends FabricCommandSender implements DynmapPlayer { + private static final Gson GSON = new GsonBuilder().create(); + private final DynmapPlugin plugin; + // FIXME: Proper setter + ServerPlayerEntity player; + private final String skinurl; + private final UUID uuid; + + public FabricPlayer(DynmapPlugin plugin, ServerPlayerEntity player) { + this.plugin = plugin; + this.player = player; + String url = null; + if (this.player != null) { + uuid = this.player.getUuid(); + GameProfile prof = this.player.getGameProfile(); + if (prof != null) { + Property textureProperty = Iterables.getFirst(prof.getProperties().get("textures"), null); + + if (textureProperty != null) { + DynmapPlugin.TexturesPayload result = null; + try { + String json = new String(Base64.getDecoder().decode(textureProperty.getValue()), StandardCharsets.UTF_8); + result = GSON.fromJson(json, DynmapPlugin.TexturesPayload.class); + } catch (JsonParseException e) { + } + if ((result != null) && (result.textures != null) && (result.textures.containsKey("SKIN"))) { + url = result.textures.get("SKIN").url; + } + } + } + } else { + uuid = null; + } + skinurl = url; + } + + @Override + public boolean isConnected() { + return true; + } + + @Override + public String getName() { + if (player != null) { + String n = player.getName().getString(); + ; + return n; + } else + return "[Server]"; + } + + @Override + public String getDisplayName() { + if (player != null) { + String n = player.getDisplayName().getString(); + return n; + } else + return "[Server]"; + } + + @Override + public boolean isOnline() { + return true; + } + + @Override + public DynmapLocation getLocation() { + if (player == null) { + return null; + } + + Vec3d pos = player.getPos(); + return FabricAdapter.toDynmapLocation(plugin, player.getWorld(), pos.getX(), pos.getY(), pos.getZ()); + } + + @Override + public String getWorld() { + if (player == null) { + return null; + } + + if (player.world != null) { + return plugin.getWorld(player.world).getName(); + } + + return null; + } + + @Override + public InetSocketAddress getAddress() { + if (player != null) { + ServerPlayNetworkHandler networkHandler = player.networkHandler; + if ((networkHandler != null) && (networkHandler.getConnection() != null)) { + SocketAddress sa = networkHandler.getConnection().getAddress(); + if (sa instanceof InetSocketAddress) { + return (InetSocketAddress) sa; + } + } + } + return null; + } + + @Override + public boolean isSneaking() { + if (player != null) { + return player.isSneaking(); + } + + return false; + } + + @Override + public double getHealth() { + if (player != null) { + double h = player.getHealth(); + if (h > 20) h = 20; + return h; // Scale to 20 range + } else { + return 0; + } + } + + @Override + public int getArmorPoints() { + if (player != null) { + return player.getArmor(); + } else { + return 0; + } + } + + @Override + public DynmapLocation getBedSpawnLocation() { + return null; + } + + @Override + public long getLastLoginTime() { + return 0; + } + + @Override + public long getFirstLoginTime() { + return 0; + } + + @Override + public boolean hasPrivilege(String privid) { + if (player != null) + return plugin.hasPerm(player, privid); + return false; + } + + @Override + public boolean isOp() { + return plugin.isOp(player.getName().getString()); + } + + @Override + public void sendMessage(String msg) { + Text ichatcomponent = new LiteralText(msg); + player.sendSystemMessage(ichatcomponent, Util.NIL_UUID); + } + + @Override + public boolean isInvisible() { + if (player != null) { + return player.isInvisible(); + } + return false; + } + + @Override + public int getSortWeight() { + return plugin.getSortWeight(getName()); + } + + @Override + public void setSortWeight(int wt) { + if (wt == 0) { + plugin.dropSortWeight(getName()); + } else { + plugin.setSortWeight(getName(), wt); + } + } + + @Override + public boolean hasPermissionNode(String node) { + return player != null && plugin.hasPermNode(player, node); + } + + @Override + public String getSkinURL() { + return skinurl; + } + + @Override + public UUID getUUID() { + return uuid; + } + + /** + * Send title and subtitle text (called from server thread) + */ + @Override + public void sendTitleText(String title, String subtitle, int fadeInTicks, int stayTicks, int fadeOutTicks) { + if (player != null) { + ServerPlayerEntity player = this.player; + TitleFadeS2CPacket times = new TitleFadeS2CPacket(fadeInTicks, stayTicks, fadeOutTicks); + player.networkHandler.sendPacket(times); + if (title != null) { + TitleS2CPacket titlepkt = new TitleS2CPacket(new LiteralText(title)); + player.networkHandler.sendPacket(titlepkt); + } + + if (subtitle != null) { + SubtitleS2CPacket subtitlepkt = new SubtitleS2CPacket(new LiteralText(subtitle)); + player.networkHandler.sendPacket(subtitlepkt); + } + } + } +} diff --git a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/FabricServer.java b/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/FabricServer.java new file mode 100644 index 00000000..309c9ba2 --- /dev/null +++ b/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/FabricServer.java @@ -0,0 +1,609 @@ +package org.dynmap.fabric_1_18_2; + +import com.mojang.authlib.GameProfile; +import net.fabricmc.loader.api.FabricLoader; +import net.fabricmc.loader.api.ModContainer; +import net.minecraft.block.AbstractSignBlock; +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.network.MessageType; +import net.minecraft.server.BannedIpList; +import net.minecraft.server.BannedPlayerList; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.PlayerManager; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.text.LiteralText; +import net.minecraft.text.Text; +import net.minecraft.util.UserCache; +import net.minecraft.util.Util; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.registry.Registry; +import net.minecraft.world.World; +import net.minecraft.world.biome.Biome; +import org.dynmap.DynmapChunk; +import org.dynmap.DynmapCommonAPIListener; +import org.dynmap.DynmapWorld; +import org.dynmap.Log; +import org.dynmap.common.BiomeMap; +import org.dynmap.common.DynmapListenerManager; +import org.dynmap.common.DynmapPlayer; +import org.dynmap.common.DynmapServerInterface; +import org.dynmap.fabric_1_18_2.event.BlockEvents; +import org.dynmap.fabric_1_18_2.event.ServerChatEvents; +import org.dynmap.utils.MapChunkCache; +import org.dynmap.utils.VisibilityLimit; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.*; +import java.util.concurrent.*; +import java.util.stream.Collectors; + +/** + * Server access abstraction class + */ +public class FabricServer extends DynmapServerInterface { + /* Server thread scheduler */ + private final Object schedlock = new Object(); + private final DynmapPlugin plugin; + private final MinecraftServer server; + private final Registry biomeRegistry; + private long cur_tick; + private long next_id; + private long cur_tick_starttime; + private PriorityQueue runqueue = new PriorityQueue(); + + public FabricServer(DynmapPlugin plugin, MinecraftServer server) { + this.plugin = plugin; + this.server = server; + this.biomeRegistry = server.getRegistryManager().get(Registry.BIOME_KEY); + } + + private Optional getProfileByName(String player) { + UserCache cache = server.getUserCache(); + return cache.findByName(player); + } + + public final Registry getBiomeRegistry() { + return biomeRegistry; + } + + private Biome[] biomelist = null; + + public final Biome[] getBiomeList(Registry biomeRegistry) { + if (biomelist == null) { + biomelist = new Biome[256]; + Iterator iter = biomeRegistry.iterator(); + while (iter.hasNext()) { + Biome b = iter.next(); + int bidx = biomeRegistry.getRawId(b); + if (bidx >= biomelist.length) { + biomelist = Arrays.copyOf(biomelist, bidx + biomelist.length); + } + biomelist[bidx] = b; + } + } + return biomelist; + } + + @Override + public int getBlockIDAt(String wname, int x, int y, int z) { + return -1; + } + + @SuppressWarnings("deprecation") /* Not much I can do... fix this if it breaks. */ + @Override + public int isSignAt(String wname, int x, int y, int z) { + World world = plugin.getWorldByName(wname).getWorld(); + + BlockPos pos = new BlockPos(x, y, z); + if (!world.isChunkLoaded(pos)) + return -1; + + Block block = world.getBlockState(pos).getBlock(); + return (block instanceof AbstractSignBlock ? 1 : 0); + } + + @Override + public void scheduleServerTask(Runnable run, long delay) { + /* Add task record to queue */ + synchronized (schedlock) { + TaskRecord tr = new TaskRecord(cur_tick + delay, next_id++, new FutureTask(run, null)); + runqueue.add(tr); + } + } + + @Override + public DynmapPlayer[] getOnlinePlayers() { + if (server.getPlayerManager() == null) return new DynmapPlayer[0]; + + List players = server.getPlayerManager().getPlayerList(); + int playerCount = players.size(); + DynmapPlayer[] dplay = new DynmapPlayer[players.size()]; + + for (int i = 0; i < playerCount; i++) { + ServerPlayerEntity player = players.get(i); + dplay[i] = plugin.getOrAddPlayer(player); + } + + return dplay; + } + + @Override + public void reload() { + plugin.onDisable(); + plugin.onEnable(); + plugin.onStart(); + } + + @Override + public DynmapPlayer getPlayer(String name) { + List players = server.getPlayerManager().getPlayerList(); + + for (ServerPlayerEntity player : players) { + + if (player.getName().getString().equalsIgnoreCase(name)) { + return plugin.getOrAddPlayer(player); + } + } + + return null; + } + + @Override + public Set getIPBans() { + BannedIpList bl = server.getPlayerManager().getIpBanList(); + Set ips = new HashSet(); + + for (String s : bl.getNames()) { + ips.add(s); + } + + return ips; + } + + @Override + public Future callSyncMethod(Callable task) { + return callSyncMethod(task, 0); + } + + public Future callSyncMethod(Callable task, long delay) { + FutureTask ft = new FutureTask(task); + + /* Add task record to queue */ + synchronized (schedlock) { + TaskRecord tr = new TaskRecord(cur_tick + delay, next_id++, ft); + runqueue.add(tr); + } + + return ft; + } + + void clearTaskQueue() { + this.runqueue.clear(); + } + + @Override + public String getServerName() { + String sn; + if (server.isSingleplayer()) + sn = "Integrated"; + else + sn = server.getServerIp(); + if (sn == null) sn = "Unknown Server"; + return sn; + } + + @Override + public boolean isPlayerBanned(String pid) { + PlayerManager scm = server.getPlayerManager(); + BannedPlayerList bl = scm.getUserBanList(); + try { + return bl.contains(getProfileByName(pid).get()); + } catch (NoSuchElementException e) { + /* If this profile doesn't exist, default to "banned" for good measure. */ + return true; + } + } + + @Override + public String stripChatColor(String s) { + return DynmapPlugin.patternControlCode.matcher(s).replaceAll(""); + } + + private Set registered = new HashSet(); + + @Override + public boolean requestEventNotification(DynmapListenerManager.EventType type) { + if (registered.contains(type)) { + return true; + } + + switch (type) { + case WORLD_LOAD: + case WORLD_UNLOAD: + /* Already called for normal world activation/deactivation */ + break; + + case WORLD_SPAWN_CHANGE: + /*TODO + pm.registerEvents(new Listener() { + @EventHandler(priority=EventPriority.MONITOR) + public void onSpawnChange(SpawnChangeEvent evt) { + DynmapWorld w = new BukkitWorld(evt.getWorld()); + core.listenerManager.processWorldEvent(EventType.WORLD_SPAWN_CHANGE, w); + } + }, DynmapPlugin.this); + */ + break; + + case PLAYER_JOIN: + case PLAYER_QUIT: + /* Already handled */ + break; + + case PLAYER_BED_LEAVE: + /*TODO + pm.registerEvents(new Listener() { + @EventHandler(priority=EventPriority.MONITOR) + public void onPlayerBedLeave(PlayerBedLeaveEvent evt) { + DynmapPlayer p = new BukkitPlayer(evt.getPlayer()); + core.listenerManager.processPlayerEvent(EventType.PLAYER_BED_LEAVE, p); + } + }, DynmapPlugin.this); + */ + break; + + case PLAYER_CHAT: + if (plugin.chathandler == null) { + plugin.setChatHandler(new DynmapPlugin.ChatHandler(plugin)); + ServerChatEvents.EVENT.register((player, message) -> plugin.chathandler.handleChat(player, message)); + } + break; + + case BLOCK_BREAK: + /* Already handled by BlockEvents logic */ + break; + + case SIGN_CHANGE: + BlockEvents.SIGN_CHANGE_EVENT.register((world, pos, lines, material, player) -> { + plugin.core.processSignChange("fabric", FabricWorld.getWorldName(plugin, world), + pos.getX(), pos.getY(), pos.getZ(), lines, player.getName().asString()); + }); + break; + + default: + Log.severe("Unhandled event type: " + type); + return false; + } + + registered.add(type); + return true; + } + + @Override + public boolean sendWebChatEvent(String source, String name, String msg) { + return DynmapCommonAPIListener.fireWebChatEvent(source, name, msg); + } + + @Override + public void broadcastMessage(String msg) { + Text component = new LiteralText(msg); + server.getPlayerManager().broadcast(component, MessageType.SYSTEM, Util.NIL_UUID); + Log.info(stripChatColor(msg)); + } + + @Override + public String[] getBiomeIDs() { + BiomeMap[] b = BiomeMap.values(); + String[] bname = new String[b.length]; + + for (int i = 0; i < bname.length; i++) { + bname[i] = b[i].toString(); + } + + return bname; + } + + @Override + public double getCacheHitRate() { + if (plugin.sscache != null) + return plugin.sscache.getHitRate(); + return 0.0; + } + + @Override + public void resetCacheStats() { + if (plugin.sscache != null) + plugin.sscache.resetStats(); + } + + @Override + public DynmapWorld getWorldByName(String wname) { + return plugin.getWorldByName(wname); + } + + @Override + public DynmapPlayer getOfflinePlayer(String name) { + /* + OfflinePlayer op = getServer().getOfflinePlayer(name); + if(op != null) { + return new BukkitPlayer(op); + } + */ + return null; + } + + @Override + public Set checkPlayerPermissions(String player, Set perms) { + if (isPlayerBanned(player)) { + return Collections.emptySet(); + } + Set rslt = plugin.hasOfflinePermissions(player, perms); + if (rslt == null) { + rslt = new HashSet(); + if (plugin.isOp(player)) { + rslt.addAll(perms); + } + } + return rslt; + } + + @Override + public boolean checkPlayerPermission(String player, String perm) { + if (isPlayerBanned(player)) { + return false; + } + return plugin.hasOfflinePermission(player, perm); + } + + /** + * Render processor helper - used by code running on render threads to request chunk snapshot cache from server/sync thread + */ + @Override + public MapChunkCache createMapChunkCache(DynmapWorld w, List chunks, + boolean blockdata, boolean highesty, boolean biome, boolean rawbiome) { + FabricMapChunkCache c = (FabricMapChunkCache) w.getChunkCache(chunks); + if (c == null) { + return null; + } + if (w.visibility_limits != null) { + for (VisibilityLimit limit : w.visibility_limits) { + c.setVisibleRange(limit); + } + + c.setHiddenFillStyle(w.hiddenchunkstyle); + } + + if (w.hidden_limits != null) { + for (VisibilityLimit limit : w.hidden_limits) { + c.setHiddenRange(limit); + } + + c.setHiddenFillStyle(w.hiddenchunkstyle); + } + + if (!c.setChunkDataTypes(blockdata, biome, highesty, rawbiome)) { + Log.severe("CraftBukkit build does not support biome APIs"); + } + + if (chunks.size() == 0) /* No chunks to get? */ { + c.loadChunks(0); + return c; + } + + //Now handle any chunks in server thread that are already loaded (on server thread) + final FabricMapChunkCache cc = c; + Future f = this.callSyncMethod(new Callable() { + public Boolean call() throws Exception { + // Update busy state on world + //FabricWorld fw = (FabricWorld) cc.getWorld(); + //TODO + //setBusy(fw.getWorld()); + cc.getLoadedChunks(); + return true; + } + }, 0); + try { + f.get(); + } catch (CancellationException cx) { + return null; + } catch (InterruptedException cx) { + return null; + } catch (ExecutionException xx) { + Log.severe("Exception while loading chunks", xx.getCause()); + return null; + } catch (Exception ix) { + Log.severe(ix); + return null; + } + if (!w.isLoaded()) { + return null; + } + // Now, do rest of chunk reading from calling thread + c.readChunks(chunks.size()); + + return c; + } + + @Override + public int getMaxPlayers() { + return server.getMaxPlayerCount(); + } + + @Override + public int getCurrentPlayers() { + return server.getPlayerManager().getCurrentPlayerCount(); + } + + public void tickEvent(MinecraftServer server) { + cur_tick_starttime = System.nanoTime(); + long elapsed = cur_tick_starttime - plugin.lasttick; + plugin.lasttick = cur_tick_starttime; + plugin.avgticklen = ((plugin.avgticklen * 99) / 100) + (elapsed / 100); + plugin.tps = (double) 1E9 / (double) plugin.avgticklen; + // Tick core + if (plugin.core != null) { + plugin.core.serverTick(plugin.tps); + } + + boolean done = false; + TaskRecord tr = null; + + while (!plugin.blockupdatequeue.isEmpty()) { + DynmapPlugin.BlockUpdateRec r = plugin.blockupdatequeue.remove(); + BlockState bs = r.w.getBlockState(new BlockPos(r.x, r.y, r.z)); + int idx = Block.STATE_IDS.getRawId(bs); + if (!org.dynmap.hdmap.HDBlockModels.isChangeIgnoredBlock(DynmapPlugin.stateByID[idx])) { + if (plugin.onblockchange_with_id) + plugin.mapManager.touch(r.wid, r.x, r.y, r.z, "blockchange[" + idx + "]"); + else + plugin.mapManager.touch(r.wid, r.x, r.y, r.z, "blockchange"); + } + } + + long now; + + synchronized (schedlock) { + cur_tick++; + now = System.nanoTime(); + tr = runqueue.peek(); + /* Nothing due to run */ + if ((tr == null) || (tr.getTickToRun() > cur_tick) || ((now - cur_tick_starttime) > plugin.perTickLimit)) { + done = true; + } else { + tr = runqueue.poll(); + } + } + while (!done) { + tr.run(); + + synchronized (schedlock) { + tr = runqueue.peek(); + now = System.nanoTime(); + /* Nothing due to run */ + if ((tr == null) || (tr.getTickToRun() > cur_tick) || ((now - cur_tick_starttime) > plugin.perTickLimit)) { + done = true; + } else { + tr = runqueue.poll(); + } + } + } + while (!plugin.msgqueue.isEmpty()) { + DynmapPlugin.ChatMessage cm = plugin.msgqueue.poll(); + DynmapPlayer dp = null; + if (cm.sender != null) + dp = plugin.getOrAddPlayer(cm.sender); + else + dp = new FabricPlayer(plugin, null); + + plugin.core.listenerManager.processChatEvent(DynmapListenerManager.EventType.PLAYER_CHAT, dp, cm.message); + } + // Check for generated chunks + if ((cur_tick % 20) == 0) { + } + } + + private Optional getModContainerById(String id) { + return FabricLoader.getInstance().getModContainer(id); + } + + @Override + public boolean isModLoaded(String name) { + return FabricLoader.getInstance().getModContainer(name).isPresent(); + } + + @Override + public String getModVersion(String name) { + Optional mod = getModContainerById(name); // Try case sensitive lookup + return mod.map(modContainer -> modContainer.getMetadata().getVersion().getFriendlyString()).orElse(null); + } + + @Override + public double getServerTPS() { + return plugin.tps; + } + + @Override + public String getServerIP() { + if (server.isSingleplayer()) + return "0.0.0.0"; + else + return server.getServerIp(); + } + + @Override + public File getModContainerFile(String name) { + Optional container = getModContainerById(name); // Try case sensitive lookup + if (container.isPresent()) { + Path path = container.get().getRootPath(); + if (path.getFileSystem().provider().getScheme().equals("jar")) { + path = Paths.get(path.getFileSystem().toString()); + } + return path.toFile(); + } + return null; + } + + @Override + public List getModList() { + return FabricLoader.getInstance() + .getAllMods() + .stream() + .map(container -> container.getMetadata().getId()) + .collect(Collectors.toList()); + } + + @Override + public Map getBlockIDMap() { + Map map = new HashMap(); + return map; + } + + @Override + public InputStream openResource(String modid, String rname) { + if (modid == null) modid = "minecraft"; + + if ("minecraft".equals(modid)) { + return MinecraftServer.class.getClassLoader().getResourceAsStream(rname); + } else { + if (rname.startsWith("/") || rname.startsWith("\\")) { + rname = rname.substring(1); + } + + final String finalModid = modid; + final String finalRname = rname; + return getModContainerById(modid).map(container -> { + try { + return Files.newInputStream(container.getPath(finalRname)); + } catch (IOException e) { + Log.severe("Failed to load resource of mod :" + finalModid, e); + return null; + } + }).orElse(null); + } + } + + /** + * Get block unique ID map (module:blockid) + */ + @Override + public Map getBlockUniqueIDMap() { + HashMap map = new HashMap(); + return map; + } + + /** + * Get item unique ID map (module:itemid) + */ + @Override + public Map getItemUniqueIDMap() { + HashMap map = new HashMap(); + return map; + } + +} diff --git a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/FabricWorld.java b/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/FabricWorld.java new file mode 100644 index 00000000..0ae91886 --- /dev/null +++ b/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/FabricWorld.java @@ -0,0 +1,229 @@ +package org.dynmap.fabric_1_18_2; + +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.registry.RegistryKey; +import net.minecraft.world.Heightmap; +import net.minecraft.world.LightType; +import net.minecraft.world.World; +import net.minecraft.world.border.WorldBorder; +import org.dynmap.DynmapChunk; +import org.dynmap.DynmapLocation; +import org.dynmap.DynmapWorld; +import org.dynmap.utils.MapChunkCache; +import org.dynmap.utils.Polygon; + +import java.util.List; + +public class FabricWorld extends DynmapWorld { + // TODO: Store this relative to World saves for integrated server + public static final String SAVED_WORLDS_FILE = "fabricworlds.yml"; + + private final DynmapPlugin plugin; + private World world; + private final boolean skylight; + private final boolean isnether; + private final boolean istheend; + private final String env; + private DynmapLocation spawnloc = new DynmapLocation(); + private static int maxWorldHeight = 320; // Maximum allows world height + + public static int getMaxWorldHeight() { + return maxWorldHeight; + } + + public static void setMaxWorldHeight(int h) { + maxWorldHeight = h; + } + + public static String getWorldName(DynmapPlugin plugin, World w) { + RegistryKey rk = w.getRegistryKey(); + if (rk == World.OVERWORLD) { // Overworld? + return w.getServer().getSaveProperties().getLevelName(); + } else if (rk == World.END) { + return "DIM1"; + } else if (rk == World.NETHER) { + return "DIM-1"; + } else { + return rk.getValue().getNamespace() + "_" + rk.getValue().getPath(); + } + } + + public void updateWorld(World w) { + this.updateWorldHeights(w.getHeight(), w.getDimension().getMinimumY(), w.getSeaLevel()); + } + + public FabricWorld(DynmapPlugin plugin, World w) { + this(plugin, getWorldName(plugin, w), w.getHeight(), + w.getSeaLevel(), + w.getRegistryKey() == World.NETHER, + w.getRegistryKey() == World.END, + w.getRegistryKey().getValue().getPath(), + w.getDimension().getMinimumY()); + setWorldLoaded(w); + } + + public FabricWorld(DynmapPlugin plugin, String name, int height, int sealevel, boolean nether, boolean the_end, String deftitle, int miny) { + super(name, (height > maxWorldHeight) ? maxWorldHeight : height, sealevel, miny); + this.plugin = plugin; + world = null; + setTitle(deftitle); + isnether = nether; + istheend = the_end; + skylight = !(isnether || istheend); + + if (isnether) { + env = "nether"; + } else if (istheend) { + env = "the_end"; + } else { + env = "normal"; + } + + } + + /* Test if world is nether */ + @Override + public boolean isNether() { + return isnether; + } + + public boolean isTheEnd() { + return istheend; + } + + /* Get world spawn location */ + @Override + public DynmapLocation getSpawnLocation() { + if (world != null) { + spawnloc.x = world.getLevelProperties().getSpawnX(); + spawnloc.y = world.getLevelProperties().getSpawnY(); + spawnloc.z = world.getLevelProperties().getSpawnZ(); + spawnloc.world = this.getName(); + } + return spawnloc; + } + + /* Get world time */ + @Override + public long getTime() { + if (world != null) + return world.getTimeOfDay(); + else + return -1; + } + + /* World is storming */ + @Override + public boolean hasStorm() { + if (world != null) + return world.isRaining(); + else + return false; + } + + /* World is thundering */ + @Override + public boolean isThundering() { + if (world != null) + return world.isThundering(); + else + return false; + } + + /* World is loaded */ + @Override + public boolean isLoaded() { + return (world != null); + } + + /* Set world to unloaded */ + @Override + public void setWorldUnloaded() { + getSpawnLocation(); + world = null; + } + + /* Set world to loaded */ + public void setWorldLoaded(World w) { + world = w; + this.sealevel = w.getSeaLevel(); // Read actual current sealevel from world + // Update lighting table + for (int i = 0; i < 16; i++) { + this.setBrightnessTableEntry(i, w.getDimension().getBrightness(i)); + } + } + + /* Get light level of block */ + @Override + public int getLightLevel(int x, int y, int z) { + if (world != null) + return world.getLightLevel(new BlockPos(x, y, z)); + else + return -1; + } + + /* Get highest Y coord of given location */ + @Override + public int getHighestBlockYAt(int x, int z) { + if (world != null) { + return world.getChunk(x >> 4, z >> 4).getHeightmap(Heightmap.Type.MOTION_BLOCKING).get(x & 15, z & 15); + } else + return -1; + } + + /* Test if sky light level is requestable */ + @Override + public boolean canGetSkyLightLevel() { + return skylight; + } + + /* Return sky light level */ + @Override + public int getSkyLightLevel(int x, int y, int z) { + if (world != null) { + return world.getLightLevel(LightType.SKY, new BlockPos(x, y, z)); + } else + return -1; + } + + /** + * Get world environment ID (lower case - normal, the_end, nether) + */ + @Override + public String getEnvironment() { + return env; + } + + /** + * Get map chunk cache for world + */ + @Override + public MapChunkCache getChunkCache(List chunks) { + if (world != null) { + FabricMapChunkCache c = new FabricMapChunkCache(plugin); + c.setChunks(this, chunks); + return c; + } + return null; + } + + public World getWorld() { + return world; + } + + @Override + public Polygon getWorldBorder() { + if (world != null) { + WorldBorder wb = world.getWorldBorder(); + if ((wb != null) && (wb.getSize() < 5.9E7)) { + Polygon p = new Polygon(); + p.addVertex(wb.getBoundWest(), wb.getBoundNorth()); + p.addVertex(wb.getBoundWest(), wb.getBoundSouth()); + p.addVertex(wb.getBoundEast(), wb.getBoundSouth()); + p.addVertex(wb.getBoundEast(), wb.getBoundNorth()); + return p; + } + } + return null; + } +} diff --git a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/NBT.java b/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/NBT.java new file mode 100644 index 00000000..afaec108 --- /dev/null +++ b/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/NBT.java @@ -0,0 +1,126 @@ +package org.dynmap.fabric_1_18_2; + +import org.dynmap.common.chunk.GenericBitStorage; +import org.dynmap.common.chunk.GenericNBTCompound; +import org.dynmap.common.chunk.GenericNBTList; + +import java.util.Set; +import net.minecraft.nbt.NbtCompound; +import net.minecraft.nbt.NbtList; +import net.minecraft.util.collection.PackedIntegerArray; + +public class NBT { + + public static class NBTCompound implements GenericNBTCompound { + private final NbtCompound obj; + public NBTCompound(NbtCompound t) { + this.obj = t; + } + @Override + public Set getAllKeys() { + return obj.getKeys(); + } + @Override + public boolean contains(String s) { + return obj.contains(s); + } + @Override + public boolean contains(String s, int i) { + return obj.contains(s, i); + } + @Override + public byte getByte(String s) { + return obj.getByte(s); + } + @Override + public short getShort(String s) { + return obj.getShort(s); + } + @Override + public int getInt(String s) { + return obj.getInt(s); + } + @Override + public long getLong(String s) { + return obj.getLong(s); + } + @Override + public float getFloat(String s) { + return obj.getFloat(s); + } + @Override + public double getDouble(String s) { + return obj.getDouble(s); + } + @Override + public String getString(String s) { + return obj.getString(s); + } + @Override + public byte[] getByteArray(String s) { + return obj.getByteArray(s); + } + @Override + public int[] getIntArray(String s) { + return obj.getIntArray(s); + } + @Override + public long[] getLongArray(String s) { + return obj.getLongArray(s); + } + @Override + public GenericNBTCompound getCompound(String s) { + return new NBTCompound(obj.getCompound(s)); + } + @Override + public GenericNBTList getList(String s, int i) { + return new NBTList(obj.getList(s, i)); + } + @Override + public boolean getBoolean(String s) { + return obj.getBoolean(s); + } + @Override + public String getAsString(String s) { + return obj.get(s).asString(); + } + @Override + public GenericBitStorage makeBitStorage(int bits, int count, long[] data) { + return new OurBitStorage(bits, count, data); + } + public String toString() { + return obj.toString(); + } + } + public static class NBTList implements GenericNBTList { + private final NbtList obj; + public NBTList(NbtList t) { + obj = t; + } + @Override + public int size() { + return obj.size(); + } + @Override + public String getString(int idx) { + return obj.getString(idx); + } + @Override + public GenericNBTCompound getCompound(int idx) { + return new NBTCompound(obj.getCompound(idx)); + } + public String toString() { + return obj.toString(); + } + } + public static class OurBitStorage implements GenericBitStorage { + private final PackedIntegerArray bs; + public OurBitStorage(int bits, int count, long[] data) { + bs = new PackedIntegerArray(bits, count, data); + } + @Override + public int get(int idx) { + return bs.get(idx); + } + } +} diff --git a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/TaskRecord.java b/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/TaskRecord.java new file mode 100644 index 00000000..ecde4814 --- /dev/null +++ b/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/TaskRecord.java @@ -0,0 +1,38 @@ +package org.dynmap.fabric_1_18_2; + +import java.util.concurrent.FutureTask; + +class TaskRecord implements Comparable { + TaskRecord(long ticktorun, long id, FutureTask future) { + this.ticktorun = ticktorun; + this.id = id; + this.future = future; + } + + private final long ticktorun; + private final long id; + private final FutureTask future; + + void run() { + this.future.run(); + } + + long getTickToRun() { + return this.ticktorun; + } + + @Override + public int compareTo(TaskRecord o) { + if (this.ticktorun < o.ticktorun) { + return -1; + } else if (this.ticktorun > o.ticktorun) { + return 1; + } else if (this.id < o.id) { + return -1; + } else if (this.id > o.id) { + return 1; + } else { + return 0; + } + } +} diff --git a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/VersionCheck.java b/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/VersionCheck.java new file mode 100644 index 00000000..03ff3f5a --- /dev/null +++ b/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/VersionCheck.java @@ -0,0 +1,98 @@ +package org.dynmap.fabric_1_18_2; + +import org.dynmap.DynmapCore; +import org.dynmap.Log; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URL; + +public class VersionCheck { + private static final String VERSION_URL = "http://mikeprimm.com/dynmap/releases.php"; + + public static void runCheck(final DynmapCore core) { + new Thread(new Runnable() { + public void run() { + doCheck(core); + } + }).start(); + } + + private static int getReleaseVersion(String s) { + int index = s.lastIndexOf('-'); + if (index < 0) + index = s.lastIndexOf('.'); + if (index >= 0) + s = s.substring(0, index); + String[] split = s.split("\\."); + int v = 0; + try { + for (int i = 0; (i < split.length) && (i < 3); i++) { + v += Integer.parseInt(split[i]) << (8 * (2 - i)); + } + } catch (NumberFormatException nfx) { + } + return v; + } + + private static int getBuildNumber(String s) { + int index = s.lastIndexOf('-'); + if (index < 0) + index = s.lastIndexOf('.'); + if (index >= 0) + s = s.substring(index + 1); + try { + return Integer.parseInt(s); + } catch (NumberFormatException nfx) { + return 99999999; + } + } + + private static void doCheck(DynmapCore core) { + String pluginver = core.getDynmapPluginVersion(); + String platform = core.getDynmapPluginPlatform(); + String platver = core.getDynmapPluginPlatformVersion(); + if ((pluginver == null) || (platform == null) || (platver == null)) + return; + HttpURLConnection conn = null; + String loc = VERSION_URL; + int cur_ver = getReleaseVersion(pluginver); + int cur_bn = getBuildNumber(pluginver); + try { + while ((loc != null) && (!loc.isEmpty())) { + URL url = new URL(loc); + conn = (HttpURLConnection) url.openConnection(); + conn.setRequestProperty("User-Agent", "Dynmap (" + platform + "/" + platver + "/" + pluginver); + conn.connect(); + loc = conn.getHeaderField("Location"); + } + BufferedReader rdr = new BufferedReader(new InputStreamReader(conn.getInputStream())); + String line = null; + while ((line = rdr.readLine()) != null) { + String[] split = line.split(":"); + if (split.length < 4) continue; + /* If our platform and version, or wildcard platform version */ + if (split[0].equals(platform) && (split[1].equals("*") || split[1].equals(platver))) { + int recommended_ver = getReleaseVersion(split[2]); + int recommended_bn = getBuildNumber(split[2]); + if ((recommended_ver > cur_ver) || ((recommended_ver == cur_ver) && (recommended_bn > cur_bn))) { /* Newer recommended build */ + Log.info("Version obsolete: new recommended version " + split[2] + " is available."); + } else if (cur_ver > recommended_ver) { /* Running dev or prerelease? */ + int prerel_ver = getReleaseVersion(split[3]); + int prerel_bn = getBuildNumber(split[3]); + if ((prerel_ver > cur_ver) || ((prerel_ver == cur_ver) && (prerel_bn > cur_bn))) { + Log.info("Version obsolete: new prerelease version " + split[3] + " is available."); + } + } + } + } + } catch (Exception x) { + Log.info("Error checking for latest version"); + } finally { + if (conn != null) { + conn.disconnect(); + } + } + } +} diff --git a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/access/ProtoChunkAccessor.java b/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/access/ProtoChunkAccessor.java new file mode 100644 index 00000000..1b98c24d --- /dev/null +++ b/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/access/ProtoChunkAccessor.java @@ -0,0 +1,5 @@ +package org.dynmap.fabric_1_18_2.access; + +public interface ProtoChunkAccessor { + boolean getTouchedByWorldGen(); +} diff --git a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/command/DmapCommand.java b/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/command/DmapCommand.java new file mode 100644 index 00000000..87690eda --- /dev/null +++ b/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/command/DmapCommand.java @@ -0,0 +1,9 @@ +package org.dynmap.fabric_1_18_2.command; + +import org.dynmap.fabric_1_18_2.DynmapPlugin; + +public class DmapCommand extends DynmapCommandExecutor { + public DmapCommand(DynmapPlugin p) { + super("dmap", p); + } +} diff --git a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/command/DmarkerCommand.java b/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/command/DmarkerCommand.java new file mode 100644 index 00000000..e132b941 --- /dev/null +++ b/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/command/DmarkerCommand.java @@ -0,0 +1,9 @@ +package org.dynmap.fabric_1_18_2.command; + +import org.dynmap.fabric_1_18_2.DynmapPlugin; + +public class DmarkerCommand extends DynmapCommandExecutor { + public DmarkerCommand(DynmapPlugin p) { + super("dmarker", p); + } +} diff --git a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/command/DynmapCommand.java b/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/command/DynmapCommand.java new file mode 100644 index 00000000..8e4c3c67 --- /dev/null +++ b/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/command/DynmapCommand.java @@ -0,0 +1,9 @@ +package org.dynmap.fabric_1_18_2.command; + +import org.dynmap.fabric_1_18_2.DynmapPlugin; + +public class DynmapCommand extends DynmapCommandExecutor { + public DynmapCommand(DynmapPlugin p) { + super("dynmap", p); + } +} diff --git a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/command/DynmapCommandExecutor.java b/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/command/DynmapCommandExecutor.java new file mode 100644 index 00000000..bf2e90b5 --- /dev/null +++ b/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/command/DynmapCommandExecutor.java @@ -0,0 +1,63 @@ +package org.dynmap.fabric_1_18_2.command; + +import com.mojang.brigadier.Command; +import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.context.CommandContext; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import com.mojang.brigadier.tree.ArgumentCommandNode; +import com.mojang.brigadier.tree.LiteralCommandNode; +import com.mojang.brigadier.tree.RootCommandNode; +import net.minecraft.server.command.ServerCommandSource; +import org.dynmap.fabric_1_18_2.DynmapPlugin; + +import java.util.Arrays; + +import static com.mojang.brigadier.arguments.StringArgumentType.greedyString; +import static net.minecraft.server.command.CommandManager.argument; +import static net.minecraft.server.command.CommandManager.literal; + +public class DynmapCommandExecutor implements Command { + private final String cmd; + private final DynmapPlugin plugin; + + DynmapCommandExecutor(String cmd, DynmapPlugin plugin) { + this.cmd = cmd; + this.plugin = plugin; + } + + public void register(CommandDispatcher dispatcher) { + final RootCommandNode root = dispatcher.getRoot(); + + final LiteralCommandNode command = literal(this.cmd) + .executes(this) + .build(); + + final ArgumentCommandNode args = argument("args", greedyString()) + .executes(this) + .build(); + + // So this becomes "cmd" [args] + command.addChild(args); + + // Add command to the command dispatcher via root node. + root.addChild(command); + } + + @Override + public int run(CommandContext context) throws CommandSyntaxException { + // Commands in brigadier may be proxied in Minecraft via a syntax like `/execute ... ... run dmap [args]` + // Dynmap will fail to parse this properly, so we find the starting position of the actual command being parsed after any forks or redirects. + // The start position of the range specifies where the actual command dynmap has registered starts + int start = context.getRange().getStart(); + String dynmapInput = context.getInput().substring(start); + + String[] args = dynmapInput.split("\\s+"); + plugin.handleCommand(context.getSource(), cmd, Arrays.copyOfRange(args, 1, args.length)); + return 1; + } + + // @Override // TODO: Usage? + public String getUsage(ServerCommandSource commandSource) { + return "Run /" + cmd + " help for details on using command"; + } +} diff --git a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/command/DynmapExpCommand.java b/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/command/DynmapExpCommand.java new file mode 100644 index 00000000..4fb29b79 --- /dev/null +++ b/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/command/DynmapExpCommand.java @@ -0,0 +1,9 @@ +package org.dynmap.fabric_1_18_2.command; + +import org.dynmap.fabric_1_18_2.DynmapPlugin; + +public class DynmapExpCommand extends DynmapCommandExecutor { + public DynmapExpCommand(DynmapPlugin p) { + super("dynmapexp", p); + } +} diff --git a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/event/BlockEvents.java b/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/event/BlockEvents.java new file mode 100644 index 00000000..9ad017ca --- /dev/null +++ b/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/event/BlockEvents.java @@ -0,0 +1,40 @@ +package org.dynmap.fabric_1_18_2.event; + +import net.fabricmc.fabric.api.event.Event; +import net.fabricmc.fabric.api.event.EventFactory; +import net.minecraft.block.Material; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +public class BlockEvents { + private BlockEvents() { + } + + public static Event BLOCK_EVENT = EventFactory.createArrayBacked(BlockCallback.class, + (listeners) -> (world, pos) -> { + for (BlockCallback callback : listeners) { + callback.onBlockEvent(world, pos); + } + } + ); + + public static Event SIGN_CHANGE_EVENT = EventFactory.createArrayBacked(SignChangeCallback.class, + (listeners) -> (world, pos, lines, material, player) -> { + for (SignChangeCallback callback : listeners) { + callback.onSignChange(world, pos, lines, material, player); + } + } + ); + + @FunctionalInterface + public interface BlockCallback { + void onBlockEvent(World world, BlockPos pos); + } + + @FunctionalInterface + public interface SignChangeCallback { + void onSignChange(ServerWorld world, BlockPos pos, String[] lines, Material material, ServerPlayerEntity player); + } +} diff --git a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/event/CustomServerChunkEvents.java b/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/event/CustomServerChunkEvents.java new file mode 100644 index 00000000..5f3a1c9f --- /dev/null +++ b/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/event/CustomServerChunkEvents.java @@ -0,0 +1,21 @@ +package org.dynmap.fabric_1_18_2.event; + +import net.fabricmc.fabric.api.event.Event; +import net.fabricmc.fabric.api.event.EventFactory; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.world.chunk.Chunk; + +public class CustomServerChunkEvents { + public static Event CHUNK_GENERATE = EventFactory.createArrayBacked(ChunkGenerate.class, + (listeners) -> (world, chunk) -> { + for (ChunkGenerate callback : listeners) { + callback.onChunkGenerate(world, chunk); + } + } + ); + + @FunctionalInterface + public interface ChunkGenerate { + void onChunkGenerate(ServerWorld world, Chunk chunk); + } +} \ No newline at end of file diff --git a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/event/CustomServerLifecycleEvents.java b/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/event/CustomServerLifecycleEvents.java new file mode 100644 index 00000000..8ac46ae2 --- /dev/null +++ b/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/event/CustomServerLifecycleEvents.java @@ -0,0 +1,14 @@ +package org.dynmap.fabric_1_18_2.event; + +import net.fabricmc.fabric.api.event.Event; +import net.fabricmc.fabric.api.event.EventFactory; +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; + +public class CustomServerLifecycleEvents { + public static final Event SERVER_STARTED_PRE_WORLD_LOAD = + EventFactory.createArrayBacked(ServerLifecycleEvents.ServerStarted.class, (callbacks) -> (server) -> { + for (ServerLifecycleEvents.ServerStarted callback : callbacks) { + callback.onServerStarted(server); + } + }); +} diff --git a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/event/PlayerEvents.java b/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/event/PlayerEvents.java new file mode 100644 index 00000000..1d584861 --- /dev/null +++ b/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/event/PlayerEvents.java @@ -0,0 +1,62 @@ +package org.dynmap.fabric_1_18_2.event; + +import net.fabricmc.fabric.api.event.Event; +import net.fabricmc.fabric.api.event.EventFactory; +import net.minecraft.server.network.ServerPlayerEntity; + +public class PlayerEvents { + private PlayerEvents() { + } + + public static Event PLAYER_LOGGED_IN = EventFactory.createArrayBacked(PlayerLoggedIn.class, + (listeners) -> (player) -> { + for (PlayerLoggedIn callback : listeners) { + callback.onPlayerLoggedIn(player); + } + } + ); + + public static Event PLAYER_LOGGED_OUT = EventFactory.createArrayBacked(PlayerLoggedOut.class, + (listeners) -> (player) -> { + for (PlayerLoggedOut callback : listeners) { + callback.onPlayerLoggedOut(player); + } + } + ); + + public static Event PLAYER_CHANGED_DIMENSION = EventFactory.createArrayBacked(PlayerChangedDimension.class, + (listeners) -> (player) -> { + for (PlayerChangedDimension callback : listeners) { + callback.onPlayerChangedDimension(player); + } + } + ); + + public static Event PLAYER_RESPAWN = EventFactory.createArrayBacked(PlayerRespawn.class, + (listeners) -> (player) -> { + for (PlayerRespawn callback : listeners) { + callback.onPlayerRespawn(player); + } + } + ); + + @FunctionalInterface + public interface PlayerLoggedIn { + void onPlayerLoggedIn(ServerPlayerEntity player); + } + + @FunctionalInterface + public interface PlayerLoggedOut { + void onPlayerLoggedOut(ServerPlayerEntity player); + } + + @FunctionalInterface + public interface PlayerChangedDimension { + void onPlayerChangedDimension(ServerPlayerEntity player); + } + + @FunctionalInterface + public interface PlayerRespawn { + void onPlayerRespawn(ServerPlayerEntity player); + } +} diff --git a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/event/ServerChatEvents.java b/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/event/ServerChatEvents.java new file mode 100644 index 00000000..2724320b --- /dev/null +++ b/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/event/ServerChatEvents.java @@ -0,0 +1,23 @@ +package org.dynmap.fabric_1_18_2.event; + +import net.fabricmc.fabric.api.event.Event; +import net.fabricmc.fabric.api.event.EventFactory; +import net.minecraft.server.network.ServerPlayerEntity; + +public class ServerChatEvents { + private ServerChatEvents() { + } + + public static Event EVENT = EventFactory.createArrayBacked(ServerChatCallback.class, + (listeners) -> (player, message) -> { + for (ServerChatCallback callback : listeners) { + callback.onChatMessage(player, message); + } + } + ); + + @FunctionalInterface + public interface ServerChatCallback { + void onChatMessage(ServerPlayerEntity player, String message); + } +} \ No newline at end of file diff --git a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/mixin/BiomeEffectsAccessor.java b/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/mixin/BiomeEffectsAccessor.java new file mode 100644 index 00000000..f1d75396 --- /dev/null +++ b/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/mixin/BiomeEffectsAccessor.java @@ -0,0 +1,11 @@ +package org.dynmap.fabric_1_18_2.mixin; + +import net.minecraft.world.biome.BiomeEffects; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(BiomeEffects.class) +public interface BiomeEffectsAccessor { + @Accessor + int getWaterColor(); +} diff --git a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/mixin/MinecraftServerMixin.java b/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/mixin/MinecraftServerMixin.java new file mode 100644 index 00000000..b3d1e82f --- /dev/null +++ b/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/mixin/MinecraftServerMixin.java @@ -0,0 +1,16 @@ +package org.dynmap.fabric_1_18_2.mixin; + +import net.minecraft.server.MinecraftServer; +import org.dynmap.fabric_1_18_2.event.CustomServerLifecycleEvents; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(MinecraftServer.class) +public class MinecraftServerMixin { + @Inject(method = "loadWorld", at = @At("HEAD")) + protected void loadWorld(CallbackInfo info) { + CustomServerLifecycleEvents.SERVER_STARTED_PRE_WORLD_LOAD.invoker().onServerStarted((MinecraftServer) (Object) this); + } +} diff --git a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/mixin/PlayerManagerMixin.java b/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/mixin/PlayerManagerMixin.java new file mode 100644 index 00000000..2a733175 --- /dev/null +++ b/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/mixin/PlayerManagerMixin.java @@ -0,0 +1,29 @@ +package org.dynmap.fabric_1_18_2.mixin; + +import net.minecraft.network.ClientConnection; +import net.minecraft.server.PlayerManager; +import net.minecraft.server.network.ServerPlayerEntity; +import org.dynmap.fabric_1_18_2.event.PlayerEvents; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(PlayerManager.class) +public class PlayerManagerMixin { + @Inject(method = "onPlayerConnect", at = @At("TAIL")) + public void onPlayerConnect(ClientConnection connection, ServerPlayerEntity player, CallbackInfo info) { + PlayerEvents.PLAYER_LOGGED_IN.invoker().onPlayerLoggedIn(player); + } + + @Inject(method = "remove", at = @At("HEAD")) + public void remove(ServerPlayerEntity player, CallbackInfo info) { + PlayerEvents.PLAYER_LOGGED_OUT.invoker().onPlayerLoggedOut(player); + } + + @Inject(method = "respawnPlayer", at = @At("RETURN")) + public void respawnPlayer(ServerPlayerEntity player, boolean alive, CallbackInfoReturnable info) { + PlayerEvents.PLAYER_RESPAWN.invoker().onPlayerRespawn(info.getReturnValue()); + } +} diff --git a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/mixin/ProtoChunkMixin.java b/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/mixin/ProtoChunkMixin.java new file mode 100644 index 00000000..e591e8b2 --- /dev/null +++ b/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/mixin/ProtoChunkMixin.java @@ -0,0 +1,30 @@ +package org.dynmap.fabric_1_18_2.mixin; + +import net.minecraft.block.BlockState; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.chunk.ProtoChunk; +import org.dynmap.fabric_1_18_2.access.ProtoChunkAccessor; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(ProtoChunk.class) +public class ProtoChunkMixin implements ProtoChunkAccessor { + private boolean touchedByWorldGen = false; + + @Inject( + method = "setBlockState", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/world/chunk/ChunkSection;setBlockState(IIILnet/minecraft/block/BlockState;)Lnet/minecraft/block/BlockState;" + ) + ) + public void setBlockState(BlockPos pos, BlockState state, boolean moved, CallbackInfoReturnable info) { + touchedByWorldGen = true; + } + + public boolean getTouchedByWorldGen() { + return touchedByWorldGen; + } +} \ No newline at end of file diff --git a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/mixin/ServerPlayNetworkHandlerMixin.java b/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/mixin/ServerPlayNetworkHandlerMixin.java new file mode 100644 index 00000000..9a373518 --- /dev/null +++ b/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/mixin/ServerPlayNetworkHandlerMixin.java @@ -0,0 +1,66 @@ +package org.dynmap.fabric_1_18_2.mixin; + +import net.minecraft.block.BlockState; +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.block.entity.SignBlockEntity; +import net.minecraft.network.packet.c2s.play.UpdateSignC2SPacket; +import net.minecraft.server.filter.TextStream; +import net.minecraft.server.network.ServerPlayNetworkHandler; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.text.LiteralText; +import net.minecraft.util.math.BlockPos; + +import java.util.List; + +import org.dynmap.fabric_1_18_2.event.BlockEvents; +import org.dynmap.fabric_1_18_2.event.ServerChatEvents; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.LocalCapture; + +@Mixin(ServerPlayNetworkHandler.class) +public abstract class ServerPlayNetworkHandlerMixin { + @Shadow + public ServerPlayerEntity player; + + @Inject( + method = "handleMessage", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/server/PlayerManager;broadcast(Lnet/minecraft/text/Text;Ljava/util/function/Function;Lnet/minecraft/network/MessageType;Ljava/util/UUID;)V", + shift = At.Shift.BEFORE + ) + ) + public void onGameMessage(TextStream.Message message, CallbackInfo info) { + ServerChatEvents.EVENT.invoker().onChatMessage(player, message.getRaw()); + } + + @Inject( + method = "onSignUpdate", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/block/entity/SignBlockEntity;markDirty()V", + shift = At.Shift.BEFORE + ), + locals = LocalCapture.CAPTURE_FAILHARD + ) + public void onSignUpdate(UpdateSignC2SPacket packet, List signText, CallbackInfo info, + ServerWorld serverWorld, BlockPos blockPos, BlockState blockState, BlockEntity blockEntity, SignBlockEntity signBlockEntity) + { + // Pull the raw text from the input. + String[] rawTexts = new String[4]; + for (int i=0; i info) { + ServerPlayerEntity player = (ServerPlayerEntity) (Object) this; + if (player.getRemovalReason() == null) { + PlayerEvents.PLAYER_CHANGED_DIMENSION.invoker().onPlayerChangedDimension(player); + } + } +} diff --git a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/mixin/ThreadedAnvilChunkStorageMixin.java b/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/mixin/ThreadedAnvilChunkStorageMixin.java new file mode 100644 index 00000000..d26ea0c1 --- /dev/null +++ b/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/mixin/ThreadedAnvilChunkStorageMixin.java @@ -0,0 +1,32 @@ +package org.dynmap.fabric_1_18_2.mixin; + +import net.minecraft.server.world.ChunkHolder; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.server.world.ThreadedAnvilChunkStorage; +import net.minecraft.world.chunk.Chunk; +import org.dynmap.fabric_1_18_2.access.ProtoChunkAccessor; +import org.dynmap.fabric_1_18_2.event.CustomServerChunkEvents; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(value = ThreadedAnvilChunkStorage.class, priority = 666 /* fire before Fabric API CHUNK_LOAD event */) +public abstract class ThreadedAnvilChunkStorageMixin { + @Final + @Shadow + ServerWorld world; + + @Inject( + /* Same place as fabric-lifecycle-events-v1 event CHUNK_LOAD (we will fire before it) */ + method = "method_17227", + at = @At("TAIL") + ) + private void onChunkGenerate(ChunkHolder chunkHolder, Chunk protoChunk, CallbackInfoReturnable callbackInfoReturnable) { + if (((ProtoChunkAccessor)protoChunk).getTouchedByWorldGen()) { + CustomServerChunkEvents.CHUNK_GENERATE.invoker().onChunkGenerate(this.world, callbackInfoReturnable.getReturnValue()); + } + } +} \ No newline at end of file diff --git a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/mixin/WorldChunkMixin.java b/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/mixin/WorldChunkMixin.java new file mode 100644 index 00000000..6d3b1059 --- /dev/null +++ b/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/mixin/WorldChunkMixin.java @@ -0,0 +1,25 @@ +package org.dynmap.fabric_1_18_2.mixin; + +import net.minecraft.block.BlockState; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import net.minecraft.world.chunk.WorldChunk; +import org.dynmap.fabric_1_18_2.event.BlockEvents; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(WorldChunk.class) +public abstract class WorldChunkMixin { + @Shadow + public abstract World getWorld(); + + @Inject(method = "setBlockState", at = @At("RETURN")) + public void setBlockState(BlockPos pos, BlockState state, boolean moved, CallbackInfoReturnable info) { + if (info.getReturnValue() != null) { + BlockEvents.BLOCK_EVENT.invoker().onBlockEvent(this.getWorld(), pos); + } + } +} diff --git a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/permissions/FilePermissions.java b/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/permissions/FilePermissions.java new file mode 100644 index 00000000..f9ac9012 --- /dev/null +++ b/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/permissions/FilePermissions.java @@ -0,0 +1,103 @@ +package org.dynmap.fabric_1_18_2.permissions; + +import net.minecraft.entity.player.PlayerEntity; +import org.dynmap.ConfigurationNode; +import org.dynmap.Log; +import org.dynmap.fabric_1_18_2.DynmapPlugin; + +import java.io.File; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class FilePermissions implements PermissionProvider { + private HashMap> perms; + private Set defperms; + + public static FilePermissions create() { + File f = new File("dynmap/permissions.yml"); + if (!f.exists()) + return null; + ConfigurationNode cfg = new ConfigurationNode(f); + cfg.load(); + + Log.info("Using permissions.yml for access control"); + + return new FilePermissions(cfg); + } + + private FilePermissions(ConfigurationNode cfg) { + perms = new HashMap>(); + for (String k : cfg.keySet()) { + List p = cfg.getStrings(k, null); + if (p != null) { + k = k.toLowerCase(); + HashSet pset = new HashSet(); + for (String perm : p) { + pset.add(perm.toLowerCase()); + } + perms.put(k, pset); + if (k.equals("defaultuser")) { + defperms = pset; + } + } + } + } + + private boolean hasPerm(String player, String perm) { + Set ps = perms.get(player); + if ((ps != null) && (ps.contains(perm))) { + return true; + } + if (defperms.contains(perm)) { + return true; + } + return false; + } + + @Override + public Set hasOfflinePermissions(String player, Set perms) { + player = player.toLowerCase(); + HashSet rslt = new HashSet(); + if (DynmapPlugin.plugin.isOp(player)) { + rslt.addAll(perms); + } else { + for (String p : perms) { + if (hasPerm(player, p)) { + rslt.add(p); + } + } + } + return rslt; + } + + @Override + public boolean hasOfflinePermission(String player, String perm) { + player = player.toLowerCase(); + if (DynmapPlugin.plugin.isOp(player)) { + return true; + } else { + return hasPerm(player, perm); + } + } + + @Override + public boolean has(PlayerEntity psender, String permission) { + if (psender != null) { + String n = psender.getName().getString().toLowerCase(); + return hasPerm(n, permission); + } + return true; + } + + @Override + public boolean hasPermissionNode(PlayerEntity psender, String permission) { + if (psender != null) { + String player = psender.getName().getString().toLowerCase(); + return DynmapPlugin.plugin.isOp(player); + } + return false; + } + +} diff --git a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/permissions/OpPermissions.java b/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/permissions/OpPermissions.java new file mode 100644 index 00000000..bb5c43ed --- /dev/null +++ b/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/permissions/OpPermissions.java @@ -0,0 +1,52 @@ +package org.dynmap.fabric_1_18_2.permissions; + +import net.minecraft.entity.player.PlayerEntity; +import org.dynmap.Log; +import org.dynmap.fabric_1_18_2.DynmapPlugin; + +import java.util.HashSet; +import java.util.Set; + +public class OpPermissions implements PermissionProvider { + public HashSet usrCommands = new HashSet(); + + public OpPermissions(String[] usrCommands) { + for (String usrCommand : usrCommands) { + this.usrCommands.add(usrCommand); + } + Log.info("Using ops.txt for access control"); + } + + @Override + public Set hasOfflinePermissions(String player, Set perms) { + HashSet rslt = new HashSet(); + if (DynmapPlugin.plugin.isOp(player)) { + rslt.addAll(perms); + } + return rslt; + } + + @Override + public boolean hasOfflinePermission(String player, String perm) { + return DynmapPlugin.plugin.isOp(player); + } + + @Override + public boolean has(PlayerEntity psender, String permission) { + if (psender != null) { + if (usrCommands.contains(permission)) { + return true; + } + return DynmapPlugin.plugin.isOp(psender.getName().getString()); + } + return true; + } + + @Override + public boolean hasPermissionNode(PlayerEntity psender, String permission) { + if (psender != null) { + return DynmapPlugin.plugin.isOp(psender.getName().getString()); + } + return true; + } +} diff --git a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/permissions/PermissionProvider.java b/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/permissions/PermissionProvider.java new file mode 100644 index 00000000..3a36249e --- /dev/null +++ b/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/permissions/PermissionProvider.java @@ -0,0 +1,16 @@ +package org.dynmap.fabric_1_18_2.permissions; + +import net.minecraft.entity.player.PlayerEntity; + +import java.util.Set; + +public interface PermissionProvider { + boolean has(PlayerEntity sender, String permission); + + boolean hasPermissionNode(PlayerEntity sender, String permission); + + Set hasOfflinePermissions(String player, Set perms); + + boolean hasOfflinePermission(String player, String perm); + +} diff --git a/fabric-1.19/src/main/resources/assets/dynmap/icon.png b/fabric-1.19/src/main/resources/assets/dynmap/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..d18f3e145d02440b065b2365ff14b9261b5877c4 GIT binary patch literal 34043 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%0AL%*pBb$DiCiIy`b6`#WF% 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" + #aws_secret_access_key: "" + #prefix: "" + +components: + - class: org.dynmap.ClientConfigurationComponent + + - class: org.dynmap.InternalClientUpdateComponent + sendhealth: true + sendposition: true + allowwebchat: true + webchat-interval: 5 + hidewebchatip: false + trustclientname: false + includehiddenplayers: false + # (optional) if true, color codes in player display names are used + use-name-colors: false + # (optional) if true, player login IDs will be used for web chat when their IPs match + use-player-login-ip: true + # (optional) if use-player-login-ip is true, setting this to true will cause chat messages not matching a known player IP to be ignored + require-player-login-ip: false + # (optional) block player login IDs that are banned from chatting + block-banned-player-chat: true + # Require login for web-to-server chat (requires login-enabled: true) + webchat-requires-login: false + # If set to true, users must have dynmap.webchat permission in order to chat + webchat-permissions: false + # Limit length of single chat messages + chatlengthlimit: 256 + # # Optional - make players hidden when they are inside/underground/in shadows (#=light level: 0=full shadow,15=sky) + # hideifshadow: 4 + # # Optional - make player hidden when they are under cover (#=sky light level,0=underground,15=open to sky) + # hideifundercover: 14 + # # (Optional) if true, players that are crouching/sneaking will be hidden + hideifsneaking: false + # If true, player positions/status is protected (login with ID with dynmap.playermarkers.seeall permission required for info other than self) + protected-player-info: false + # If true, hide players with invisibility potion effects active + hide-if-invisiblity-potion: true + # If true, player names are not shown on map, chat, list + hidenames: false + #- class: org.dynmap.JsonFileClientUpdateComponent + # writeinterval: 1 + # sendhealth: true + # sendposition: true + # allowwebchat: true + # webchat-interval: 5 + # hidewebchatip: false + # includehiddenplayers: false + # use-name-colors: false + # use-player-login-ip: false + # require-player-login-ip: false + # block-banned-player-chat: true + # hideifshadow: 0 + # hideifundercover: 0 + # hideifsneaking: false + # # Require login for web-to-server chat (requires login-enabled: true) + # webchat-requires-login: false + # # If set to true, users must have dynmap.webchat permission in order to chat + # webchat-permissions: false + # # Limit length of single chat messages + # chatlengthlimit: 256 + # hide-if-invisiblity-potion: true + # hidenames: false + + - class: org.dynmap.SimpleWebChatComponent + allowchat: true + # If true, web UI users can supply name for chat using 'playername' URL parameter. 'trustclientname' must also be set true. + allowurlname: false + + # Note: this component is needed for the dmarker commands, and for the Marker API to be available to other plugins + - class: org.dynmap.MarkersComponent + type: markers + showlabel: false + enablesigns: false + # Default marker set for sign markers + default-sign-set: markers + # (optional) add spawn point markers to standard marker layer + showspawn: true + spawnicon: world + spawnlabel: "Spawn" + # (optional) layer for showing offline player's positions (for 'maxofflinetime' minutes after logoff) + showofflineplayers: false + offlinelabel: "Offline" + offlineicon: offlineuser + offlinehidebydefault: true + offlineminzoom: 0 + maxofflinetime: 30 + # (optional) layer for showing player's spawn beds + showspawnbeds: false + spawnbedlabel: "Spawn Beds" + spawnbedicon: bed + spawnbedhidebydefault: true + spawnbedminzoom: 0 + spawnbedformat: "%name%'s bed" + # (optional) Show world border (vanilla 1.8+) + showworldborder: true + worldborderlabel: "Border" + + - class: org.dynmap.ClientComponent + type: chat + allowurlname: false + - class: org.dynmap.ClientComponent + type: chatballoon + focuschatballoons: false + - class: org.dynmap.ClientComponent + type: chatbox + showplayerfaces: true + messagettl: 5 + # Optional: set number of lines in scrollable message history: if set, messagettl is not used to age out messages + #scrollback: 100 + # Optional: set maximum number of lines visible for chatbox + #visiblelines: 10 + # Optional: send push button + sendbutton: false + - class: org.dynmap.ClientComponent + type: playermarkers + showplayerfaces: true + showplayerhealth: true + # If true, show player body too (only valid if showplayerfaces=true) + showplayerbody: false + # Option to make player faces small - don't use with showplayerhealth or largeplayerfaces + smallplayerfaces: false + # Option to make player faces larger - don't use with showplayerhealth or smallplayerfaces + largeplayerfaces: false + # Optional - make player faces layer hidden by default + hidebydefault: false + # Optional - ordering priority in layer menu (low goes before high - default is 0) + layerprio: 0 + # Optional - label for player marker layer (default is 'Players') + label: "Players" + + #- class: org.dynmap.ClientComponent + # type: digitalclock + - class: org.dynmap.ClientComponent + type: link + + - class: org.dynmap.ClientComponent + type: timeofdayclock + showdigitalclock: true + #showweather: true + # Mouse pointer world coordinate display + - class: org.dynmap.ClientComponent + type: coord + label: "Location" + hidey: false + show-mcr: false + show-chunk: false + + # Note: more than one logo component can be defined + #- class: org.dynmap.ClientComponent + # type: logo + # text: "Dynmap" + # #logourl: "images/block_surface.png" + # linkurl: "http://forums.bukkit.org/threads/dynmap.489/" + # # Valid positions: top-left, top-right, bottom-left, bottom-right + # position: bottom-right + + #- class: org.dynmap.ClientComponent + # type: inactive + # timeout: 1800 # in seconds (1800 seconds = 30 minutes) + # redirecturl: inactive.html + # #showmessage: 'You were inactive for too long.' + + #- class: org.dynmap.TestComponent + # stuff: "This is some configuration-value" + +# Treat hiddenplayers.txt as a whitelist for players to be shown on the map? (Default false) +display-whitelist: false + +# How often a tile gets rendered (in seconds). +renderinterval: 1 + +# How many tiles on update queue before accelerate render interval +renderacceleratethreshold: 60 + +# How often to render tiles when backlog is above renderacceleratethreshold +renderaccelerateinterval: 0.2 + +# How many update tiles to work on at once (if not defined, default is 1/2 the number of cores) +tiles-rendered-at-once: 2 + +# If true, use normal priority threads for rendering (versus low priority) - this can keep rendering +# from starving on busy Windows boxes (Linux JVMs pretty much ignore thread priority), but may result +# in more competition for CPU resources with other processes +usenormalthreadpriority: true + +# Save and restore pending tile renders - prevents their loss on server shutdown or /reload +saverestorepending: true + +# Save period for pending jobs (in seconds): periodic saving for crash recovery of jobs +save-pending-period: 900 + +# Zoom-out tile update period - how often to scan for and process tile updates into zoom-out tiles (in seconds) +zoomoutperiod: 30 + +# Control whether zoom out tiles are validated on startup (can be needed if zoomout processing is interrupted, but can be expensive on large maps) +initial-zoomout-validate: true + +# Default delay on processing of updated tiles, in seconds. This can reduce potentially expensive re-rendering +# of frequently updated tiles (such as due to machines, pistons, quarries or other automation). Values can +# also be set on individual worlds and individual maps. +tileupdatedelay: 30 + +# Tile hashing is used to minimize tile file updates when no changes have occurred - set to false to disable +enabletilehash: true + +# Optional - hide ores: render as normal stone (so that they aren't revealed by maps) +#hideores: true + +# Optional - enabled BetterGrass style rendering of grass and snow block sides +#better-grass: true + +# Optional - enable smooth lighting by default on all maps supporting it (can be set per map as lighting option) +smooth-lighting: true + +# Optional - use world provider lighting table (good for custom worlds with custom lighting curves, like nether) +# false=classic Dynmap lighting curve +use-brightness-table: true + +# Optional - render specific block names using the textures and models of another block name: can be used to hide/disguise specific +# blocks (e.g. make ores look like stone, hide chests) or to provide simple support for rendering unsupported custom blocks +block-alias: +# "minecraft:quartz_ore": "stone" +# "diamond_ore": "coal_ore" + +# Default image format for HDMaps (png, jpg, jpg-q75, jpg-q80, jpg-q85, jpg-q90, jpg-q95, jpg-q100, webp, webp-q75, webp-q80, webp-q85, webp-q90, webp-q95, webp-q100, webp-l), +# Note: any webp format requires the presence of the 'webp command line tools' (cwebp, dwebp) (https://developers.google.com/speed/webp/download) +# +# Has no effect on maps with explicit format settings +image-format: jpg-q90 + +# If cwebp or dwebp are not on the PATH, use these settings to provide their full path. Do not use these settings if the tools are on the PATH +# For Windows, include .exe +# +#cwebpPath: /usr/bin/cwebp +#dwebpPath: /usr/bin/dwebp + +# use-generated-textures: if true, use generated textures (same as client); false is static water/lava textures +# correct-water-lighting: if true, use corrected water lighting (same as client); false is legacy water (darker) +# transparent-leaves: if true, leaves are transparent (lighting-wise): false is needed for some Spout versions that break lighting on leaf blocks +use-generated-textures: true +correct-water-lighting: true +transparent-leaves: true + +# ctm-support: if true, Connected Texture Mod (CTM) in texture packs is enabled (default) +ctm-support: true +# custom-colors-support: if true, Custom Colors in texture packs is enabled (default) +custom-colors-support: true + +# Control loading of player faces (if set to false, skins are never fetched) +#fetchskins: false + +# Control updating of player faces, once loaded (if faces are being managed by other apps or manually) +#refreshskins: false + +# Customize URL used for fetching player skins (%player% is macro for name, %uuid% for UUID) +skin-url: "http://skins.minecraft.net/MinecraftSkins/%player%.png" + +# Control behavior for new (1.0+) compass orientation (sunrise moved 90 degrees: east is now what used to be south) +# default is 'newrose' (preserve pre-1.0 maps, rotate rose) +# 'newnorth' is used to rotate maps and rose (requires fullrender of any HDMap map - same as 'newrose' for FlatMap or KzedMap) +compass-mode: newnorth + +# Triggers for automatic updates : blockupdate-with-id is debug for breaking down updates by ID:meta +# To disable, set just 'none' and comment/delete the rest +render-triggers: + - blockupdate + #- blockupdate-with-id + - chunkgenerate + #- none + +# Title for the web page - if not specified, defaults to the server's name (unless it is the default of 'Unknown Server') +#webpage-title: "My Awesome Server Map" + +# The path where the tile-files are placed. +tilespath: web/tiles + +# The path where the web-files are located. +webpath: web + +# If set to false, disable extraction of webpath content (good if using custom web UI or 3rd party web UI) +# Note: web interface is unsupported in this configuration - you're on your own +update-webpath-files: true + +# The path were the /dynmapexp command exports OBJ ZIP files +exportpath: export + +# The network-interface the webserver will bind to (0.0.0.0 for all interfaces, 127.0.0.1 for only local access). +# If not set, uses same setting as server in server.properties (or 0.0.0.0 if not specified) +#webserver-bindaddress: 0.0.0.0 + +# The TCP-port the webserver will listen on. +webserver-port: 8123 + +# Maximum concurrent session on internal web server - limits resources used in Bukkit server +max-sessions: 30 + +# Disables Webserver portion of Dynmap (Advanced users only) +disable-webserver: false + +# Enable/disable having the web server allow symbolic links (true=compatible with existing code, false=more secure (default)) +allow-symlinks: true + +# Enable login support +login-enabled: false +# Require login to access website (requires login-enabled: true) +login-required: false + +# Period between tile renders for fullrender, in seconds (non-zero to pace fullrenders, lessen CPU load) +timesliceinterval: 0.0 + +# Maximum chunk loads per server tick (1/20th of a second) - reducing this below 90 will impact render performance, but also will reduce server thread load +maxchunkspertick: 200 + +# Progress report interval for fullrender/radiusrender, in tiles. Must be 100 or greater +progressloginterval: 100 + +# Parallel fullrender: if defined, number of concurrent threads used for fullrender or radiusrender +# Note: setting this will result in much more intensive CPU use, some additional memory use. Caution should be used when +# setting this to equal or exceed the number of physical cores on the system. +#parallelrendercnt: 4 + +# Interval the browser should poll for updates. +updaterate: 2000 + +# If nonzero, server will pause fullrender/radiusrender processing when 'fullrenderplayerlimit' or more users are logged in +fullrenderplayerlimit: 0 +# If nonzero, server will pause update render processing when 'updateplayerlimit' or more users are logged in +updateplayerlimit: 0 +# Target limit on server thread use - msec per tick +per-tick-time-limit: 50 +# If TPS of server is below this setting, update renders processing is paused +update-min-tps: 18.0 +# If TPS of server is below this setting, full/radius renders processing is paused +fullrender-min-tps: 18.0 +# If TPS of server is below this setting, zoom out processing is paused +zoomout-min-tps: 18.0 + +showplayerfacesinmenu: true + +# Control whether players that are hidden or not on current map are grayed out (true=yes) +grayplayerswhenhidden: true + +# Set sidebaropened: 'true' to pin menu sidebar opened permanently, 'pinned' to default the sidebar to pinned, but allow it to unpin +#sidebaropened: true + +# Customized HTTP response headers - add 'id: value' pairs to all HTTP response headers (internal web server only) +#http-response-headers: +# Access-Control-Allow-Origin: "my-domain.com" +# X-Custom-Header-Of-Mine: "MyHeaderValue" + +# Trusted proxies for web server - which proxy addresses are trusted to supply valid X-Forwarded-For fields +# This now supports both IP address, and subnet ranges (e.g. 192.168.1.0/24 or 202.24.0.0/14 ) +trusted-proxies: + - "127.0.0.1" + - "0:0:0:0:0:0:0:1" + +joinmessage: "%playername% joined" +quitmessage: "%playername% quit" +spammessage: "You may only chat once every %interval% seconds." +# format for messages from web: %playername% substitutes sender ID (typically IP), %message% includes text +webmsgformat: "&color;2[WEB] %playername%: &color;f%message%" + +# Control whether layer control is presented on the UI (default is true) +showlayercontrol: true + +# Enable checking for banned IPs via banned-ips.txt (internal web server only) +check-banned-ips: true + +# Default selection when map page is loaded +defaultzoom: 0 +defaultworld: world +defaultmap: flat +# (optional) Zoom level and map to switch to when following a player, if possible +#followzoom: 3 +#followmap: surface + +# If true, make persistent record of IP addresses used by player logins, to support web IP to player matching +persist-ids-by-ip: true + +# If true, map text to cyrillic +cyrillic-support: false + +# Messages to customize +msg: + maptypes: "Map Types" + players: "Players" + chatrequireslogin: "Chat Requires Login" + chatnotallowed: "You are not permitted to send chat messages" + hiddennamejoin: "Player joined" + hiddennamequit: "Player quit" + +# URL for client configuration (only need to be tailored for proxies or other non-standard configurations) +url: + # configuration URL + #configuration: "up/configuration" + # update URL + #update: "up/world/{world}/{timestamp}" + # sendmessage URL + #sendmessage: "up/sendmessage" + # login URL + #login: "up/login" + # register URL + #register: "up/register" + # tiles base URL + #tiles: "tiles/" + # markers base URL + #markers: "tiles/" + # Snapshot cache size, in chunks +snapshotcachesize: 500 +# Snapshot cache uses soft references (true), else weak references (false) +soft-ref-cache: true + +# Player enter/exit title messages for map markers +# +# Processing period - how often to check player positions vs markers - default is 1000ms (1 second) +#enterexitperiod: 1000 +# Title message fade in time, in ticks (0.05 second intervals) - default is 10 (1/2 second) +#titleFadeIn: 10 +# Title message stay time, in ticks (0.05 second intervals) - default is 70 (3.5 seconds) +#titleStay: 70 +# Title message fade out time, in ticks (0.05 seocnd intervals) - default is 20 (1 second) +#titleFadeOut: 20 +# Enter/exit messages use on screen titles (true - default), if false chat messages are sent instead +#enterexitUseTitle: true +# Set true if new enter messages should supercede pending exit messages (vs being queued in order), default false +#enterReplacesExits: true + +# Published public URL for Dynmap server (allows users to use 'dynmap url' command to get public URL usable to access server +# If not set, 'dynmap url' will not return anything. URL should be fully qualified (e.g. https://mc.westeroscraft.com/) +#publicURL: http://my.greatserver.com/dynmap + +# Set to true to enable verbose startup messages - can help with debugging map configuration problems +# Set to false for a much quieter startup log +verbose: false + +# Enables debugging. +#debuggers: +# - class: org.dynmap.debug.LogDebugger +# Debug: dump blocks missing render data +dump-missing-blocks: false + +# Log4J defense: string substituted for attempts to use macros in web chat +hackAttemptBlurb: "(IaM5uchA1337Haxr-Ban Me!)" diff --git a/fabric-1.19/src/main/resources/dynmap.mixins.json b/fabric-1.19/src/main/resources/dynmap.mixins.json new file mode 100644 index 00000000..9ab81811 --- /dev/null +++ b/fabric-1.19/src/main/resources/dynmap.mixins.json @@ -0,0 +1,19 @@ +{ + "required": true, + "minVersion": "0.8", + "package": "org.dynmap.fabric_1_18_2.mixin", + "compatibilityLevel": "JAVA_16", + "mixins": [ + "BiomeEffectsAccessor", + "MinecraftServerMixin", + "PlayerManagerMixin", + "ProtoChunkMixin", + "ServerPlayerEntityMixin", + "ServerPlayNetworkHandlerMixin", + "ThreadedAnvilChunkStorageMixin", + "WorldChunkMixin" + ], + "injectors": { + "defaultRequire": 1 + } +} diff --git a/fabric-1.19/src/main/resources/fabric.mod.json b/fabric-1.19/src/main/resources/fabric.mod.json new file mode 100644 index 00000000..3abb52b0 --- /dev/null +++ b/fabric-1.19/src/main/resources/fabric.mod.json @@ -0,0 +1,33 @@ +{ + "schemaVersion": 1, + "id": "dynmap", + "version": "${version}", + "name": "Dynmap", + "description": "Dynamic, Google-maps style rendered maps for your Minecraft server", + "authors": [ + "mikeprimm", + "LolHens", + "i509VCB" + ], + "contact": { + "homepage": "https://github.com/webbukkit/dynmap", + "sources": "https://github.com/webbukkit/dynmap" + }, + "license": "Apache-2.0", + "icon": "assets/dynmap/icon.png", + "environment": "*", + "entrypoints": { + "main": [ + "org.dynmap.fabric_1_18_2.DynmapMod" + ] + }, + "mixins": [ + "dynmap.mixins.json" + ], + + "depends": { + "fabricloader": ">=0.13.3", + "fabric": ">=0.47.8", + "minecraft": ">=1.18.2" + } +} diff --git a/fabric-1.19/src/main/resources/permissions.yml.example b/fabric-1.19/src/main/resources/permissions.yml.example new file mode 100644 index 00000000..a25f9adc --- /dev/null +++ b/fabric-1.19/src/main/resources/permissions.yml.example @@ -0,0 +1,27 @@ +# +# Sample permissions.yml for dynmap - trivial, flat-file based permissions for dynmap features +# To use, copy this file to dynmap/permissions.yml, and edit appropriate. File is YAML format. +# +# All operators have full permissions to all functions. +# All users receive the permissions under the 'defaultuser' section +# Specific users can be given more permissions by defining a section with their name containing their permisssions +# All permissions correspond to those documented here (https://github.com/webbukkit/dynmap/wiki/Permissions), but +# do NOT have the 'dynmap.' prefix when used here (e.g. 'dynmap.fullrender' permission is just 'fullrender' here). +# +defaultuser: + - render + - show.self + - hide.self + - sendtoweb + - stats + - marker.list + - marker.listsets + - marker.icons + - webregister + - webchat + #- marker.sign + +#playername1: +# - fullrender +# - cancelrender +# - radiusrender From 0ba89fefc4363b3d5119589851fd80fb7dd4e776 Mon Sep 17 00:00:00 2001 From: Kosma Moczek Date: Thu, 19 May 2022 17:15:49 +0200 Subject: [PATCH 09/27] fabric-1.19: rename 1.18.2 -> 1.19 --- .../DynmapMod.java | 2 +- .../DynmapPlugin.java | 26 +++++++++---------- .../FabricAdapter.java | 2 +- .../FabricCommandSender.java | 2 +- .../FabricLogger.java | 2 +- .../FabricMapChunkCache.java | 2 +- .../FabricPlayer.java | 2 +- .../FabricServer.java | 6 ++--- .../FabricWorld.java | 2 +- .../{fabric_1_18_2 => fabric_1_19}/NBT.java | 2 +- .../TaskRecord.java | 2 +- .../VersionCheck.java | 2 +- .../access/ProtoChunkAccessor.java | 2 +- .../command/DmapCommand.java | 4 +-- .../command/DmarkerCommand.java | 4 +-- .../command/DynmapCommand.java | 4 +-- .../command/DynmapCommandExecutor.java | 4 +-- .../command/DynmapExpCommand.java | 4 +-- .../event/BlockEvents.java | 2 +- .../event/CustomServerChunkEvents.java | 2 +- .../event/CustomServerLifecycleEvents.java | 2 +- .../event/PlayerEvents.java | 2 +- .../event/ServerChatEvents.java | 2 +- .../mixin/BiomeEffectsAccessor.java | 2 +- .../mixin/MinecraftServerMixin.java | 4 +-- .../mixin/PlayerManagerMixin.java | 4 +-- .../mixin/ProtoChunkMixin.java | 4 +-- .../mixin/ServerPlayNetworkHandlerMixin.java | 6 ++--- .../mixin/ServerPlayerEntityMixin.java | 4 +-- .../mixin/ThreadedAnvilChunkStorageMixin.java | 6 ++--- .../mixin/WorldChunkMixin.java | 4 +-- .../permissions/FilePermissions.java | 4 +-- .../permissions/OpPermissions.java | 4 +-- .../permissions/PermissionProvider.java | 2 +- .../src/main/resources/dynmap.mixins.json | 2 +- .../src/main/resources/fabric.mod.json | 4 +-- 36 files changed, 67 insertions(+), 67 deletions(-) rename fabric-1.19/src/main/java/org/dynmap/{fabric_1_18_2 => fabric_1_19}/DynmapMod.java (98%) rename fabric-1.19/src/main/java/org/dynmap/{fabric_1_18_2 => fabric_1_19}/DynmapPlugin.java (97%) rename fabric-1.19/src/main/java/org/dynmap/{fabric_1_18_2 => fabric_1_19}/FabricAdapter.java (91%) rename fabric-1.19/src/main/java/org/dynmap/{fabric_1_18_2 => fabric_1_19}/FabricCommandSender.java (96%) rename fabric-1.19/src/main/java/org/dynmap/{fabric_1_18_2 => fabric_1_19}/FabricLogger.java (96%) rename fabric-1.19/src/main/java/org/dynmap/{fabric_1_18_2 => fabric_1_19}/FabricMapChunkCache.java (99%) rename fabric-1.19/src/main/java/org/dynmap/{fabric_1_18_2 => fabric_1_19}/FabricPlayer.java (99%) rename fabric-1.19/src/main/java/org/dynmap/{fabric_1_18_2 => fabric_1_19}/FabricServer.java (99%) rename fabric-1.19/src/main/java/org/dynmap/{fabric_1_18_2 => fabric_1_19}/FabricWorld.java (99%) rename fabric-1.19/src/main/java/org/dynmap/{fabric_1_18_2 => fabric_1_19}/NBT.java (98%) rename fabric-1.19/src/main/java/org/dynmap/{fabric_1_18_2 => fabric_1_19}/TaskRecord.java (96%) rename fabric-1.19/src/main/java/org/dynmap/{fabric_1_18_2 => fabric_1_19}/VersionCheck.java (99%) rename fabric-1.19/src/main/java/org/dynmap/{fabric_1_18_2 => fabric_1_19}/access/ProtoChunkAccessor.java (65%) rename fabric-1.19/src/main/java/org/dynmap/{fabric_1_18_2 => fabric_1_19}/command/DmapCommand.java (60%) rename fabric-1.19/src/main/java/org/dynmap/{fabric_1_18_2 => fabric_1_19}/command/DmarkerCommand.java (61%) rename fabric-1.19/src/main/java/org/dynmap/{fabric_1_18_2 => fabric_1_19}/command/DynmapCommand.java (61%) rename fabric-1.19/src/main/java/org/dynmap/{fabric_1_18_2 => fabric_1_19}/command/DynmapCommandExecutor.java (96%) rename fabric-1.19/src/main/java/org/dynmap/{fabric_1_18_2 => fabric_1_19}/command/DynmapExpCommand.java (62%) rename fabric-1.19/src/main/java/org/dynmap/{fabric_1_18_2 => fabric_1_19}/event/BlockEvents.java (97%) rename fabric-1.19/src/main/java/org/dynmap/{fabric_1_18_2 => fabric_1_19}/event/CustomServerChunkEvents.java (94%) rename fabric-1.19/src/main/java/org/dynmap/{fabric_1_18_2 => fabric_1_19}/event/CustomServerLifecycleEvents.java (93%) rename fabric-1.19/src/main/java/org/dynmap/{fabric_1_18_2 => fabric_1_19}/event/PlayerEvents.java (98%) rename fabric-1.19/src/main/java/org/dynmap/{fabric_1_18_2 => fabric_1_19}/event/ServerChatEvents.java (94%) rename fabric-1.19/src/main/java/org/dynmap/{fabric_1_18_2 => fabric_1_19}/mixin/BiomeEffectsAccessor.java (86%) rename fabric-1.19/src/main/java/org/dynmap/{fabric_1_18_2 => fabric_1_19}/mixin/MinecraftServerMixin.java (83%) rename fabric-1.19/src/main/java/org/dynmap/{fabric_1_18_2 => fabric_1_19}/mixin/PlayerManagerMixin.java (93%) rename fabric-1.19/src/main/java/org/dynmap/{fabric_1_18_2 => fabric_1_19}/mixin/ProtoChunkMixin.java (91%) rename fabric-1.19/src/main/java/org/dynmap/{fabric_1_18_2 => fabric_1_19}/mixin/ServerPlayNetworkHandlerMixin.java (94%) rename fabric-1.19/src/main/java/org/dynmap/{fabric_1_18_2 => fabric_1_19}/mixin/ServerPlayerEntityMixin.java (93%) rename fabric-1.19/src/main/java/org/dynmap/{fabric_1_18_2 => fabric_1_19}/mixin/ThreadedAnvilChunkStorageMixin.java (88%) rename fabric-1.19/src/main/java/org/dynmap/{fabric_1_18_2 => fabric_1_19}/mixin/WorldChunkMixin.java (90%) rename fabric-1.19/src/main/java/org/dynmap/{fabric_1_18_2 => fabric_1_19}/permissions/FilePermissions.java (96%) rename fabric-1.19/src/main/java/org/dynmap/{fabric_1_18_2 => fabric_1_19}/permissions/OpPermissions.java (93%) rename fabric-1.19/src/main/java/org/dynmap/{fabric_1_18_2 => fabric_1_19}/permissions/PermissionProvider.java (89%) diff --git a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/DynmapMod.java b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/DynmapMod.java similarity index 98% rename from fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/DynmapMod.java rename to fabric-1.19/src/main/java/org/dynmap/fabric_1_19/DynmapMod.java index db446234..3bcf5f32 100644 --- a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/DynmapMod.java +++ b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/DynmapMod.java @@ -1,4 +1,4 @@ -package org.dynmap.fabric_1_18_2; +package org.dynmap.fabric_1_19; import net.fabricmc.api.ModInitializer; import net.fabricmc.loader.api.FabricLoader; diff --git a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/DynmapPlugin.java b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/DynmapPlugin.java similarity index 97% rename from fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/DynmapPlugin.java rename to fabric-1.19/src/main/java/org/dynmap/fabric_1_19/DynmapPlugin.java index 49a1955b..280f6923 100644 --- a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/DynmapPlugin.java +++ b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/DynmapPlugin.java @@ -1,4 +1,4 @@ -package org.dynmap.fabric_1_18_2; +package org.dynmap.fabric_1_19; import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.exceptions.CommandSyntaxException; @@ -39,18 +39,18 @@ import org.dynmap.common.DynmapCommandSender; import org.dynmap.common.DynmapListenerManager; import org.dynmap.common.DynmapPlayer; import org.dynmap.common.chunk.GenericChunkCache; -import org.dynmap.fabric_1_18_2.command.DmapCommand; -import org.dynmap.fabric_1_18_2.command.DmarkerCommand; -import org.dynmap.fabric_1_18_2.command.DynmapCommand; -import org.dynmap.fabric_1_18_2.command.DynmapExpCommand; -import org.dynmap.fabric_1_18_2.event.BlockEvents; -import org.dynmap.fabric_1_18_2.event.CustomServerChunkEvents; -import org.dynmap.fabric_1_18_2.event.CustomServerLifecycleEvents; -import org.dynmap.fabric_1_18_2.event.PlayerEvents; -import org.dynmap.fabric_1_18_2.mixin.BiomeEffectsAccessor; -import org.dynmap.fabric_1_18_2.permissions.FilePermissions; -import org.dynmap.fabric_1_18_2.permissions.OpPermissions; -import org.dynmap.fabric_1_18_2.permissions.PermissionProvider; +import org.dynmap.fabric_1_19.command.DmapCommand; +import org.dynmap.fabric_1_19.command.DmarkerCommand; +import org.dynmap.fabric_1_19.command.DynmapCommand; +import org.dynmap.fabric_1_19.command.DynmapExpCommand; +import org.dynmap.fabric_1_19.event.BlockEvents; +import org.dynmap.fabric_1_19.event.CustomServerChunkEvents; +import org.dynmap.fabric_1_19.event.CustomServerLifecycleEvents; +import org.dynmap.fabric_1_19.event.PlayerEvents; +import org.dynmap.fabric_1_19.mixin.BiomeEffectsAccessor; +import org.dynmap.fabric_1_19.permissions.FilePermissions; +import org.dynmap.fabric_1_19.permissions.OpPermissions; +import org.dynmap.fabric_1_19.permissions.PermissionProvider; import org.dynmap.permissions.PermissionsHandler; import org.dynmap.renderer.DynmapBlockState; diff --git a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/FabricAdapter.java b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/FabricAdapter.java similarity index 91% rename from fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/FabricAdapter.java rename to fabric-1.19/src/main/java/org/dynmap/fabric_1_19/FabricAdapter.java index ee3d9a3a..d10f7060 100644 --- a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/FabricAdapter.java +++ b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/FabricAdapter.java @@ -1,4 +1,4 @@ -package org.dynmap.fabric_1_18_2; +package org.dynmap.fabric_1_19; import net.minecraft.server.world.ServerWorld; import org.dynmap.DynmapLocation; diff --git a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/FabricCommandSender.java b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/FabricCommandSender.java similarity index 96% rename from fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/FabricCommandSender.java rename to fabric-1.19/src/main/java/org/dynmap/fabric_1_19/FabricCommandSender.java index 1280ccc9..29769a68 100644 --- a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/FabricCommandSender.java +++ b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/FabricCommandSender.java @@ -1,4 +1,4 @@ -package org.dynmap.fabric_1_18_2; +package org.dynmap.fabric_1_19; import net.minecraft.server.command.ServerCommandSource; import net.minecraft.text.LiteralText; diff --git a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/FabricLogger.java b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/FabricLogger.java similarity index 96% rename from fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/FabricLogger.java rename to fabric-1.19/src/main/java/org/dynmap/fabric_1_19/FabricLogger.java index 4253fc89..0aeebc45 100644 --- a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/FabricLogger.java +++ b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/FabricLogger.java @@ -1,4 +1,4 @@ -package org.dynmap.fabric_1_18_2; +package org.dynmap.fabric_1_19; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; diff --git a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/FabricMapChunkCache.java b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/FabricMapChunkCache.java similarity index 99% rename from fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/FabricMapChunkCache.java rename to fabric-1.19/src/main/java/org/dynmap/fabric_1_19/FabricMapChunkCache.java index f7394767..fdea7adc 100644 --- a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/FabricMapChunkCache.java +++ b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/FabricMapChunkCache.java @@ -1,4 +1,4 @@ -package org.dynmap.fabric_1_18_2; +package org.dynmap.fabric_1_19; import net.minecraft.nbt.*; import net.minecraft.server.world.ServerChunkManager; diff --git a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/FabricPlayer.java b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/FabricPlayer.java similarity index 99% rename from fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/FabricPlayer.java rename to fabric-1.19/src/main/java/org/dynmap/fabric_1_19/FabricPlayer.java index 8655569c..535ee4a5 100644 --- a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/FabricPlayer.java +++ b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/FabricPlayer.java @@ -1,4 +1,4 @@ -package org.dynmap.fabric_1_18_2; +package org.dynmap.fabric_1_19; import com.google.common.collect.Iterables; import com.google.gson.Gson; diff --git a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/FabricServer.java b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/FabricServer.java similarity index 99% rename from fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/FabricServer.java rename to fabric-1.19/src/main/java/org/dynmap/fabric_1_19/FabricServer.java index 309c9ba2..769821cf 100644 --- a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/FabricServer.java +++ b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/FabricServer.java @@ -1,4 +1,4 @@ -package org.dynmap.fabric_1_18_2; +package org.dynmap.fabric_1_19; import com.mojang.authlib.GameProfile; import net.fabricmc.loader.api.FabricLoader; @@ -28,8 +28,8 @@ import org.dynmap.common.BiomeMap; import org.dynmap.common.DynmapListenerManager; import org.dynmap.common.DynmapPlayer; import org.dynmap.common.DynmapServerInterface; -import org.dynmap.fabric_1_18_2.event.BlockEvents; -import org.dynmap.fabric_1_18_2.event.ServerChatEvents; +import org.dynmap.fabric_1_19.event.BlockEvents; +import org.dynmap.fabric_1_19.event.ServerChatEvents; import org.dynmap.utils.MapChunkCache; import org.dynmap.utils.VisibilityLimit; diff --git a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/FabricWorld.java b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/FabricWorld.java similarity index 99% rename from fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/FabricWorld.java rename to fabric-1.19/src/main/java/org/dynmap/fabric_1_19/FabricWorld.java index 0ae91886..77da953c 100644 --- a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/FabricWorld.java +++ b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/FabricWorld.java @@ -1,4 +1,4 @@ -package org.dynmap.fabric_1_18_2; +package org.dynmap.fabric_1_19; import net.minecraft.util.math.BlockPos; import net.minecraft.util.registry.RegistryKey; diff --git a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/NBT.java b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/NBT.java similarity index 98% rename from fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/NBT.java rename to fabric-1.19/src/main/java/org/dynmap/fabric_1_19/NBT.java index afaec108..2f8b52a5 100644 --- a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/NBT.java +++ b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/NBT.java @@ -1,4 +1,4 @@ -package org.dynmap.fabric_1_18_2; +package org.dynmap.fabric_1_19; import org.dynmap.common.chunk.GenericBitStorage; import org.dynmap.common.chunk.GenericNBTCompound; diff --git a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/TaskRecord.java b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/TaskRecord.java similarity index 96% rename from fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/TaskRecord.java rename to fabric-1.19/src/main/java/org/dynmap/fabric_1_19/TaskRecord.java index ecde4814..1c7e4440 100644 --- a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/TaskRecord.java +++ b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/TaskRecord.java @@ -1,4 +1,4 @@ -package org.dynmap.fabric_1_18_2; +package org.dynmap.fabric_1_19; import java.util.concurrent.FutureTask; diff --git a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/VersionCheck.java b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/VersionCheck.java similarity index 99% rename from fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/VersionCheck.java rename to fabric-1.19/src/main/java/org/dynmap/fabric_1_19/VersionCheck.java index 03ff3f5a..4b6f5bf5 100644 --- a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/VersionCheck.java +++ b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/VersionCheck.java @@ -1,4 +1,4 @@ -package org.dynmap.fabric_1_18_2; +package org.dynmap.fabric_1_19; import org.dynmap.DynmapCore; import org.dynmap.Log; diff --git a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/access/ProtoChunkAccessor.java b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/access/ProtoChunkAccessor.java similarity index 65% rename from fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/access/ProtoChunkAccessor.java rename to fabric-1.19/src/main/java/org/dynmap/fabric_1_19/access/ProtoChunkAccessor.java index 1b98c24d..350a250b 100644 --- a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/access/ProtoChunkAccessor.java +++ b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/access/ProtoChunkAccessor.java @@ -1,4 +1,4 @@ -package org.dynmap.fabric_1_18_2.access; +package org.dynmap.fabric_1_19.access; public interface ProtoChunkAccessor { boolean getTouchedByWorldGen(); diff --git a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/command/DmapCommand.java b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/command/DmapCommand.java similarity index 60% rename from fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/command/DmapCommand.java rename to fabric-1.19/src/main/java/org/dynmap/fabric_1_19/command/DmapCommand.java index 87690eda..d6907648 100644 --- a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/command/DmapCommand.java +++ b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/command/DmapCommand.java @@ -1,6 +1,6 @@ -package org.dynmap.fabric_1_18_2.command; +package org.dynmap.fabric_1_19.command; -import org.dynmap.fabric_1_18_2.DynmapPlugin; +import org.dynmap.fabric_1_19.DynmapPlugin; public class DmapCommand extends DynmapCommandExecutor { public DmapCommand(DynmapPlugin p) { diff --git a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/command/DmarkerCommand.java b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/command/DmarkerCommand.java similarity index 61% rename from fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/command/DmarkerCommand.java rename to fabric-1.19/src/main/java/org/dynmap/fabric_1_19/command/DmarkerCommand.java index e132b941..a5c31f02 100644 --- a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/command/DmarkerCommand.java +++ b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/command/DmarkerCommand.java @@ -1,6 +1,6 @@ -package org.dynmap.fabric_1_18_2.command; +package org.dynmap.fabric_1_19.command; -import org.dynmap.fabric_1_18_2.DynmapPlugin; +import org.dynmap.fabric_1_19.DynmapPlugin; public class DmarkerCommand extends DynmapCommandExecutor { public DmarkerCommand(DynmapPlugin p) { diff --git a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/command/DynmapCommand.java b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/command/DynmapCommand.java similarity index 61% rename from fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/command/DynmapCommand.java rename to fabric-1.19/src/main/java/org/dynmap/fabric_1_19/command/DynmapCommand.java index 8e4c3c67..698b847e 100644 --- a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/command/DynmapCommand.java +++ b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/command/DynmapCommand.java @@ -1,6 +1,6 @@ -package org.dynmap.fabric_1_18_2.command; +package org.dynmap.fabric_1_19.command; -import org.dynmap.fabric_1_18_2.DynmapPlugin; +import org.dynmap.fabric_1_19.DynmapPlugin; public class DynmapCommand extends DynmapCommandExecutor { public DynmapCommand(DynmapPlugin p) { diff --git a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/command/DynmapCommandExecutor.java b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/command/DynmapCommandExecutor.java similarity index 96% rename from fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/command/DynmapCommandExecutor.java rename to fabric-1.19/src/main/java/org/dynmap/fabric_1_19/command/DynmapCommandExecutor.java index bf2e90b5..bb4fc01b 100644 --- a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/command/DynmapCommandExecutor.java +++ b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/command/DynmapCommandExecutor.java @@ -1,4 +1,4 @@ -package org.dynmap.fabric_1_18_2.command; +package org.dynmap.fabric_1_19.command; import com.mojang.brigadier.Command; import com.mojang.brigadier.CommandDispatcher; @@ -8,7 +8,7 @@ import com.mojang.brigadier.tree.ArgumentCommandNode; import com.mojang.brigadier.tree.LiteralCommandNode; import com.mojang.brigadier.tree.RootCommandNode; import net.minecraft.server.command.ServerCommandSource; -import org.dynmap.fabric_1_18_2.DynmapPlugin; +import org.dynmap.fabric_1_19.DynmapPlugin; import java.util.Arrays; diff --git a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/command/DynmapExpCommand.java b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/command/DynmapExpCommand.java similarity index 62% rename from fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/command/DynmapExpCommand.java rename to fabric-1.19/src/main/java/org/dynmap/fabric_1_19/command/DynmapExpCommand.java index 4fb29b79..29df91fc 100644 --- a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/command/DynmapExpCommand.java +++ b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/command/DynmapExpCommand.java @@ -1,6 +1,6 @@ -package org.dynmap.fabric_1_18_2.command; +package org.dynmap.fabric_1_19.command; -import org.dynmap.fabric_1_18_2.DynmapPlugin; +import org.dynmap.fabric_1_19.DynmapPlugin; public class DynmapExpCommand extends DynmapCommandExecutor { public DynmapExpCommand(DynmapPlugin p) { diff --git a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/event/BlockEvents.java b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/event/BlockEvents.java similarity index 97% rename from fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/event/BlockEvents.java rename to fabric-1.19/src/main/java/org/dynmap/fabric_1_19/event/BlockEvents.java index 9ad017ca..3fefe2fa 100644 --- a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/event/BlockEvents.java +++ b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/event/BlockEvents.java @@ -1,4 +1,4 @@ -package org.dynmap.fabric_1_18_2.event; +package org.dynmap.fabric_1_19.event; import net.fabricmc.fabric.api.event.Event; import net.fabricmc.fabric.api.event.EventFactory; diff --git a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/event/CustomServerChunkEvents.java b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/event/CustomServerChunkEvents.java similarity index 94% rename from fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/event/CustomServerChunkEvents.java rename to fabric-1.19/src/main/java/org/dynmap/fabric_1_19/event/CustomServerChunkEvents.java index 5f3a1c9f..ee756e20 100644 --- a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/event/CustomServerChunkEvents.java +++ b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/event/CustomServerChunkEvents.java @@ -1,4 +1,4 @@ -package org.dynmap.fabric_1_18_2.event; +package org.dynmap.fabric_1_19.event; import net.fabricmc.fabric.api.event.Event; import net.fabricmc.fabric.api.event.EventFactory; diff --git a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/event/CustomServerLifecycleEvents.java b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/event/CustomServerLifecycleEvents.java similarity index 93% rename from fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/event/CustomServerLifecycleEvents.java rename to fabric-1.19/src/main/java/org/dynmap/fabric_1_19/event/CustomServerLifecycleEvents.java index 8ac46ae2..b6385ddd 100644 --- a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/event/CustomServerLifecycleEvents.java +++ b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/event/CustomServerLifecycleEvents.java @@ -1,4 +1,4 @@ -package org.dynmap.fabric_1_18_2.event; +package org.dynmap.fabric_1_19.event; import net.fabricmc.fabric.api.event.Event; import net.fabricmc.fabric.api.event.EventFactory; diff --git a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/event/PlayerEvents.java b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/event/PlayerEvents.java similarity index 98% rename from fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/event/PlayerEvents.java rename to fabric-1.19/src/main/java/org/dynmap/fabric_1_19/event/PlayerEvents.java index 1d584861..fc02bd34 100644 --- a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/event/PlayerEvents.java +++ b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/event/PlayerEvents.java @@ -1,4 +1,4 @@ -package org.dynmap.fabric_1_18_2.event; +package org.dynmap.fabric_1_19.event; import net.fabricmc.fabric.api.event.Event; import net.fabricmc.fabric.api.event.EventFactory; diff --git a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/event/ServerChatEvents.java b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/event/ServerChatEvents.java similarity index 94% rename from fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/event/ServerChatEvents.java rename to fabric-1.19/src/main/java/org/dynmap/fabric_1_19/event/ServerChatEvents.java index 2724320b..6ab805c4 100644 --- a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/event/ServerChatEvents.java +++ b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/event/ServerChatEvents.java @@ -1,4 +1,4 @@ -package org.dynmap.fabric_1_18_2.event; +package org.dynmap.fabric_1_19.event; import net.fabricmc.fabric.api.event.Event; import net.fabricmc.fabric.api.event.EventFactory; diff --git a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/mixin/BiomeEffectsAccessor.java b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/mixin/BiomeEffectsAccessor.java similarity index 86% rename from fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/mixin/BiomeEffectsAccessor.java rename to fabric-1.19/src/main/java/org/dynmap/fabric_1_19/mixin/BiomeEffectsAccessor.java index f1d75396..ab6e135c 100644 --- a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/mixin/BiomeEffectsAccessor.java +++ b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/mixin/BiomeEffectsAccessor.java @@ -1,4 +1,4 @@ -package org.dynmap.fabric_1_18_2.mixin; +package org.dynmap.fabric_1_19.mixin; import net.minecraft.world.biome.BiomeEffects; import org.spongepowered.asm.mixin.Mixin; diff --git a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/mixin/MinecraftServerMixin.java b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/mixin/MinecraftServerMixin.java similarity index 83% rename from fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/mixin/MinecraftServerMixin.java rename to fabric-1.19/src/main/java/org/dynmap/fabric_1_19/mixin/MinecraftServerMixin.java index b3d1e82f..6eee0d55 100644 --- a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/mixin/MinecraftServerMixin.java +++ b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/mixin/MinecraftServerMixin.java @@ -1,7 +1,7 @@ -package org.dynmap.fabric_1_18_2.mixin; +package org.dynmap.fabric_1_19.mixin; import net.minecraft.server.MinecraftServer; -import org.dynmap.fabric_1_18_2.event.CustomServerLifecycleEvents; +import org.dynmap.fabric_1_19.event.CustomServerLifecycleEvents; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; diff --git a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/mixin/PlayerManagerMixin.java b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/mixin/PlayerManagerMixin.java similarity index 93% rename from fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/mixin/PlayerManagerMixin.java rename to fabric-1.19/src/main/java/org/dynmap/fabric_1_19/mixin/PlayerManagerMixin.java index 2a733175..a356cf25 100644 --- a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/mixin/PlayerManagerMixin.java +++ b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/mixin/PlayerManagerMixin.java @@ -1,9 +1,9 @@ -package org.dynmap.fabric_1_18_2.mixin; +package org.dynmap.fabric_1_19.mixin; import net.minecraft.network.ClientConnection; import net.minecraft.server.PlayerManager; import net.minecraft.server.network.ServerPlayerEntity; -import org.dynmap.fabric_1_18_2.event.PlayerEvents; +import org.dynmap.fabric_1_19.event.PlayerEvents; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; diff --git a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/mixin/ProtoChunkMixin.java b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/mixin/ProtoChunkMixin.java similarity index 91% rename from fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/mixin/ProtoChunkMixin.java rename to fabric-1.19/src/main/java/org/dynmap/fabric_1_19/mixin/ProtoChunkMixin.java index e591e8b2..4d0856be 100644 --- a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/mixin/ProtoChunkMixin.java +++ b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/mixin/ProtoChunkMixin.java @@ -1,9 +1,9 @@ -package org.dynmap.fabric_1_18_2.mixin; +package org.dynmap.fabric_1_19.mixin; import net.minecraft.block.BlockState; import net.minecraft.util.math.BlockPos; import net.minecraft.world.chunk.ProtoChunk; -import org.dynmap.fabric_1_18_2.access.ProtoChunkAccessor; +import org.dynmap.fabric_1_19.access.ProtoChunkAccessor; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; diff --git a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/mixin/ServerPlayNetworkHandlerMixin.java b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/mixin/ServerPlayNetworkHandlerMixin.java similarity index 94% rename from fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/mixin/ServerPlayNetworkHandlerMixin.java rename to fabric-1.19/src/main/java/org/dynmap/fabric_1_19/mixin/ServerPlayNetworkHandlerMixin.java index 9a373518..4fda22fc 100644 --- a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/mixin/ServerPlayNetworkHandlerMixin.java +++ b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/mixin/ServerPlayNetworkHandlerMixin.java @@ -1,4 +1,4 @@ -package org.dynmap.fabric_1_18_2.mixin; +package org.dynmap.fabric_1_19.mixin; import net.minecraft.block.BlockState; import net.minecraft.block.entity.BlockEntity; @@ -13,8 +13,8 @@ import net.minecraft.util.math.BlockPos; import java.util.List; -import org.dynmap.fabric_1_18_2.event.BlockEvents; -import org.dynmap.fabric_1_18_2.event.ServerChatEvents; +import org.dynmap.fabric_1_19.event.BlockEvents; +import org.dynmap.fabric_1_19.event.ServerChatEvents; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; diff --git a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/mixin/ServerPlayerEntityMixin.java b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/mixin/ServerPlayerEntityMixin.java similarity index 93% rename from fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/mixin/ServerPlayerEntityMixin.java rename to fabric-1.19/src/main/java/org/dynmap/fabric_1_19/mixin/ServerPlayerEntityMixin.java index 769136a8..a2b1edd6 100644 --- a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/mixin/ServerPlayerEntityMixin.java +++ b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/mixin/ServerPlayerEntityMixin.java @@ -1,9 +1,9 @@ -package org.dynmap.fabric_1_18_2.mixin; +package org.dynmap.fabric_1_19.mixin; import net.minecraft.entity.Entity; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.world.ServerWorld; -import org.dynmap.fabric_1_18_2.event.PlayerEvents; +import org.dynmap.fabric_1_19.event.PlayerEvents; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; diff --git a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/mixin/ThreadedAnvilChunkStorageMixin.java b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/mixin/ThreadedAnvilChunkStorageMixin.java similarity index 88% rename from fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/mixin/ThreadedAnvilChunkStorageMixin.java rename to fabric-1.19/src/main/java/org/dynmap/fabric_1_19/mixin/ThreadedAnvilChunkStorageMixin.java index d26ea0c1..908fd912 100644 --- a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/mixin/ThreadedAnvilChunkStorageMixin.java +++ b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/mixin/ThreadedAnvilChunkStorageMixin.java @@ -1,11 +1,11 @@ -package org.dynmap.fabric_1_18_2.mixin; +package org.dynmap.fabric_1_19.mixin; import net.minecraft.server.world.ChunkHolder; import net.minecraft.server.world.ServerWorld; import net.minecraft.server.world.ThreadedAnvilChunkStorage; import net.minecraft.world.chunk.Chunk; -import org.dynmap.fabric_1_18_2.access.ProtoChunkAccessor; -import org.dynmap.fabric_1_18_2.event.CustomServerChunkEvents; +import org.dynmap.fabric_1_19.access.ProtoChunkAccessor; +import org.dynmap.fabric_1_19.event.CustomServerChunkEvents; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; diff --git a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/mixin/WorldChunkMixin.java b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/mixin/WorldChunkMixin.java similarity index 90% rename from fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/mixin/WorldChunkMixin.java rename to fabric-1.19/src/main/java/org/dynmap/fabric_1_19/mixin/WorldChunkMixin.java index 6d3b1059..fee76172 100644 --- a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/mixin/WorldChunkMixin.java +++ b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/mixin/WorldChunkMixin.java @@ -1,10 +1,10 @@ -package org.dynmap.fabric_1_18_2.mixin; +package org.dynmap.fabric_1_19.mixin; import net.minecraft.block.BlockState; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import net.minecraft.world.chunk.WorldChunk; -import org.dynmap.fabric_1_18_2.event.BlockEvents; +import org.dynmap.fabric_1_19.event.BlockEvents; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; diff --git a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/permissions/FilePermissions.java b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/permissions/FilePermissions.java similarity index 96% rename from fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/permissions/FilePermissions.java rename to fabric-1.19/src/main/java/org/dynmap/fabric_1_19/permissions/FilePermissions.java index f9ac9012..78f21d3b 100644 --- a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/permissions/FilePermissions.java +++ b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/permissions/FilePermissions.java @@ -1,9 +1,9 @@ -package org.dynmap.fabric_1_18_2.permissions; +package org.dynmap.fabric_1_19.permissions; import net.minecraft.entity.player.PlayerEntity; import org.dynmap.ConfigurationNode; import org.dynmap.Log; -import org.dynmap.fabric_1_18_2.DynmapPlugin; +import org.dynmap.fabric_1_19.DynmapPlugin; import java.io.File; import java.util.HashMap; diff --git a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/permissions/OpPermissions.java b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/permissions/OpPermissions.java similarity index 93% rename from fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/permissions/OpPermissions.java rename to fabric-1.19/src/main/java/org/dynmap/fabric_1_19/permissions/OpPermissions.java index bb5c43ed..fdf9369b 100644 --- a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/permissions/OpPermissions.java +++ b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/permissions/OpPermissions.java @@ -1,8 +1,8 @@ -package org.dynmap.fabric_1_18_2.permissions; +package org.dynmap.fabric_1_19.permissions; import net.minecraft.entity.player.PlayerEntity; import org.dynmap.Log; -import org.dynmap.fabric_1_18_2.DynmapPlugin; +import org.dynmap.fabric_1_19.DynmapPlugin; import java.util.HashSet; import java.util.Set; diff --git a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/permissions/PermissionProvider.java b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/permissions/PermissionProvider.java similarity index 89% rename from fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/permissions/PermissionProvider.java rename to fabric-1.19/src/main/java/org/dynmap/fabric_1_19/permissions/PermissionProvider.java index 3a36249e..7affe811 100644 --- a/fabric-1.19/src/main/java/org/dynmap/fabric_1_18_2/permissions/PermissionProvider.java +++ b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/permissions/PermissionProvider.java @@ -1,4 +1,4 @@ -package org.dynmap.fabric_1_18_2.permissions; +package org.dynmap.fabric_1_19.permissions; import net.minecraft.entity.player.PlayerEntity; diff --git a/fabric-1.19/src/main/resources/dynmap.mixins.json b/fabric-1.19/src/main/resources/dynmap.mixins.json index 9ab81811..c5c9e89b 100644 --- a/fabric-1.19/src/main/resources/dynmap.mixins.json +++ b/fabric-1.19/src/main/resources/dynmap.mixins.json @@ -1,7 +1,7 @@ { "required": true, "minVersion": "0.8", - "package": "org.dynmap.fabric_1_18_2.mixin", + "package": "org.dynmap.fabric_1_19.mixin", "compatibilityLevel": "JAVA_16", "mixins": [ "BiomeEffectsAccessor", diff --git a/fabric-1.19/src/main/resources/fabric.mod.json b/fabric-1.19/src/main/resources/fabric.mod.json index 3abb52b0..bb3637b2 100644 --- a/fabric-1.19/src/main/resources/fabric.mod.json +++ b/fabric-1.19/src/main/resources/fabric.mod.json @@ -18,7 +18,7 @@ "environment": "*", "entrypoints": { "main": [ - "org.dynmap.fabric_1_18_2.DynmapMod" + "org.dynmap.fabric_1_19.DynmapMod" ] }, "mixins": [ @@ -28,6 +28,6 @@ "depends": { "fabricloader": ">=0.13.3", "fabric": ">=0.47.8", - "minecraft": ">=1.18.2" + "minecraft": "1.19.x" } } From 61b03bcdbbce4cfb73c956fb8207ca2acd4d2824 Mon Sep 17 00:00:00 2001 From: Kosma Moczek Date: Thu, 19 May 2022 17:20:21 +0200 Subject: [PATCH 10/27] fabric-1.19: migrateMappings to 1.19-pre1+build.1 --- fabric-1.19/gradle.properties | 8 ++++---- .../main/java/org/dynmap/fabric_1_19/DynmapPlugin.java | 2 +- .../java/org/dynmap/fabric_1_19/FabricCommandSender.java | 4 ++-- .../main/java/org/dynmap/fabric_1_19/FabricPlayer.java | 8 ++++---- .../main/java/org/dynmap/fabric_1_19/FabricServer.java | 6 +++--- .../fabric_1_19/mixin/ServerPlayNetworkHandlerMixin.java | 4 ++-- 6 files changed, 16 insertions(+), 16 deletions(-) diff --git a/fabric-1.19/gradle.properties b/fabric-1.19/gradle.properties index bdb66d3a..b2366258 100644 --- a/fabric-1.19/gradle.properties +++ b/fabric-1.19/gradle.properties @@ -1,4 +1,4 @@ -minecraft_version=1.18.2 -yarn_mappings=1.18.2+build.1 -loader_version=0.13.3 -fabric_version=0.47.8+1.18.2 +minecraft_version=1.19-pre1 +yarn_mappings=1.19-pre1+build.1 +loader_version=0.14.5 +fabric_version=0.52.4+1.19 diff --git a/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/DynmapPlugin.java b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/DynmapPlugin.java index 280f6923..fc122cd8 100644 --- a/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/DynmapPlugin.java +++ b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/DynmapPlugin.java @@ -527,7 +527,7 @@ public class DynmapPlugin { // getPlayer throws a CommandSyntaxException, so getEntity and instanceof for safety if (commandSource.getEntity() instanceof ServerPlayerEntity) { - psender = commandSource.getPlayer(); + psender = commandSource.getPlayerOrThrow(); } if (psender != null) { diff --git a/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/FabricCommandSender.java b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/FabricCommandSender.java index 29769a68..b73af70c 100644 --- a/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/FabricCommandSender.java +++ b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/FabricCommandSender.java @@ -1,7 +1,7 @@ package org.dynmap.fabric_1_19; import net.minecraft.server.command.ServerCommandSource; -import net.minecraft.text.LiteralText; +import net.minecraft.text.LiteralTextContent; import net.minecraft.text.Text; import org.dynmap.common.DynmapCommandSender; @@ -25,7 +25,7 @@ public class FabricCommandSender implements DynmapCommandSender { @Override public void sendMessage(String msg) { if (sender != null) { - Text ichatcomponent = new LiteralText(msg); + Text ichatcomponent = new LiteralTextContent(msg); sender.sendFeedback(ichatcomponent, false); } } diff --git a/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/FabricPlayer.java b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/FabricPlayer.java index 535ee4a5..0986adfc 100644 --- a/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/FabricPlayer.java +++ b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/FabricPlayer.java @@ -12,7 +12,7 @@ import net.minecraft.network.packet.s2c.play.TitleFadeS2CPacket; import net.minecraft.network.packet.s2c.play.TitleS2CPacket; import net.minecraft.server.network.ServerPlayNetworkHandler; import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.text.LiteralText; +import net.minecraft.text.LiteralTextContent; import net.minecraft.text.Text; import net.minecraft.util.Util; import net.minecraft.util.math.Vec3d; @@ -188,7 +188,7 @@ public class FabricPlayer extends FabricCommandSender implements DynmapPlayer { @Override public void sendMessage(String msg) { - Text ichatcomponent = new LiteralText(msg); + Text ichatcomponent = new LiteralTextContent(msg); player.sendSystemMessage(ichatcomponent, Util.NIL_UUID); } @@ -239,12 +239,12 @@ public class FabricPlayer extends FabricCommandSender implements DynmapPlayer { TitleFadeS2CPacket times = new TitleFadeS2CPacket(fadeInTicks, stayTicks, fadeOutTicks); player.networkHandler.sendPacket(times); if (title != null) { - TitleS2CPacket titlepkt = new TitleS2CPacket(new LiteralText(title)); + TitleS2CPacket titlepkt = new TitleS2CPacket(new LiteralTextContent(title)); player.networkHandler.sendPacket(titlepkt); } if (subtitle != null) { - SubtitleS2CPacket subtitlepkt = new SubtitleS2CPacket(new LiteralText(subtitle)); + SubtitleS2CPacket subtitlepkt = new SubtitleS2CPacket(new LiteralTextContent(subtitle)); player.networkHandler.sendPacket(subtitlepkt); } } diff --git a/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/FabricServer.java b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/FabricServer.java index 769821cf..8e9e5401 100644 --- a/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/FabricServer.java +++ b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/FabricServer.java @@ -12,7 +12,7 @@ import net.minecraft.server.BannedPlayerList; import net.minecraft.server.MinecraftServer; import net.minecraft.server.PlayerManager; import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.text.LiteralText; +import net.minecraft.text.LiteralTextContent; import net.minecraft.text.Text; import net.minecraft.util.UserCache; import net.minecraft.util.Util; @@ -272,7 +272,7 @@ public class FabricServer extends DynmapServerInterface { case SIGN_CHANGE: BlockEvents.SIGN_CHANGE_EVENT.register((world, pos, lines, material, player) -> { plugin.core.processSignChange("fabric", FabricWorld.getWorldName(plugin, world), - pos.getX(), pos.getY(), pos.getZ(), lines, player.getName().asString()); + pos.getX(), pos.getY(), pos.getZ(), lines, player.getName().getContent()); }); break; @@ -292,7 +292,7 @@ public class FabricServer extends DynmapServerInterface { @Override public void broadcastMessage(String msg) { - Text component = new LiteralText(msg); + Text component = new LiteralTextContent(msg); server.getPlayerManager().broadcast(component, MessageType.SYSTEM, Util.NIL_UUID); Log.info(stripChatColor(msg)); } diff --git a/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/mixin/ServerPlayNetworkHandlerMixin.java b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/mixin/ServerPlayNetworkHandlerMixin.java index 4fda22fc..19c027a9 100644 --- a/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/mixin/ServerPlayNetworkHandlerMixin.java +++ b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/mixin/ServerPlayNetworkHandlerMixin.java @@ -8,7 +8,7 @@ import net.minecraft.server.filter.TextStream; import net.minecraft.server.network.ServerPlayNetworkHandler; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.world.ServerWorld; -import net.minecraft.text.LiteralText; +import net.minecraft.text.LiteralTextContent; import net.minecraft.util.math.BlockPos; import java.util.List; @@ -61,6 +61,6 @@ public abstract class ServerPlayNetworkHandlerMixin { // Put the (possibly updated) texts in the sign. Ignore filtering (is this OK?). for (int i=0; i Date: Thu, 19 May 2022 17:23:10 +0200 Subject: [PATCH 11/27] settings.gradle: add fabric-1.19 --- settings.gradle | 2 ++ 1 file changed, 2 insertions(+) diff --git a/settings.gradle b/settings.gradle index b7e91e37..735f48fa 100644 --- a/settings.gradle +++ b/settings.gradle @@ -23,6 +23,7 @@ include ':bukkit-helper' include ':dynmap-api' include ':DynmapCore' include ':DynmapCoreAPI' +include ':fabric-1.19' include ':fabric-1.18.2' include ':fabric-1.18' include ':fabric-1.17.1' @@ -51,6 +52,7 @@ project(':bukkit-helper').projectDir = "$rootDir/bukkit-helper" as File project(':dynmap-api').projectDir = "$rootDir/dynmap-api" as File project(':DynmapCore').projectDir = "$rootDir/DynmapCore" as File project(':DynmapCoreAPI').projectDir = "$rootDir/DynmapCoreAPI" as File +project(':fabric-1.19').projectDir = "$rootDir/fabric-1.19" as File project(':fabric-1.18.2').projectDir = "$rootDir/fabric-1.18.2" as File project(':fabric-1.18').projectDir = "$rootDir/fabric-1.18" as File project(':fabric-1.17.1').projectDir = "$rootDir/fabric-1.17.1" as File From f80bb89d96417144e0cdaaa54e42a5fc2be4bde8 Mon Sep 17 00:00:00 2001 From: Kosma Moczek Date: Thu, 19 May 2022 18:49:55 +0200 Subject: [PATCH 12/27] fabric-1.19: move to Loom 0.12-SNAPSHOT --- fabric-1.19/build.gradle | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fabric-1.19/build.gradle b/fabric-1.19/build.gradle index 570efaf4..5d6eea4a 100644 --- a/fabric-1.19/build.gradle +++ b/fabric-1.19/build.gradle @@ -1,5 +1,6 @@ plugins { - id 'fabric-loom' version '0.11-SNAPSHOT' + // TODO: switch to a stable Loom release once 1.19 lands + id 'fabric-loom' version '0.12-SNAPSHOT' } archivesBaseName = "Dynmap" From 556051dc9a538546323fdb0625b61a076de23213 Mon Sep 17 00:00:00 2001 From: Kosma Moczek Date: Sun, 29 May 2022 12:35:53 +0200 Subject: [PATCH 13/27] build.gradle: workaround for Shadow not supporting Java 19 classes --- build.gradle | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/build.gradle b/build.gradle index f8877613..b8e6ac94 100644 --- a/build.gradle +++ b/build.gradle @@ -1,3 +1,16 @@ +// Workaround for Shadow not supporting Java 19 classes. +// Remove this once Shadow updates. +// See: https://github.com/johnrengelman/shadow/pull/770 +// See: https://discord.com/channels/722722769950998560/793019909055578113/978939925061857315 +buildscript { + configurations.all { + resolutionStrategy { + force("org.ow2.asm:asm:9.3") + force("org.ow2.asm:asm-commons:9.3") + } + } +} + plugins { id "com.github.johnrengelman.shadow" version "7.1.0" id 'java' From f02a73bb0db77c8cb53c1cae51ed2d8fb7e8d10f Mon Sep 17 00:00:00 2001 From: Kosma Moczek Date: Sun, 29 May 2022 13:26:51 +0200 Subject: [PATCH 14/27] fabric-1.19: do the actual porting work --- .../org/dynmap/fabric_1_19/DynmapPlugin.java | 2 +- .../fabric_1_19/FabricCommandSender.java | 2 +- .../fabric_1_19/FabricMapChunkCache.java | 3 ++- .../org/dynmap/fabric_1_19/FabricPlayer.java | 8 ++++---- .../org/dynmap/fabric_1_19/FabricServer.java | 6 +++--- .../org/dynmap/fabric_1_19/FabricWorld.java | 15 +++++++++++---- .../mixin/ServerPlayNetworkHandlerMixin.java | 19 ++++++++++++------- 7 files changed, 34 insertions(+), 21 deletions(-) diff --git a/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/DynmapPlugin.java b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/DynmapPlugin.java index fc122cd8..64de3ad3 100644 --- a/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/DynmapPlugin.java +++ b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/DynmapPlugin.java @@ -268,7 +268,7 @@ public class DynmapPlugin { } // TODO: Consider whether cheats are enabled for integrated server - return server.isSingleplayer() && player.equalsIgnoreCase(server.getSinglePlayerName()); + return server.isSingleplayer() && server.isHost(server.getPlayerManager().getPlayer(player).getGameProfile()); } boolean hasPerm(PlayerEntity psender, String permission) { diff --git a/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/FabricCommandSender.java b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/FabricCommandSender.java index b73af70c..b2bf4e49 100644 --- a/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/FabricCommandSender.java +++ b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/FabricCommandSender.java @@ -25,7 +25,7 @@ public class FabricCommandSender implements DynmapCommandSender { @Override public void sendMessage(String msg) { if (sender != null) { - Text ichatcomponent = new LiteralTextContent(msg); + Text ichatcomponent = Text.literal(msg); sender.sendFeedback(ichatcomponent, false); } } diff --git a/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/FabricMapChunkCache.java b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/FabricMapChunkCache.java index fdea7adc..4e63d359 100644 --- a/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/FabricMapChunkCache.java +++ b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/FabricMapChunkCache.java @@ -83,7 +83,8 @@ public class FabricMapChunkCache extends GenericMapChunkCache { ThreadedAnvilChunkStorage acl = cps.threadedAnvilChunkStorage; ChunkPos coord = new ChunkPos(x, z); - return acl.getNbt(coord); + // Async chunk reading is synchronized here. Perhaps we can do async and improve performance? + return acl.getNbt(coord).join().orElse(null); } catch (Exception exc) { Log.severe(String.format("Error reading chunk: %s,%d,%d", dw.getName(), x, z), exc); return null; diff --git a/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/FabricPlayer.java b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/FabricPlayer.java index 0986adfc..83bdf97b 100644 --- a/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/FabricPlayer.java +++ b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/FabricPlayer.java @@ -188,8 +188,8 @@ public class FabricPlayer extends FabricCommandSender implements DynmapPlayer { @Override public void sendMessage(String msg) { - Text ichatcomponent = new LiteralTextContent(msg); - player.sendSystemMessage(ichatcomponent, Util.NIL_UUID); + Text ichatcomponent = Text.literal(msg); + player.sendMessage(ichatcomponent); } @Override @@ -239,12 +239,12 @@ public class FabricPlayer extends FabricCommandSender implements DynmapPlayer { TitleFadeS2CPacket times = new TitleFadeS2CPacket(fadeInTicks, stayTicks, fadeOutTicks); player.networkHandler.sendPacket(times); if (title != null) { - TitleS2CPacket titlepkt = new TitleS2CPacket(new LiteralTextContent(title)); + TitleS2CPacket titlepkt = new TitleS2CPacket(Text.literal(title)); player.networkHandler.sendPacket(titlepkt); } if (subtitle != null) { - SubtitleS2CPacket subtitlepkt = new SubtitleS2CPacket(new LiteralTextContent(subtitle)); + SubtitleS2CPacket subtitlepkt = new SubtitleS2CPacket(Text.literal(subtitle)); player.networkHandler.sendPacket(subtitlepkt); } } diff --git a/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/FabricServer.java b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/FabricServer.java index 8e9e5401..f6a84c41 100644 --- a/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/FabricServer.java +++ b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/FabricServer.java @@ -272,7 +272,7 @@ public class FabricServer extends DynmapServerInterface { case SIGN_CHANGE: BlockEvents.SIGN_CHANGE_EVENT.register((world, pos, lines, material, player) -> { plugin.core.processSignChange("fabric", FabricWorld.getWorldName(plugin, world), - pos.getX(), pos.getY(), pos.getZ(), lines, player.getName().getContent()); + pos.getX(), pos.getY(), pos.getZ(), lines, player.getName().getString()); }); break; @@ -292,8 +292,8 @@ public class FabricServer extends DynmapServerInterface { @Override public void broadcastMessage(String msg) { - Text component = new LiteralTextContent(msg); - server.getPlayerManager().broadcast(component, MessageType.SYSTEM, Util.NIL_UUID); + Text component = Text.literal(msg); + server.getPlayerManager().broadcast(component, MessageType.SYSTEM); Log.info(stripChatColor(msg)); } diff --git a/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/FabricWorld.java b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/FabricWorld.java index 77da953c..500d4cba 100644 --- a/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/FabricWorld.java +++ b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/FabricWorld.java @@ -1,6 +1,7 @@ package org.dynmap.fabric_1_19; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; import net.minecraft.util.registry.RegistryKey; import net.minecraft.world.Heightmap; import net.minecraft.world.LightType; @@ -49,7 +50,7 @@ public class FabricWorld extends DynmapWorld { } public void updateWorld(World w) { - this.updateWorldHeights(w.getHeight(), w.getDimension().getMinimumY(), w.getSeaLevel()); + this.updateWorldHeights(w.getHeight(), w.getBottomY(), w.getSeaLevel()); } public FabricWorld(DynmapPlugin plugin, World w) { @@ -58,7 +59,7 @@ public class FabricWorld extends DynmapWorld { w.getRegistryKey() == World.NETHER, w.getRegistryKey() == World.END, w.getRegistryKey().getValue().getPath(), - w.getDimension().getMinimumY()); + w.getBottomY()); setWorldLoaded(w); } @@ -148,8 +149,14 @@ public class FabricWorld extends DynmapWorld { world = w; this.sealevel = w.getSeaLevel(); // Read actual current sealevel from world // Update lighting table - for (int i = 0; i < 16; i++) { - this.setBrightnessTableEntry(i, w.getDimension().getBrightness(i)); + for (int lightLevel = 0; lightLevel < 16; lightLevel++) { + // Algorithm based on LightmapTextureManager.getBrightness() + // We can't call that method because it's client-only. + // This means the code below can stop being correct if Mojang ever + // updates the curve; in that case we should reflect the changes. + float value = (float) lightLevel / 15.0f; + float brightness = value / (4.0f - 3.0f * value); + this.setBrightnessTableEntry(lightLevel, MathHelper.lerp(w.getDimension().ambientLight(), brightness, 1.0F)); } } diff --git a/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/mixin/ServerPlayNetworkHandlerMixin.java b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/mixin/ServerPlayNetworkHandlerMixin.java index 19c027a9..fa945b94 100644 --- a/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/mixin/ServerPlayNetworkHandlerMixin.java +++ b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/mixin/ServerPlayNetworkHandlerMixin.java @@ -3,16 +3,21 @@ package org.dynmap.fabric_1_19.mixin; import net.minecraft.block.BlockState; import net.minecraft.block.entity.BlockEntity; import net.minecraft.block.entity.SignBlockEntity; +import net.minecraft.network.MessageType; +import net.minecraft.network.encryption.SignedChatMessage; import net.minecraft.network.packet.c2s.play.UpdateSignC2SPacket; +import net.minecraft.server.filter.Message; import net.minecraft.server.filter.TextStream; import net.minecraft.server.network.ServerPlayNetworkHandler; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.world.ServerWorld; import net.minecraft.text.LiteralTextContent; +import net.minecraft.text.Text; import net.minecraft.util.math.BlockPos; import java.util.List; +import net.minecraft.util.registry.RegistryKey; import org.dynmap.fabric_1_19.event.BlockEvents; import org.dynmap.fabric_1_19.event.ServerChatEvents; import org.spongepowered.asm.mixin.Mixin; @@ -28,15 +33,15 @@ public abstract class ServerPlayNetworkHandlerMixin { public ServerPlayerEntity player; @Inject( - method = "handleMessage", + method = "method_44155", at = @At( value = "INVOKE", - target = "Lnet/minecraft/server/PlayerManager;broadcast(Lnet/minecraft/text/Text;Ljava/util/function/Function;Lnet/minecraft/network/MessageType;Ljava/util/UUID;)V", + target = "Lnet/minecraft/server/PlayerManager;broadcast(Lnet/minecraft/server/filter/Message;Lnet/minecraft/server/network/ServerPlayerEntity;Lnet/minecraft/util/registry/RegistryKey;)V", shift = At.Shift.BEFORE ) ) - public void onGameMessage(TextStream.Message message, CallbackInfo info) { - ServerChatEvents.EVENT.invoker().onChatMessage(player, message.getRaw()); + public void onGameMessage(Message message, CallbackInfo ci) { + ServerChatEvents.EVENT.invoker().onChatMessage(player, message.raw().getContent().getString()); } @Inject( @@ -48,19 +53,19 @@ public abstract class ServerPlayNetworkHandlerMixin { ), locals = LocalCapture.CAPTURE_FAILHARD ) - public void onSignUpdate(UpdateSignC2SPacket packet, List signText, CallbackInfo info, + public void onSignUpdate(UpdateSignC2SPacket packet, List> signText, CallbackInfo info, ServerWorld serverWorld, BlockPos blockPos, BlockState blockState, BlockEntity blockEntity, SignBlockEntity signBlockEntity) { // Pull the raw text from the input. String[] rawTexts = new String[4]; for (int i=0; i Date: Sun, 29 May 2022 14:44:11 +0200 Subject: [PATCH 15/27] fabric-1.19: update to 1.19-pre3 --- fabric-1.19/gradle.properties | 8 ++++---- .../main/java/org/dynmap/fabric_1_19/DynmapPlugin.java | 4 ++-- .../mixin/ServerPlayNetworkHandlerMixin.java | 10 +++++----- fabric-1.19/src/main/resources/fabric.mod.json | 4 ++-- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/fabric-1.19/gradle.properties b/fabric-1.19/gradle.properties index b2366258..a1ed7988 100644 --- a/fabric-1.19/gradle.properties +++ b/fabric-1.19/gradle.properties @@ -1,4 +1,4 @@ -minecraft_version=1.19-pre1 -yarn_mappings=1.19-pre1+build.1 -loader_version=0.14.5 -fabric_version=0.52.4+1.19 +minecraft_version=1.19-pre3 +yarn_mappings=1.19-pre3+build.4 +loader_version=0.14.6 +fabric_version=0.53.4+1.19 diff --git a/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/DynmapPlugin.java b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/DynmapPlugin.java index 64de3ad3..7c265749 100644 --- a/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/DynmapPlugin.java +++ b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/DynmapPlugin.java @@ -2,7 +2,7 @@ package org.dynmap.fabric_1_19; import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.exceptions.CommandSyntaxException; -import net.fabricmc.fabric.api.command.v1.CommandRegistrationCallback; +import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerChunkEvents; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents; @@ -96,7 +96,7 @@ public class DynmapPlugin { plugin = this; // Fabric events persist between server instances ServerLifecycleEvents.SERVER_STARTING.register(this::serverStart); - CommandRegistrationCallback.EVENT.register((dispatcher, dedicated) -> registerCommands(dispatcher)); + CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> registerCommands(dispatcher)); CustomServerLifecycleEvents.SERVER_STARTED_PRE_WORLD_LOAD.register(this::serverStarted); ServerLifecycleEvents.SERVER_STOPPING.register(this::serverStop); } diff --git a/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/mixin/ServerPlayNetworkHandlerMixin.java b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/mixin/ServerPlayNetworkHandlerMixin.java index fa945b94..89afc9bc 100644 --- a/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/mixin/ServerPlayNetworkHandlerMixin.java +++ b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/mixin/ServerPlayNetworkHandlerMixin.java @@ -6,7 +6,7 @@ import net.minecraft.block.entity.SignBlockEntity; import net.minecraft.network.MessageType; import net.minecraft.network.encryption.SignedChatMessage; import net.minecraft.network.packet.c2s.play.UpdateSignC2SPacket; -import net.minecraft.server.filter.Message; +import net.minecraft.server.filter.FilteredMessage; import net.minecraft.server.filter.TextStream; import net.minecraft.server.network.ServerPlayNetworkHandler; import net.minecraft.server.network.ServerPlayerEntity; @@ -33,14 +33,14 @@ public abstract class ServerPlayNetworkHandlerMixin { public ServerPlayerEntity player; @Inject( - method = "method_44155", + method = "handleDecoratedMessage", at = @At( value = "INVOKE", - target = "Lnet/minecraft/server/PlayerManager;broadcast(Lnet/minecraft/server/filter/Message;Lnet/minecraft/server/network/ServerPlayerEntity;Lnet/minecraft/util/registry/RegistryKey;)V", + target = "Lnet/minecraft/server/PlayerManager;broadcast(Lnet/minecraft/server/filter/FilteredMessage;Lnet/minecraft/server/network/ServerPlayerEntity;Lnet/minecraft/util/registry/RegistryKey;)V", shift = At.Shift.BEFORE ) ) - public void onGameMessage(Message message, CallbackInfo ci) { + public void onGameMessage(FilteredMessage message, CallbackInfo ci) { ServerChatEvents.EVENT.invoker().onChatMessage(player, message.raw().getContent().getString()); } @@ -53,7 +53,7 @@ public abstract class ServerPlayNetworkHandlerMixin { ), locals = LocalCapture.CAPTURE_FAILHARD ) - public void onSignUpdate(UpdateSignC2SPacket packet, List> signText, CallbackInfo info, + public void onSignUpdate(UpdateSignC2SPacket packet, List> signText, CallbackInfo info, ServerWorld serverWorld, BlockPos blockPos, BlockState blockState, BlockEntity blockEntity, SignBlockEntity signBlockEntity) { // Pull the raw text from the input. diff --git a/fabric-1.19/src/main/resources/fabric.mod.json b/fabric-1.19/src/main/resources/fabric.mod.json index bb3637b2..31df4672 100644 --- a/fabric-1.19/src/main/resources/fabric.mod.json +++ b/fabric-1.19/src/main/resources/fabric.mod.json @@ -26,8 +26,8 @@ ], "depends": { - "fabricloader": ">=0.13.3", - "fabric": ">=0.47.8", + "fabricloader": ">=0.14.6", + "fabric": ">=0.53.4", "minecraft": "1.19.x" } } From 078275d16d2844f82c0243e5b76295ead0ee35ac Mon Sep 17 00:00:00 2001 From: RedstoneFuture Date: Sun, 29 May 2022 15:28:06 +0200 Subject: [PATCH 16/27] Add no-permission message option --- DynmapCore/src/main/java/org/dynmap/DynmapCore.java | 6 +++++- fabric-1.14.4/src/main/resources/configuration.txt | 5 ++++- fabric-1.15.2/src/main/resources/configuration.txt | 3 +++ fabric-1.16.4/src/main/resources/configuration.txt | 3 +++ fabric-1.17.1/src/main/resources/configuration.txt | 3 +++ fabric-1.18.2/src/main/resources/configuration.txt | 3 +++ fabric-1.18/src/main/resources/configuration.txt | 3 +++ forge-1.12.2/src/main/resources/configuration.txt | 5 ++++- forge-1.14.4/src/main/resources/configuration.txt | 5 ++++- forge-1.15.2/src/main/resources/configuration.txt | 5 ++++- forge-1.16.5/src/main/resources/configuration.txt | 5 ++++- forge-1.17.1/src/main/resources/configuration.txt | 5 ++++- forge-1.18.2/src/main/resources/configuration.txt | 5 ++++- forge-1.18/src/main/resources/configuration.txt | 5 ++++- spigot/src/main/resources/configuration.txt | 3 +++ 15 files changed, 55 insertions(+), 9 deletions(-) diff --git a/DynmapCore/src/main/java/org/dynmap/DynmapCore.java b/DynmapCore/src/main/java/org/dynmap/DynmapCore.java index 41fcfd67..fba99b8f 100644 --- a/DynmapCore/src/main/java/org/dynmap/DynmapCore.java +++ b/DynmapCore/src/main/java/org/dynmap/DynmapCore.java @@ -135,6 +135,7 @@ public class DynmapCore implements DynmapCommonAPI { private int fullrenderplayerlimit; /* Number of online players that will cause fullrender processing to pause */ private int updateplayerlimit; /* Number of online players that will cause update processing to pause */ private String publicURL; // If set, public HRL for accessing dynmap (declared by administrator) + private String noPermissionMsg; private boolean didfullpause; private boolean didupdatepause; private Map> ids_by_ip = new HashMap>(); @@ -571,6 +572,9 @@ public class DynmapCore implements DynmapCommonAPI { Log.info("EXPERIMENTAL: chunk migration enabled"); publicURL = configuration.getString("publicURL", ""); + + /* Send this message if the player does not have permission to use the command */ + noPermissionMsg = configuration.getString("noPermissionMsg", "You don't have permission to use this command!"); /* Load preupdate/postupdate commands */ ImageIOManager.preUpdateCommand = configuration.getString("custom-commands/image-updates/preupdatecommand", ""); @@ -2097,7 +2101,7 @@ public class DynmapCore implements DynmapCommonAPI { if (!(sender instanceof DynmapPlayer) || sender.isOp()) { return true; } else if (!sender.hasPrivilege(permission.toLowerCase())) { - sender.sendMessage("You don't have permission to use this command!"); + sender.sendMessage(noPermissionMsg); return false; } return true; diff --git a/fabric-1.14.4/src/main/resources/configuration.txt b/fabric-1.14.4/src/main/resources/configuration.txt index 9889eaa3..cd925d90 100644 --- a/fabric-1.14.4/src/main/resources/configuration.txt +++ b/fabric-1.14.4/src/main/resources/configuration.txt @@ -470,7 +470,10 @@ soft-ref-cache: true # Published public URL for Dynmap server (allows users to use 'dynmap url' command to get public URL usable to access server # If not set, 'dynmap url' will not return anything. URL should be fully qualified (e.g. https://mc.westeroscraft.com/) #publicURL: http://my.greatserver.com/dynmap - + +# Send this message if the player does not have permission to use the command +noPermissionMsg: "You don't have permission to use this command!" + # Set to true to enable verbose startup messages - can help with debugging map configuration problems # Set to false for a much quieter startup log verbose: false diff --git a/fabric-1.15.2/src/main/resources/configuration.txt b/fabric-1.15.2/src/main/resources/configuration.txt index fbf2a220..cd925d90 100644 --- a/fabric-1.15.2/src/main/resources/configuration.txt +++ b/fabric-1.15.2/src/main/resources/configuration.txt @@ -471,6 +471,9 @@ soft-ref-cache: true # If not set, 'dynmap url' will not return anything. URL should be fully qualified (e.g. https://mc.westeroscraft.com/) #publicURL: http://my.greatserver.com/dynmap +# Send this message if the player does not have permission to use the command +noPermissionMsg: "You don't have permission to use this command!" + # Set to true to enable verbose startup messages - can help with debugging map configuration problems # Set to false for a much quieter startup log verbose: false diff --git a/fabric-1.16.4/src/main/resources/configuration.txt b/fabric-1.16.4/src/main/resources/configuration.txt index 41fefecf..9781d362 100644 --- a/fabric-1.16.4/src/main/resources/configuration.txt +++ b/fabric-1.16.4/src/main/resources/configuration.txt @@ -479,6 +479,9 @@ soft-ref-cache: true # If not set, 'dynmap url' will not return anything. URL should be fully qualified (e.g. https://mc.westeroscraft.com/) #publicURL: http://my.greatserver.com/dynmap +# Send this message if the player does not have permission to use the command +noPermissionMsg: "You don't have permission to use this command!" + # Set to true to enable verbose startup messages - can help with debugging map configuration problems # Set to false for a much quieter startup log verbose: false diff --git a/fabric-1.17.1/src/main/resources/configuration.txt b/fabric-1.17.1/src/main/resources/configuration.txt index 41fefecf..9781d362 100644 --- a/fabric-1.17.1/src/main/resources/configuration.txt +++ b/fabric-1.17.1/src/main/resources/configuration.txt @@ -479,6 +479,9 @@ soft-ref-cache: true # If not set, 'dynmap url' will not return anything. URL should be fully qualified (e.g. https://mc.westeroscraft.com/) #publicURL: http://my.greatserver.com/dynmap +# Send this message if the player does not have permission to use the command +noPermissionMsg: "You don't have permission to use this command!" + # Set to true to enable verbose startup messages - can help with debugging map configuration problems # Set to false for a much quieter startup log verbose: false diff --git a/fabric-1.18.2/src/main/resources/configuration.txt b/fabric-1.18.2/src/main/resources/configuration.txt index c0379e35..2e123c79 100644 --- a/fabric-1.18.2/src/main/resources/configuration.txt +++ b/fabric-1.18.2/src/main/resources/configuration.txt @@ -477,6 +477,9 @@ soft-ref-cache: true # If not set, 'dynmap url' will not return anything. URL should be fully qualified (e.g. https://mc.westeroscraft.com/) #publicURL: http://my.greatserver.com/dynmap +# Send this message if the player does not have permission to use the command +noPermissionMsg: "You don't have permission to use this command!" + # Set to true to enable verbose startup messages - can help with debugging map configuration problems # Set to false for a much quieter startup log verbose: false diff --git a/fabric-1.18/src/main/resources/configuration.txt b/fabric-1.18/src/main/resources/configuration.txt index c0379e35..2e123c79 100644 --- a/fabric-1.18/src/main/resources/configuration.txt +++ b/fabric-1.18/src/main/resources/configuration.txt @@ -477,6 +477,9 @@ soft-ref-cache: true # If not set, 'dynmap url' will not return anything. URL should be fully qualified (e.g. https://mc.westeroscraft.com/) #publicURL: http://my.greatserver.com/dynmap +# Send this message if the player does not have permission to use the command +noPermissionMsg: "You don't have permission to use this command!" + # Set to true to enable verbose startup messages - can help with debugging map configuration problems # Set to false for a much quieter startup log verbose: false diff --git a/forge-1.12.2/src/main/resources/configuration.txt b/forge-1.12.2/src/main/resources/configuration.txt index 8b7fd7ff..55c511d6 100644 --- a/forge-1.12.2/src/main/resources/configuration.txt +++ b/forge-1.12.2/src/main/resources/configuration.txt @@ -461,7 +461,10 @@ soft-ref-cache: true #enterexitUseTitle: true # Set true if new enter messages should supercede pending exit messages (vs being queued in order), default false #enterReplacesExits: true - + +# Send this message if the player does not have permission to use the command +noPermissionMsg: "You don't have permission to use this command!" + # Set to true to enable verbose startup messages - can help with debugging map configuration problems # Set to false for a much quieter startup log verbose: false diff --git a/forge-1.14.4/src/main/resources/configuration.txt b/forge-1.14.4/src/main/resources/configuration.txt index 4e9bec12..a58a9e9d 100644 --- a/forge-1.14.4/src/main/resources/configuration.txt +++ b/forge-1.14.4/src/main/resources/configuration.txt @@ -478,7 +478,10 @@ soft-ref-cache: true # Published public URL for Dynmap server (allows users to use 'dynmap url' command to get public URL usable to access server # If not set, 'dynmap url' will not return anything. URL should be fully qualified (e.g. https://mc.westeroscraft.com/) #publicURL: http://my.greatserver.com/dynmap - + +# Send this message if the player does not have permission to use the command +noPermissionMsg: "You don't have permission to use this command!" + # Set to true to enable verbose startup messages - can help with debugging map configuration problems # Set to false for a much quieter startup log verbose: false diff --git a/forge-1.15.2/src/main/resources/configuration.txt b/forge-1.15.2/src/main/resources/configuration.txt index 4e9bec12..a58a9e9d 100644 --- a/forge-1.15.2/src/main/resources/configuration.txt +++ b/forge-1.15.2/src/main/resources/configuration.txt @@ -478,7 +478,10 @@ soft-ref-cache: true # Published public URL for Dynmap server (allows users to use 'dynmap url' command to get public URL usable to access server # If not set, 'dynmap url' will not return anything. URL should be fully qualified (e.g. https://mc.westeroscraft.com/) #publicURL: http://my.greatserver.com/dynmap - + +# Send this message if the player does not have permission to use the command +noPermissionMsg: "You don't have permission to use this command!" + # Set to true to enable verbose startup messages - can help with debugging map configuration problems # Set to false for a much quieter startup log verbose: false diff --git a/forge-1.16.5/src/main/resources/configuration.txt b/forge-1.16.5/src/main/resources/configuration.txt index 748a4f77..161202ed 100644 --- a/forge-1.16.5/src/main/resources/configuration.txt +++ b/forge-1.16.5/src/main/resources/configuration.txt @@ -478,7 +478,10 @@ soft-ref-cache: true # Published public URL for Dynmap server (allows users to use 'dynmap url' command to get public URL usable to access server # If not set, 'dynmap url' will not return anything. URL should be fully qualified (e.g. https://mc.westeroscraft.com/) #publicURL: http://my.greatserver.com/dynmap - + +# Send this message if the player does not have permission to use the command +noPermissionMsg: "You don't have permission to use this command!" + # Set to true to enable verbose startup messages - can help with debugging map configuration problems # Set to false for a much quieter startup log verbose: false diff --git a/forge-1.17.1/src/main/resources/configuration.txt b/forge-1.17.1/src/main/resources/configuration.txt index a41e9950..6931e0c1 100644 --- a/forge-1.17.1/src/main/resources/configuration.txt +++ b/forge-1.17.1/src/main/resources/configuration.txt @@ -478,7 +478,10 @@ soft-ref-cache: true # Published public URL for Dynmap server (allows users to use 'dynmap url' command to get public URL usable to access server # If not set, 'dynmap url' will not return anything. URL should be fully qualified (e.g. https://mc.westeroscraft.com/) #publicURL: http://my.greatserver.com/dynmap - + +# Send this message if the player does not have permission to use the command +noPermissionMsg: "You don't have permission to use this command!" + # Set to true to enable verbose startup messages - can help with debugging map configuration problems # Set to false for a much quieter startup log verbose: false diff --git a/forge-1.18.2/src/main/resources/configuration.txt b/forge-1.18.2/src/main/resources/configuration.txt index 748a4f77..161202ed 100644 --- a/forge-1.18.2/src/main/resources/configuration.txt +++ b/forge-1.18.2/src/main/resources/configuration.txt @@ -478,7 +478,10 @@ soft-ref-cache: true # Published public URL for Dynmap server (allows users to use 'dynmap url' command to get public URL usable to access server # If not set, 'dynmap url' will not return anything. URL should be fully qualified (e.g. https://mc.westeroscraft.com/) #publicURL: http://my.greatserver.com/dynmap - + +# Send this message if the player does not have permission to use the command +noPermissionMsg: "You don't have permission to use this command!" + # Set to true to enable verbose startup messages - can help with debugging map configuration problems # Set to false for a much quieter startup log verbose: false diff --git a/forge-1.18/src/main/resources/configuration.txt b/forge-1.18/src/main/resources/configuration.txt index 748a4f77..161202ed 100644 --- a/forge-1.18/src/main/resources/configuration.txt +++ b/forge-1.18/src/main/resources/configuration.txt @@ -478,7 +478,10 @@ soft-ref-cache: true # Published public URL for Dynmap server (allows users to use 'dynmap url' command to get public URL usable to access server # If not set, 'dynmap url' will not return anything. URL should be fully qualified (e.g. https://mc.westeroscraft.com/) #publicURL: http://my.greatserver.com/dynmap - + +# Send this message if the player does not have permission to use the command +noPermissionMsg: "You don't have permission to use this command!" + # Set to true to enable verbose startup messages - can help with debugging map configuration problems # Set to false for a much quieter startup log verbose: false diff --git a/spigot/src/main/resources/configuration.txt b/spigot/src/main/resources/configuration.txt index 87b593fd..f48f19e2 100644 --- a/spigot/src/main/resources/configuration.txt +++ b/spigot/src/main/resources/configuration.txt @@ -505,6 +505,9 @@ soft-ref-cache: true # If not set, 'dynmap url' will not return anything. URL should be fully qualified (e.g. https://mc.westeroscraft.com/) #publicURL: http://my.greatserver.com/dynmap +# Send this message if the player does not have permission to use the command +noPermissionMsg: "You don't have permission to use this command!" + # Set to true to enable verbose startup messages - can help with debugging map configuration problems # Set to false for a much quieter startup log verbose: false From 536b96a5f946af9ff26ef7c85aa45d0a0c59b3f3 Mon Sep 17 00:00:00 2001 From: Marijn Doeve Date: Mon, 30 May 2022 21:27:42 +0200 Subject: [PATCH 17/27] Set Initial schema version to 4 --- .../org/dynmap/storage/postgresql/PostgreSQLMapStorage.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DynmapCore/src/main/java/org/dynmap/storage/postgresql/PostgreSQLMapStorage.java b/DynmapCore/src/main/java/org/dynmap/storage/postgresql/PostgreSQLMapStorage.java index 361e445a..533bd1e9 100644 --- a/DynmapCore/src/main/java/org/dynmap/storage/postgresql/PostgreSQLMapStorage.java +++ b/DynmapCore/src/main/java/org/dynmap/storage/postgresql/PostgreSQLMapStorage.java @@ -468,7 +468,7 @@ public class PostgreSQLMapStorage extends MapStorage { doUpdate(c, "CREATE TABLE " + tableStandaloneFiles + " (FileName VARCHAR(128) NOT NULL, ServerID BIGINT NOT NULL DEFAULT 0, Content BYTEA, PRIMARY KEY (FileName, ServerID))"); doUpdate(c, "CREATE INDEX " + tableMaps + "_idx ON " + tableMaps + "(WorldID, MapID, Variant, ServerID)"); doUpdate(c, "CREATE TABLE " + tableSchemaVersion + " (level INT PRIMARY KEY NOT NULL)"); - doUpdate(c, "INSERT INTO " + tableSchemaVersion + " (level) VALUES (3)"); + doUpdate(c, "INSERT INTO " + tableSchemaVersion + " (level) VALUES (4)"); version = 4; // initialzed to current schema } catch (SQLException x) { logSQLException("Error creating tables", x); From 0592bc9f049ab653df33d136071feb97a476333e Mon Sep 17 00:00:00 2001 From: Mike Primm Date: Sun, 5 Jun 2022 17:35:50 -0500 Subject: [PATCH 18/27] Update Gson reference to current spigot level (bogus security flag) --- bukkit-helper/build.gradle | 2 +- spigot/build.gradle | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bukkit-helper/build.gradle b/bukkit-helper/build.gradle index b8b14737..83ece802 100644 --- a/bukkit-helper/build.gradle +++ b/bukkit-helper/build.gradle @@ -12,5 +12,5 @@ dependencies { implementation project(':dynmap-api') implementation project(path: ':DynmapCore', configuration: 'shadow') implementation group: 'org.bukkit', name: 'bukkit', version:'1.7.10-R0.1-SNAPSHOT' - implementation group: 'com.google.code.gson', name: 'gson', version:'2.8.2' + implementation group: 'com.google.code.gson', name: 'gson', version:'2.8.9' } diff --git a/spigot/build.gradle b/spigot/build.gradle index 4f60145e..8f647d09 100644 --- a/spigot/build.gradle +++ b/spigot/build.gradle @@ -31,7 +31,7 @@ dependencies { implementation group: 'org.anjocaido', name: 'EssentialsGroupManager', version: '2.10.1' implementation group: 'org.bstats', name: 'bstats-bukkit', version: '2.2.1' implementation group: 'com.googlecode.json-simple', name: 'json-simple', version: '1.1.1' - implementation group: 'com.google.code.gson', name: 'gson', version: '2.8.2' + implementation group: 'com.google.code.gson', name: 'gson', version: '2.8.9' implementation project(':bukkit-helper') implementation(project(':bukkit-helper-113-2')) { transitive = false From f8a81ce0ac0aa1e2d1bfa52027783b279b46e6c7 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin Date: Mon, 6 Jun 2022 09:51:08 +0300 Subject: [PATCH 19/27] feat: URI-encode markers loading world name --- DynmapCore/src/main/resources/extracted/web/js/markers.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DynmapCore/src/main/resources/extracted/web/js/markers.js b/DynmapCore/src/main/resources/extracted/web/js/markers.js index 33a7e1dc..42742f1a 100644 --- a/DynmapCore/src/main/resources/extracted/web/js/markers.js +++ b/DynmapCore/src/main/resources/extracted/web/js/markers.js @@ -27,7 +27,7 @@ componentconstructors['markers'] = function(dynmap, configuration) { function loadmarkers(world) { removeAllMarkers(); - var url = concatURL(dynmap.options.url.markers, '_markers_/marker_'+world+'.json'); + var url = concatURL(dynmap.options.url.markers, '_markers_/marker_' + encodeURIComponent(world) + '.json'); $.getJSON(url, function(data) { var ts = data.timestamp; From 9c9c93493ec3fff402ecebe1b069108458be92bc Mon Sep 17 00:00:00 2001 From: Mike Primm Date: Tue, 7 Jun 2022 12:28:16 -0500 Subject: [PATCH 20/27] Initial spigot/paper 1.19 port --- bukkit-helper-119/.gitignore | 1 + bukkit-helper-119/bin/.gitignore | 1 + bukkit-helper-119/build.gradle | 15 + .../helper/v119/AsyncChunkProvider119.java | 60 +++ .../v119/BukkitVersionHelperSpigot119.java | 456 ++++++++++++++++++ .../bukkit/helper/v119/MapChunkCache119.java | 103 ++++ .../org/dynmap/bukkit/helper/v119/NBT.java | 126 +++++ .../.settings/org.eclipse.jdt.core.prefs | 2 +- settings.gradle | 2 + spigot/build.gradle | 4 + .../main/java/org/dynmap/bukkit/Helper.java | 4 + 11 files changed, 773 insertions(+), 1 deletion(-) create mode 100644 bukkit-helper-119/.gitignore create mode 100644 bukkit-helper-119/bin/.gitignore create mode 100644 bukkit-helper-119/build.gradle create mode 100644 bukkit-helper-119/src/main/java/org/dynmap/bukkit/helper/v119/AsyncChunkProvider119.java create mode 100644 bukkit-helper-119/src/main/java/org/dynmap/bukkit/helper/v119/BukkitVersionHelperSpigot119.java create mode 100644 bukkit-helper-119/src/main/java/org/dynmap/bukkit/helper/v119/MapChunkCache119.java create mode 100644 bukkit-helper-119/src/main/java/org/dynmap/bukkit/helper/v119/NBT.java diff --git a/bukkit-helper-119/.gitignore b/bukkit-helper-119/.gitignore new file mode 100644 index 00000000..84c048a7 --- /dev/null +++ b/bukkit-helper-119/.gitignore @@ -0,0 +1 @@ +/build/ diff --git a/bukkit-helper-119/bin/.gitignore b/bukkit-helper-119/bin/.gitignore new file mode 100644 index 00000000..ddf9c656 --- /dev/null +++ b/bukkit-helper-119/bin/.gitignore @@ -0,0 +1 @@ +/main/ diff --git a/bukkit-helper-119/build.gradle b/bukkit-helper-119/build.gradle new file mode 100644 index 00000000..74aa29e4 --- /dev/null +++ b/bukkit-helper-119/build.gradle @@ -0,0 +1,15 @@ +eclipse { + project { + name = "Dynmap(Spigot-1.19)" + } +} + +description = 'bukkit-helper-1.19' + +dependencies { + implementation project(':bukkit-helper') + implementation project(':dynmap-api') + implementation project(path: ':DynmapCore', configuration: 'shadow') + implementation group: 'org.spigotmc', name: 'spigot-api', version:'1.19-R0.1-SNAPSHOT' + implementation group: 'org.spigotmc', name: 'spigot', version:'1.19-R0.1-SNAPSHOT' +} diff --git a/bukkit-helper-119/src/main/java/org/dynmap/bukkit/helper/v119/AsyncChunkProvider119.java b/bukkit-helper-119/src/main/java/org/dynmap/bukkit/helper/v119/AsyncChunkProvider119.java new file mode 100644 index 00000000..7438575c --- /dev/null +++ b/bukkit-helper-119/src/main/java/org/dynmap/bukkit/helper/v119/AsyncChunkProvider119.java @@ -0,0 +1,60 @@ +package org.dynmap.bukkit.helper.v119; + +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.server.level.WorldServer; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.Objects; +import java.util.concurrent.CompletableFuture; +import java.util.function.Consumer; +import java.util.function.Predicate; + +/** + * The provider used to work with paper libs + * Because paper libs need java 17 we can't interact with them directly + */ +public class AsyncChunkProvider119 { + private final Thread ioThread; + private final Method getChunk; + private final Predicate ifFailed; + AsyncChunkProvider119 () { + try { + Predicate ifFailed1 = null; + Method getChunk1 = null; + Thread ioThread1 = null; + try { + Class threadClass = Class.forName("com.destroystokyo.paper.io.PaperFileIOThread"); + Class[] classes = threadClass.getClasses(); + Class holder = Arrays.stream(classes).filter(aClass -> aClass.getSimpleName().equals("Holder")).findAny().orElseThrow(RuntimeException::new); + ioThread1 = (Thread) holder.getField("INSTANCE").get(null); + getChunk1 = threadClass.getMethod("loadChunkDataAsync", WorldServer.class, int.class, int.class, int.class, Consumer.class, boolean.class, boolean.class, boolean.class); + NBTTagCompound failure = (NBTTagCompound) threadClass.getField("FAILURE_VALUE").get(null); + ifFailed1 = nbtTagCompound -> nbtTagCompound == failure; + } catch (ClassNotFoundException | NoSuchFieldException | IllegalAccessException | NoSuchMethodException e) { + e.printStackTrace(); + } + ifFailed = Objects.requireNonNull(ifFailed1); + getChunk = Objects.requireNonNull(getChunk1); + ioThread = Objects.requireNonNull(ioThread1); + } catch (Throwable e) { + e.printStackTrace(); + throw new RuntimeException(e); + } + } + public CompletableFuture getChunk(WorldServer world, int x, int y) throws InvocationTargetException, IllegalAccessException { + CompletableFuture future = new CompletableFuture<>(); + getChunk.invoke(ioThread,world,x,y,5,(Consumer) future::complete, false, true, true); + return future.thenApply((resultFuture) -> { + if (resultFuture == null) return null; + try { + NBTTagCompound compound = (NBTTagCompound) resultFuture.getClass().getField("chunkData").get(resultFuture); + return ifFailed.test(compound) ? null : compound; + } catch (IllegalAccessException | NoSuchFieldException e) { + e.printStackTrace(); + } + return null; + }); + } +} diff --git a/bukkit-helper-119/src/main/java/org/dynmap/bukkit/helper/v119/BukkitVersionHelperSpigot119.java b/bukkit-helper-119/src/main/java/org/dynmap/bukkit/helper/v119/BukkitVersionHelperSpigot119.java new file mode 100644 index 00000000..d4d5daf9 --- /dev/null +++ b/bukkit-helper-119/src/main/java/org/dynmap/bukkit/helper/v119/BukkitVersionHelperSpigot119.java @@ -0,0 +1,456 @@ +package org.dynmap.bukkit.helper.v119; + +import org.bukkit.*; +import org.bukkit.craftbukkit.v1_19_R1.CraftChunk; +import org.bukkit.craftbukkit.v1_19_R1.CraftWorld; +import org.bukkit.craftbukkit.v1_19_R1.entity.CraftPlayer; +import org.bukkit.entity.Player; +import org.dynmap.DynmapChunk; +import org.dynmap.Log; +import org.dynmap.bukkit.helper.BukkitMaterial; +import org.dynmap.bukkit.helper.BukkitVersionHelper; +import org.dynmap.bukkit.helper.BukkitWorld; +import org.dynmap.bukkit.helper.BukkitVersionHelperGeneric.TexturesPayload; +import org.dynmap.renderer.DynmapBlockState; +import org.dynmap.utils.MapChunkCache; +import org.dynmap.utils.Polygon; + +import com.google.common.collect.Iterables; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonParseException; +import com.mojang.authlib.GameProfile; +import com.mojang.authlib.properties.Property; +import com.mojang.authlib.properties.PropertyMap; + +import net.minecraft.core.RegistryBlockID; +import net.minecraft.core.RegistryBlocks; +import net.minecraft.core.BlockPosition; +import net.minecraft.core.IRegistry; +import net.minecraft.nbt.NBTTagByteArray; +import net.minecraft.nbt.NBTTagByte; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagDouble; +import net.minecraft.nbt.NBTTagFloat; +import net.minecraft.nbt.NBTTagIntArray; +import net.minecraft.nbt.NBTTagInt; +import net.minecraft.nbt.NBTTagLong; +import net.minecraft.nbt.NBTTagShort; +import net.minecraft.nbt.NBTTagString; +import net.minecraft.resources.MinecraftKey; +import net.minecraft.nbt.NBTBase; +import net.minecraft.server.MinecraftServer; +import net.minecraft.world.level.BlockAccessAir; +import net.minecraft.world.level.biome.BiomeBase; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.BlockFluids; +import net.minecraft.world.level.block.entity.TileEntity; +import net.minecraft.world.level.block.state.IBlockData; + +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Base64; +import java.util.Collection; +import java.util.HashMap; +import java.util.IdentityHashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + + +/** + * Helper for isolation of bukkit version specific issues + */ +public class BukkitVersionHelperSpigot119 extends BukkitVersionHelper { + private final boolean unsafeAsync; + + public BukkitVersionHelperSpigot119() { + boolean unsafeAsync1; + try { + Class.forName("com.destroystokyo.paper.io.PaperFileIOThread"); + unsafeAsync1 = false; + } catch (ClassNotFoundException e) { + unsafeAsync1 = true; + } + this.unsafeAsync = unsafeAsync1; + } + + @Override + public boolean isUnsafeAsync() { + return unsafeAsync; + } + + /** + * Get block short name list + */ + @Override + public String[] getBlockNames() { + RegistryBlockID bsids = Block.o; + Block baseb = null; + Iterator iter = bsids.iterator(); + ArrayList names = new ArrayList(); + while (iter.hasNext()) { + IBlockData bs = iter.next(); + Block b = bs.b(); + // If this is new block vs last, it's the base block state + if (b != baseb) { + baseb = b; + continue; + } + MinecraftKey id = RegistryBlocks.V.b(b); + String bn = id.toString(); + if (bn != null) { + names.add(bn); + Log.info("block=" + bn); + } + } + return names.toArray(new String[0]); + } + + private static IRegistry reg = null; + + private static IRegistry getBiomeReg() { + if (reg == null) { + reg = MinecraftServer.getServer().aX().d(IRegistry.aR); + } + return reg; + } + + private Object[] biomelist; + /** + * Get list of defined biomebase objects + */ + @Override + public Object[] getBiomeBaseList() { + if (biomelist == null) { + biomelist = new BiomeBase[256]; + Iterator iter = getBiomeReg().iterator(); + while (iter.hasNext()) { + BiomeBase b = iter.next(); + int bidx = getBiomeReg().a(b); + if (bidx >= biomelist.length) { + biomelist = Arrays.copyOf(biomelist, bidx + biomelist.length); + } + biomelist[bidx] = b; + } + } + return biomelist; + } + + /** Get ID from biomebase */ + @Override + public int getBiomeBaseID(Object bb) { + return getBiomeReg().a((BiomeBase)bb); + } + + public static IdentityHashMap dataToState; + + /** + * Initialize block states (org.dynmap.blockstate.DynmapBlockState) + */ + @Override + public void initializeBlockStates() { + dataToState = new IdentityHashMap(); + HashMap lastBlockState = new HashMap(); + RegistryBlockID bsids = Block.o; + Block baseb = null; + Iterator iter = bsids.iterator(); + ArrayList names = new ArrayList(); + + // Loop through block data states + DynmapBlockState.Builder bld = new DynmapBlockState.Builder(); + while (iter.hasNext()) { + IBlockData bd = iter.next(); + Block b = bd.b(); + MinecraftKey id = RegistryBlocks.V.b(b); + String bname = id.toString(); + DynmapBlockState lastbs = lastBlockState.get(bname); // See if we have seen this one + int idx = 0; + if (lastbs != null) { // Yes + idx = lastbs.getStateCount(); // Get number of states so far, since this is next + } + // Build state name + String sb = ""; + String fname = bd.toString(); + int off1 = fname.indexOf('['); + if (off1 >= 0) { + int off2 = fname.indexOf(']'); + sb = fname.substring(off1+1, off2); + } + net.minecraft.world.level.material.Material mat = bd.d(); + + int lightAtten = b.g(bd, BlockAccessAir.a, BlockPosition.b); // getLightBlock + //Log.info("statename=" + bname + "[" + sb + "], lightAtten=" + lightAtten); + // Fill in base attributes + bld.setBaseState(lastbs).setStateIndex(idx).setBlockName(bname).setStateName(sb).setMaterial(mat.toString()).setAttenuatesLight(lightAtten); + if (mat.b()) { bld.setSolid(); } + if (mat == net.minecraft.world.level.material.Material.a) { bld.setAir(); } + if (mat == net.minecraft.world.level.material.Material.z) { bld.setLog(); } + if (mat == net.minecraft.world.level.material.Material.F) { bld.setLeaves(); } + if ((!bd.p().c()) && ((bd.b() instanceof BlockFluids) == false)) { // Test if fluid type for block is not empty + bld.setWaterlogged(); + } + DynmapBlockState dbs = bld.build(); // Build state + + dataToState.put(bd, dbs); + lastBlockState.put(bname, (lastbs == null) ? dbs : lastbs); + Log.verboseinfo("blk=" + bname + ", idx=" + idx + ", state=" + sb + ", waterlogged=" + dbs.isWaterlogged()); + } + } + /** + * Create chunk cache for given chunks of given world + * @param dw - world + * @param chunks - chunk list + * @return cache + */ + @Override + public MapChunkCache getChunkCache(BukkitWorld dw, List chunks) { + MapChunkCache119 c = new MapChunkCache119(gencache); + c.setChunks(dw, chunks); + return c; + } + + /** + * Get biome base water multiplier + */ + @Override + public int getBiomeBaseWaterMult(Object bb) { + BiomeBase biome = (BiomeBase) bb; + return biome.k(); // waterColor + } + + /** Get temperature from biomebase */ + @Override + public float getBiomeBaseTemperature(Object bb) { + return ((BiomeBase)bb).i(); + } + + /** Get humidity from biomebase */ + @Override + public float getBiomeBaseHumidity(Object bb) { + return ((BiomeBase)bb).h(); + } + + @Override + public Polygon getWorldBorder(World world) { + Polygon p = null; + WorldBorder wb = world.getWorldBorder(); + if (wb != null) { + Location c = wb.getCenter(); + double size = wb.getSize(); + if ((size > 1) && (size < 1E7)) { + size = size / 2; + p = new Polygon(); + p.addVertex(c.getX()-size, c.getZ()-size); + p.addVertex(c.getX()+size, c.getZ()-size); + p.addVertex(c.getX()+size, c.getZ()+size); + p.addVertex(c.getX()-size, c.getZ()+size); + } + } + return p; + } + // Send title/subtitle to user + public void sendTitleText(Player p, String title, String subtitle, int fadeInTicks, int stayTicks, int fadeOutTIcks) { + if (p != null) { + p.sendTitle(title, subtitle, fadeInTicks, stayTicks, fadeOutTIcks); + } + } + + /** + * Get material map by block ID + */ + @Override + public BukkitMaterial[] getMaterialList() { + return new BukkitMaterial[4096]; // Not used + } + + @Override + public void unloadChunkNoSave(World w, org.bukkit.Chunk c, int cx, int cz) { + Log.severe("unloadChunkNoSave not implemented"); + } + + private String[] biomenames; + @Override + public String[] getBiomeNames() { + if (biomenames == null) { + biomenames = new String[256]; + Iterator iter = getBiomeReg().iterator(); + while (iter.hasNext()) { + BiomeBase b = iter.next(); + int bidx = getBiomeReg().a(b); + if (bidx >= biomenames.length) { + biomenames = Arrays.copyOf(biomenames, bidx + biomenames.length); + } + biomenames[bidx] = b.toString(); + } + } + return biomenames; + } + + @Override + public String getStateStringByCombinedId(int blkid, int meta) { + Log.severe("getStateStringByCombinedId not implemented"); + return null; + } + @Override + /** Get ID string from biomebase */ + public String getBiomeBaseIDString(Object bb) { + return getBiomeReg().b((BiomeBase)bb).a(); + } + @Override + public String getBiomeBaseResourceLocsation(Object bb) { + return getBiomeReg().b((BiomeBase)bb).toString(); + } + + @Override + public Object getUnloadQueue(World world) { + Log.warning("getUnloadQueue not implemented yet"); + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean isInUnloadQueue(Object unloadqueue, int x, int z) { + Log.warning("isInUnloadQueue not implemented yet"); + // TODO Auto-generated method stub + return false; + } + + @Override + public Object[] getBiomeBaseFromSnapshot(ChunkSnapshot css) { + Log.warning("getBiomeBaseFromSnapshot not implemented yet"); + // TODO Auto-generated method stub + return new Object[256]; + } + + @Override + public long getInhabitedTicks(Chunk c) { + return ((CraftChunk)c).getHandle().u(); + } + + @Override + public Map getTileEntitiesForChunk(Chunk c) { + return ((CraftChunk)c).getHandle().i; + } + + @Override + public int getTileEntityX(Object te) { + TileEntity tileent = (TileEntity) te; + return tileent.p().u(); + } + + @Override + public int getTileEntityY(Object te) { + TileEntity tileent = (TileEntity) te; + return tileent.p().v(); + } + + @Override + public int getTileEntityZ(Object te) { + TileEntity tileent = (TileEntity) te; + return tileent.p().w(); + } + + @Override + public Object readTileEntityNBT(Object te) { + TileEntity tileent = (TileEntity) te; + NBTTagCompound nbt = tileent.n(); + return nbt; + } + + @Override + public Object getFieldValue(Object nbt, String field) { + NBTTagCompound rec = (NBTTagCompound) nbt; + NBTBase val = rec.c(field); + if(val == null) return null; + if(val instanceof NBTTagByte) { + return ((NBTTagByte)val).h(); + } + else if(val instanceof NBTTagShort) { + return ((NBTTagShort)val).g(); + } + else if(val instanceof NBTTagInt) { + return ((NBTTagInt)val).f(); + } + else if(val instanceof NBTTagLong) { + return ((NBTTagLong)val).e(); + } + else if(val instanceof NBTTagFloat) { + return ((NBTTagFloat)val).j(); + } + else if(val instanceof NBTTagDouble) { + return ((NBTTagDouble)val).i(); + } + else if(val instanceof NBTTagByteArray) { + return ((NBTTagByteArray)val).d(); + } + else if(val instanceof NBTTagString) { + return ((NBTTagString)val).e_(); + } + else if(val instanceof NBTTagIntArray) { + return ((NBTTagIntArray)val).f(); + } + return null; + } + + @Override + public Player[] getOnlinePlayers() { + Collection p = Bukkit.getServer().getOnlinePlayers(); + return p.toArray(new Player[0]); + } + + @Override + public double getHealth(Player p) { + return p.getHealth(); + } + + private static final Gson gson = new GsonBuilder().create(); + + /** + * Get skin URL for player + * @param player + */ + @Override + public String getSkinURL(Player player) { + String url = null; + CraftPlayer cp = (CraftPlayer)player; + GameProfile profile = cp.getProfile(); + if (profile != null) { + PropertyMap pm = profile.getProperties(); + if (pm != null) { + Collection txt = pm.get("textures"); + Property textureProperty = Iterables.getFirst(pm.get("textures"), null); + if (textureProperty != null) { + String val = textureProperty.getValue(); + if (val != null) { + TexturesPayload result = null; + try { + String json = new String(Base64.getDecoder().decode(val), StandardCharsets.UTF_8); + result = gson.fromJson(json, TexturesPayload.class); + } catch (JsonParseException e) { + } catch (IllegalArgumentException x) { + Log.warning("Malformed response from skin URL check: " + val); + } + if ((result != null) && (result.textures != null) && (result.textures.containsKey("SKIN"))) { + url = result.textures.get("SKIN").url; + } + } + } + } + } + return url; + } + // Get minY for world + @Override + public int getWorldMinY(World w) { + CraftWorld cw = (CraftWorld) w; + return cw.getMinHeight(); + } + @Override + public boolean useGenericCache() { + return true; + } + +} diff --git a/bukkit-helper-119/src/main/java/org/dynmap/bukkit/helper/v119/MapChunkCache119.java b/bukkit-helper-119/src/main/java/org/dynmap/bukkit/helper/v119/MapChunkCache119.java new file mode 100644 index 00000000..4743e94f --- /dev/null +++ b/bukkit-helper-119/src/main/java/org/dynmap/bukkit/helper/v119/MapChunkCache119.java @@ -0,0 +1,103 @@ +package org.dynmap.bukkit.helper.v119; + +import org.bukkit.Bukkit; +import org.bukkit.World; +import org.bukkit.craftbukkit.v1_19_R1.CraftServer; +import org.bukkit.craftbukkit.v1_19_R1.CraftWorld; +import org.dynmap.DynmapChunk; +import org.dynmap.bukkit.helper.BukkitVersionHelper; +import org.dynmap.bukkit.helper.BukkitWorld; +import org.dynmap.common.chunk.GenericChunk; +import org.dynmap.common.chunk.GenericChunkCache; +import org.dynmap.common.chunk.GenericMapChunkCache; + +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.world.level.ChunkCoordIntPair; +import net.minecraft.world.level.chunk.storage.ChunkRegionLoader; +import net.minecraft.world.level.chunk.Chunk; + +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.util.List; +import java.util.NoSuchElementException; +import java.util.concurrent.CancellationException; +import java.util.concurrent.CompletableFuture; +import java.util.function.Supplier; + +/** + * Container for managing chunks - dependent upon using chunk snapshots, since rendering is off server thread + */ +public class MapChunkCache119 extends GenericMapChunkCache { + private static final AsyncChunkProvider119 provider = BukkitVersionHelper.helper.isUnsafeAsync() ? null : new AsyncChunkProvider119(); + private World w; + /** + * Construct empty cache + */ + public MapChunkCache119(GenericChunkCache cc) { + super(cc); + } + + // Load generic chunk from existing and already loaded chunk + protected GenericChunk getLoadedChunk(DynmapChunk chunk) { + return getLoadedChunk(chunk, false).get(); + } + @Override + protected Supplier getLoadedChunkAsync(DynmapChunk ch) { + return getLoadedChunk(ch, true); + } + + @Override + protected Supplier loadChunkAsync(DynmapChunk chunk){ + try { + CompletableFuture nbt = provider.getChunk(((CraftWorld) w).getHandle(), chunk.x, chunk.z); + return () -> { + NBTTagCompound compound = nbt.join(); + return compound == null ? null : parseChunkFromNBT(new NBT.NBTCompound(compound)); + }; + } catch (InvocationTargetException | IllegalAccessException ignored) { + return () -> null; + } + } + + private Supplier getLoadedChunk(DynmapChunk chunk, boolean async) { + CraftWorld cw = (CraftWorld) w; + if (!cw.isChunkLoaded(chunk.x, chunk.z)) return () -> null; + Chunk c = cw.getHandle().getChunkIfLoaded(chunk.x, chunk.z); //already safe async on vanilla + if ((c == null) || c.o) return () -> null; // c.loaded + if (async) { //the data of the chunk may change while we write, better to write it sync + CompletableFuture nbt = CompletableFuture.supplyAsync(() -> ChunkRegionLoader.a(cw.getHandle(), c), ((CraftServer) Bukkit.getServer()).getServer()); + return () -> { + NBTTagCompound compound = nbt.join(); + return compound == null ? null : parseChunkFromNBT(new NBT.NBTCompound(compound)); + }; + } else { + NBTTagCompound nbt = ChunkRegionLoader.a(cw.getHandle(), c); + GenericChunk genericChunk; + if (nbt != null) genericChunk = parseChunkFromNBT(new NBT.NBTCompound(nbt)); + else genericChunk = null; + return () -> genericChunk; + } + + } + // Load generic chunk from unloaded chunk + protected GenericChunk loadChunk(DynmapChunk chunk) { + CraftWorld cw = (CraftWorld) w; + NBTTagCompound nbt = null; + ChunkCoordIntPair cc = new ChunkCoordIntPair(chunk.x, chunk.z); + GenericChunk gc = null; + try { // BUGBUG - convert this all to asyn properly, since now native async + nbt = cw.getHandle().k().a.f(cc).join().get(); // playerChunkMap + } catch (CancellationException cx) { + } catch (NoSuchElementException snex) { + } + if (nbt != null) { + gc = parseChunkFromNBT(new NBT.NBTCompound(nbt)); + } + return gc; + } + + public void setChunks(BukkitWorld dw, List chunks) { + this.w = dw.getWorld(); + super.setChunks(dw, chunks); + } +} diff --git a/bukkit-helper-119/src/main/java/org/dynmap/bukkit/helper/v119/NBT.java b/bukkit-helper-119/src/main/java/org/dynmap/bukkit/helper/v119/NBT.java new file mode 100644 index 00000000..14503faf --- /dev/null +++ b/bukkit-helper-119/src/main/java/org/dynmap/bukkit/helper/v119/NBT.java @@ -0,0 +1,126 @@ +package org.dynmap.bukkit.helper.v119; + +import org.dynmap.common.chunk.GenericBitStorage; +import org.dynmap.common.chunk.GenericNBTCompound; +import org.dynmap.common.chunk.GenericNBTList; + +import java.util.Set; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraft.util.SimpleBitStorage; + +public class NBT { + + public static class NBTCompound implements GenericNBTCompound { + private final NBTTagCompound obj; + public NBTCompound(NBTTagCompound t) { + this.obj = t; + } + @Override + public Set getAllKeys() { + return obj.d(); + } + @Override + public boolean contains(String s) { + return obj.e(s); + } + @Override + public boolean contains(String s, int i) { + return obj.b(s, i); + } + @Override + public byte getByte(String s) { + return obj.f(s); + } + @Override + public short getShort(String s) { + return obj.g(s); + } + @Override + public int getInt(String s) { + return obj.h(s); + } + @Override + public long getLong(String s) { + return obj.i(s); + } + @Override + public float getFloat(String s) { + return obj.j(s); + } + @Override + public double getDouble(String s) { + return obj.k(s); + } + @Override + public String getString(String s) { + return obj.l(s); + } + @Override + public byte[] getByteArray(String s) { + return obj.m(s); + } + @Override + public int[] getIntArray(String s) { + return obj.n(s); + } + @Override + public long[] getLongArray(String s) { + return obj.o(s); + } + @Override + public GenericNBTCompound getCompound(String s) { + return new NBTCompound(obj.p(s)); + } + @Override + public GenericNBTList getList(String s, int i) { + return new NBTList(obj.c(s, i)); + } + @Override + public boolean getBoolean(String s) { + return obj.q(s); + } + @Override + public String getAsString(String s) { + return obj.c(s).e_(); + } + @Override + public GenericBitStorage makeBitStorage(int bits, int count, long[] data) { + return new OurBitStorage(bits, count, data); + } + public String toString() { + return obj.toString(); + } + } + public static class NBTList implements GenericNBTList { + private final NBTTagList obj; + public NBTList(NBTTagList t) { + obj = t; + } + @Override + public int size() { + return obj.size(); + } + @Override + public String getString(int idx) { + return obj.j(idx); + } + @Override + public GenericNBTCompound getCompound(int idx) { + return new NBTCompound(obj.a(idx)); + } + public String toString() { + return obj.toString(); + } + } + public static class OurBitStorage implements GenericBitStorage { + private final SimpleBitStorage bs; + public OurBitStorage(int bits, int count, long[] data) { + bs = new SimpleBitStorage(bits, count, data); + } + @Override + public int get(int idx) { + return bs.a(idx); + } + } +} diff --git a/bukkit-helper/.settings/org.eclipse.jdt.core.prefs b/bukkit-helper/.settings/org.eclipse.jdt.core.prefs index 34340ad4..68479f99 100644 --- a/bukkit-helper/.settings/org.eclipse.jdt.core.prefs +++ b/bukkit-helper/.settings/org.eclipse.jdt.core.prefs @@ -1,5 +1,5 @@ # -#Tue Mar 29 22:17:34 CDT 2022 +#Tue Jun 07 11:38:11 CDT 2022 org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning org.eclipse.jdt.core.compiler.problem.assertIdentifier=error org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 diff --git a/settings.gradle b/settings.gradle index b7e91e37..49c06be4 100644 --- a/settings.gradle +++ b/settings.gradle @@ -19,6 +19,7 @@ include ':bukkit-helper-116-4' include ':bukkit-helper-117' include ':bukkit-helper-118' include ':bukkit-helper-118-2' +include ':bukkit-helper-119' include ':bukkit-helper' include ':dynmap-api' include ':DynmapCore' @@ -47,6 +48,7 @@ project(':bukkit-helper-116-4').projectDir = "$rootDir/bukkit-helper-116-4" as F project(':bukkit-helper-117').projectDir = "$rootDir/bukkit-helper-117" as File project(':bukkit-helper-118').projectDir = "$rootDir/bukkit-helper-118" as File project(':bukkit-helper-118-2').projectDir = "$rootDir/bukkit-helper-118-2" as File +project(':bukkit-helper-119').projectDir = "$rootDir/bukkit-helper-119" as File project(':bukkit-helper').projectDir = "$rootDir/bukkit-helper" as File project(':dynmap-api').projectDir = "$rootDir/dynmap-api" as File project(':DynmapCore').projectDir = "$rootDir/DynmapCore" as File diff --git a/spigot/build.gradle b/spigot/build.gradle index 8f647d09..b84c5169 100644 --- a/spigot/build.gradle +++ b/spigot/build.gradle @@ -63,6 +63,9 @@ dependencies { implementation(project(':bukkit-helper-118-2')) { transitive = false } + implementation(project(':bukkit-helper-119')) { + transitive = false + } } processResources { @@ -96,6 +99,7 @@ shadowJar { include(dependency(':bukkit-helper-117')) include(dependency(':bukkit-helper-118')) include(dependency(':bukkit-helper-118-2')) + include(dependency(':bukkit-helper-119')) } relocate('org.bstats', 'org.dynmap.bstats') destinationDir = file '../target' diff --git a/spigot/src/main/java/org/dynmap/bukkit/Helper.java b/spigot/src/main/java/org/dynmap/bukkit/Helper.java index de807ecb..3856f595 100644 --- a/spigot/src/main/java/org/dynmap/bukkit/Helper.java +++ b/spigot/src/main/java/org/dynmap/bukkit/Helper.java @@ -15,6 +15,7 @@ import org.dynmap.bukkit.helper.v116_4.BukkitVersionHelperSpigot116_4; import org.dynmap.bukkit.helper.v117.BukkitVersionHelperSpigot117; import org.dynmap.bukkit.helper.v118.BukkitVersionHelperSpigot118; import org.dynmap.bukkit.helper.v118_2.BukkitVersionHelperSpigot118_2; +import org.dynmap.bukkit.helper.v119.BukkitVersionHelperSpigot119; public class Helper { @@ -40,6 +41,9 @@ public class Helper { Log.info("Loading Glowstone support"); BukkitVersionHelper.helper = new BukkitVersionHelperGlowstone(); } + else if (v.contains("(MC: 1.19")) { + BukkitVersionHelper.helper = new BukkitVersionHelperSpigot119(); + } else if (v.contains("(MC: 1.18)") || (v.contains("(MC: 1.18.1)"))) { BukkitVersionHelper.helper = new BukkitVersionHelperSpigot118(); } From a39e00ac0fa020ba08da71d29f51c8aa23622e43 Mon Sep 17 00:00:00 2001 From: Kosma Moczek Date: Tue, 7 Jun 2022 23:42:15 +0200 Subject: [PATCH 21/27] fabric-1.19: update to 1.19 release Apply suggestions from code review Co-authored-by: ThalusA <15985204+ThalusA@users.noreply.github.com> --- fabric-1.19/gradle.properties | 6 +++--- fabric-1.19/src/main/resources/dynmap.mixins.json | 2 +- fabric-1.19/src/main/resources/fabric.mod.json | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/fabric-1.19/gradle.properties b/fabric-1.19/gradle.properties index a1ed7988..20c5066a 100644 --- a/fabric-1.19/gradle.properties +++ b/fabric-1.19/gradle.properties @@ -1,4 +1,4 @@ -minecraft_version=1.19-pre3 -yarn_mappings=1.19-pre3+build.4 +minecraft_version=1.19 +yarn_mappings=1.19+build.1 loader_version=0.14.6 -fabric_version=0.53.4+1.19 +fabric_version=0.55.2+1.19 diff --git a/fabric-1.19/src/main/resources/dynmap.mixins.json b/fabric-1.19/src/main/resources/dynmap.mixins.json index c5c9e89b..ea58931e 100644 --- a/fabric-1.19/src/main/resources/dynmap.mixins.json +++ b/fabric-1.19/src/main/resources/dynmap.mixins.json @@ -2,7 +2,7 @@ "required": true, "minVersion": "0.8", "package": "org.dynmap.fabric_1_19.mixin", - "compatibilityLevel": "JAVA_16", + "compatibilityLevel": "JAVA_17", "mixins": [ "BiomeEffectsAccessor", "MinecraftServerMixin", diff --git a/fabric-1.19/src/main/resources/fabric.mod.json b/fabric-1.19/src/main/resources/fabric.mod.json index 31df4672..83e56af5 100644 --- a/fabric-1.19/src/main/resources/fabric.mod.json +++ b/fabric-1.19/src/main/resources/fabric.mod.json @@ -27,7 +27,7 @@ "depends": { "fabricloader": ">=0.14.6", - "fabric": ">=0.53.4", + "fabric": ">=0.55.2", "minecraft": "1.19.x" } } From 9f20e7a17453652fe6b88dd119f66322907f29e3 Mon Sep 17 00:00:00 2001 From: Mike Primm Date: Tue, 7 Jun 2022 19:29:41 -0500 Subject: [PATCH 22/27] Bandaid compile errors in Fabric 1.19 code --- bukkit-helper/.project | 37 ++++++++++--------- .../org/dynmap/fabric_1_19/FabricServer.java | 4 +- .../mixin/ServerPlayNetworkHandlerMixin.java | 5 +-- 3 files changed, 24 insertions(+), 22 deletions(-) diff --git a/bukkit-helper/.project b/bukkit-helper/.project index e86ee638..b372cd57 100644 --- a/bukkit-helper/.project +++ b/bukkit-helper/.project @@ -2,32 +2,35 @@ Dynmap(Spigot-Common) bukkit-helper - + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.buildship.core.gradleprojectbuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + org.eclipse.jdt.core.javanature org.eclipse.m2e.core.maven2Nature org.eclipse.buildship.core.gradleprojectnature - - - org.eclipse.jdt.core.javabuilder - - - - org.eclipse.buildship.core.gradleprojectbuilder - - - - org.eclipse.m2e.core.maven2Builder - - - - 1 + 30 - org.eclipse.core.resources.regexFilterMatcher node_modules|.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__ diff --git a/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/FabricServer.java b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/FabricServer.java index f6a84c41..645dd540 100644 --- a/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/FabricServer.java +++ b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/FabricServer.java @@ -6,7 +6,7 @@ import net.fabricmc.loader.api.ModContainer; import net.minecraft.block.AbstractSignBlock; import net.minecraft.block.Block; import net.minecraft.block.BlockState; -import net.minecraft.network.MessageType; +import net.minecraft.network.message.MessageType; import net.minecraft.server.BannedIpList; import net.minecraft.server.BannedPlayerList; import net.minecraft.server.MinecraftServer; @@ -21,9 +21,9 @@ import net.minecraft.util.registry.Registry; import net.minecraft.world.World; import net.minecraft.world.biome.Biome; import org.dynmap.DynmapChunk; -import org.dynmap.DynmapCommonAPIListener; import org.dynmap.DynmapWorld; import org.dynmap.Log; +import org.dynmap.DynmapCommonAPIListener; import org.dynmap.common.BiomeMap; import org.dynmap.common.DynmapListenerManager; import org.dynmap.common.DynmapPlayer; diff --git a/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/mixin/ServerPlayNetworkHandlerMixin.java b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/mixin/ServerPlayNetworkHandlerMixin.java index 89afc9bc..cabe6a5a 100644 --- a/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/mixin/ServerPlayNetworkHandlerMixin.java +++ b/fabric-1.19/src/main/java/org/dynmap/fabric_1_19/mixin/ServerPlayNetworkHandlerMixin.java @@ -3,8 +3,7 @@ package org.dynmap.fabric_1_19.mixin; import net.minecraft.block.BlockState; import net.minecraft.block.entity.BlockEntity; import net.minecraft.block.entity.SignBlockEntity; -import net.minecraft.network.MessageType; -import net.minecraft.network.encryption.SignedChatMessage; +import net.minecraft.network.message.SignedMessage; import net.minecraft.network.packet.c2s.play.UpdateSignC2SPacket; import net.minecraft.server.filter.FilteredMessage; import net.minecraft.server.filter.TextStream; @@ -40,7 +39,7 @@ public abstract class ServerPlayNetworkHandlerMixin { shift = At.Shift.BEFORE ) ) - public void onGameMessage(FilteredMessage message, CallbackInfo ci) { + public void onGameMessage(FilteredMessage message, CallbackInfo ci) { ServerChatEvents.EVENT.invoker().onChatMessage(player, message.raw().getContent().getString()); } From 9b7c7aa496329d50b76728bd7466b6b54c5166bd Mon Sep 17 00:00:00 2001 From: Mike Primm Date: Tue, 7 Jun 2022 22:04:44 -0500 Subject: [PATCH 23/27] Add initial forge 1.19 --- bukkit-helper/.project | 37 +- .../.settings/org.eclipse.jdt.core.prefs | 2 +- forge-1.19/.gitignore | 1 + forge-1.19/bin/.gitignore | 2 + forge-1.19/build.gradle | 92 + .../org/dynmap/forge_1_19/ClientProxy.java | 6 + .../java/org/dynmap/forge_1_19/DynmapMod.java | 136 ++ .../org/dynmap/forge_1_19/DynmapPlugin.java | 2018 +++++++++++++++++ .../dynmap/forge_1_19/ForgeMapChunkCache.java | 90 + .../org/dynmap/forge_1_19/ForgeWorld.java | 249 ++ .../main/java/org/dynmap/forge_1_19/NBT.java | 126 + .../java/org/dynmap/forge_1_19/Proxy.java | 24 + .../org/dynmap/forge_1_19/VersionCheck.java | 97 + .../permissions/FilePermissions.java | 103 + .../forge_1_19/permissions/OpPermissions.java | 51 + .../permissions/PermissionProvider.java | 15 + .../resources/META-INF/accesstransformer.cfg | 4 + .../src/main/resources/META-INF/mods.toml | 26 + .../src/main/resources/configuration.txt | 496 ++++ forge-1.19/src/main/resources/pack.mcmeta | 6 + .../main/resources/permissions.yml.example | 27 + settings.gradle | 2 + 22 files changed, 3589 insertions(+), 21 deletions(-) create mode 100644 forge-1.19/.gitignore create mode 100644 forge-1.19/bin/.gitignore create mode 100644 forge-1.19/build.gradle create mode 100644 forge-1.19/src/main/java/org/dynmap/forge_1_19/ClientProxy.java create mode 100644 forge-1.19/src/main/java/org/dynmap/forge_1_19/DynmapMod.java create mode 100644 forge-1.19/src/main/java/org/dynmap/forge_1_19/DynmapPlugin.java create mode 100644 forge-1.19/src/main/java/org/dynmap/forge_1_19/ForgeMapChunkCache.java create mode 100644 forge-1.19/src/main/java/org/dynmap/forge_1_19/ForgeWorld.java create mode 100644 forge-1.19/src/main/java/org/dynmap/forge_1_19/NBT.java create mode 100644 forge-1.19/src/main/java/org/dynmap/forge_1_19/Proxy.java create mode 100644 forge-1.19/src/main/java/org/dynmap/forge_1_19/VersionCheck.java create mode 100644 forge-1.19/src/main/java/org/dynmap/forge_1_19/permissions/FilePermissions.java create mode 100644 forge-1.19/src/main/java/org/dynmap/forge_1_19/permissions/OpPermissions.java create mode 100644 forge-1.19/src/main/java/org/dynmap/forge_1_19/permissions/PermissionProvider.java create mode 100644 forge-1.19/src/main/resources/META-INF/accesstransformer.cfg create mode 100644 forge-1.19/src/main/resources/META-INF/mods.toml create mode 100644 forge-1.19/src/main/resources/configuration.txt create mode 100644 forge-1.19/src/main/resources/pack.mcmeta create mode 100644 forge-1.19/src/main/resources/permissions.yml.example diff --git a/bukkit-helper/.project b/bukkit-helper/.project index b372cd57..e86ee638 100644 --- a/bukkit-helper/.project +++ b/bukkit-helper/.project @@ -2,35 +2,32 @@ Dynmap(Spigot-Common) bukkit-helper - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.buildship.core.gradleprojectbuilder - - - - - org.eclipse.m2e.core.maven2Builder - - - - + org.eclipse.jdt.core.javanature org.eclipse.m2e.core.maven2Nature org.eclipse.buildship.core.gradleprojectnature + + + org.eclipse.jdt.core.javabuilder + + + + org.eclipse.buildship.core.gradleprojectbuilder + + + + org.eclipse.m2e.core.maven2Builder + + + + 1 - 30 + org.eclipse.core.resources.regexFilterMatcher node_modules|.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__ diff --git a/bukkit-helper/.settings/org.eclipse.jdt.core.prefs b/bukkit-helper/.settings/org.eclipse.jdt.core.prefs index 68479f99..ed0a92f7 100644 --- a/bukkit-helper/.settings/org.eclipse.jdt.core.prefs +++ b/bukkit-helper/.settings/org.eclipse.jdt.core.prefs @@ -1,5 +1,5 @@ # -#Tue Jun 07 11:38:11 CDT 2022 +#Tue Jun 07 20:25:33 CDT 2022 org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning org.eclipse.jdt.core.compiler.problem.assertIdentifier=error org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 diff --git a/forge-1.19/.gitignore b/forge-1.19/.gitignore new file mode 100644 index 00000000..84c048a7 --- /dev/null +++ b/forge-1.19/.gitignore @@ -0,0 +1 @@ +/build/ diff --git a/forge-1.19/bin/.gitignore b/forge-1.19/bin/.gitignore new file mode 100644 index 00000000..7eed456b --- /dev/null +++ b/forge-1.19/bin/.gitignore @@ -0,0 +1,2 @@ +/main/ +/test/ diff --git a/forge-1.19/build.gradle b/forge-1.19/build.gradle new file mode 100644 index 00000000..e4c9fcc2 --- /dev/null +++ b/forge-1.19/build.gradle @@ -0,0 +1,92 @@ +buildscript { + repositories { + maven { url = 'https://files.minecraftforge.net/maven' } + jcenter() + mavenCentral() + } + dependencies { + classpath group: 'net.minecraftforge.gradle', name: 'ForgeGradle', version: '5.1.+', changing: true + } +} +apply plugin: 'net.minecraftforge.gradle' +apply plugin: 'com.github.johnrengelman.shadow' +apply plugin: 'eclipse' + +eclipse { + project { + name = "Dynmap(Forge-1.19)" + } +} + +sourceCompatibility = targetCompatibility = compileJava.sourceCompatibility = compileJava.targetCompatibility = JavaLanguageVersion.of(17) // Need this here so eclipse task generates correctly. + +println('Java: ' + System.getProperty('java.version') + ' JVM: ' + System.getProperty('java.vm.version') + '(' + System.getProperty('java.vendor') + ') Arch: ' + System.getProperty('os.arch')) + +ext.buildNumber = System.getenv().BUILD_NUMBER ?: "Dev" + +minecraft { + mappings channel: 'official', version: '1.19' + accessTransformer = file('src/main/resources/META-INF/accesstransformer.cfg') + runs { + server { + workingDirectory project.file('run').canonicalPath + } + } +} + +project.archivesBaseName = "${project.archivesBaseName}-forge-1.19" + +dependencies { + implementation project(path: ":DynmapCore", configuration: "shadow") + implementation project(path: ':DynmapCoreAPI') + + minecraft 'net.minecraftforge:forge:1.19-41.0.1' +} + +processResources +{ + filesMatching('META-INF/mods.toml') { + // replace version and mcversion + expand( + version: project.version + '-' + project.ext.buildNumber, + mcversion: "1.19" + ) + } +} + +shadowJar { + dependencies { + include(dependency(':DynmapCore')) + include(dependency("commons-codec:commons-codec:")) + exclude("META-INF/maven/**") + exclude("META-INF/services/**") + } + relocate('org.apache.commons.codec', 'org.dynmap.forge_1_19.commons.codec') + + archiveName = "Dynmap-${parent.version}-forge-1.19.jar" + destinationDir = file '../target' +} + +shadowJar.doLast { + task -> + ant.checksum file: task.archivePath +} + +afterEvaluate { +reobf { + shadowJar { + mappings = createMcpToSrg.output + } +} +} + +task deobfJar(type: Jar) { + from sourceSets.main.output + classifier = 'dev' +} + +artifacts { + archives deobfJar +} + +build.dependsOn(shadowJar) diff --git a/forge-1.19/src/main/java/org/dynmap/forge_1_19/ClientProxy.java b/forge-1.19/src/main/java/org/dynmap/forge_1_19/ClientProxy.java new file mode 100644 index 00000000..a467dc70 --- /dev/null +++ b/forge-1.19/src/main/java/org/dynmap/forge_1_19/ClientProxy.java @@ -0,0 +1,6 @@ +package org.dynmap.forge_1_19; + +public class ClientProxy extends Proxy { + public ClientProxy() { + } +} diff --git a/forge-1.19/src/main/java/org/dynmap/forge_1_19/DynmapMod.java b/forge-1.19/src/main/java/org/dynmap/forge_1_19/DynmapMod.java new file mode 100644 index 00000000..c9355651 --- /dev/null +++ b/forge-1.19/src/main/java/org/dynmap/forge_1_19/DynmapMod.java @@ -0,0 +1,136 @@ +package org.dynmap.forge_1_19; + +import java.io.File; + +import org.apache.commons.lang3.tuple.Pair; +import org.dynmap.DynmapCommonAPI; +import org.dynmap.DynmapCommonAPIListener; +import org.dynmap.Log; +import org.dynmap.forge_1_19.DynmapPlugin.OurLog; + +import net.minecraft.server.MinecraftServer; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.server.ServerAboutToStartEvent; +import net.minecraftforge.event.server.ServerStartedEvent; +import net.minecraftforge.event.server.ServerStartingEvent; +import net.minecraftforge.event.server.ServerStoppingEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.DistExecutor; +import net.minecraftforge.fml.IExtensionPoint; +import net.minecraftforge.fml.ModList; +import net.minecraftforge.fml.ModLoadingContext; +import net.minecraftforge.fml.StartupMessageManager; +import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent; +import net.minecraftforge.fml.event.lifecycle.FMLLoadCompleteEvent; +import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; +import net.minecraftforge.network.NetworkConstants;; + +@Mod("dynmap") +public class DynmapMod +{ + // The instance of your mod that Forge uses. + public static DynmapMod instance; + + // Says where the client and server 'proxy' code is loaded. + public static Proxy proxy = DistExecutor.runForDist(() -> ClientProxy::new, () -> Proxy::new); + + public static DynmapPlugin plugin; + public static File jarfile; + public static String ver; + public static boolean useforcedchunks; + + public class APICallback extends DynmapCommonAPIListener { + @Override + public void apiListenerAdded() { + if(plugin == null) { + plugin = proxy.startServer(server); + } + } + @Override + public void apiEnabled(DynmapCommonAPI api) { + } + } + + //TODO + //public class LoadingCallback implements net.minecraftforge.common.ForgeChunkManager.LoadingCallback { + // @Override + // public void ticketsLoaded(List tickets, World world) { + // if(tickets.size() > 0) { + // DynmapPlugin.setBusy(world, tickets.get(0)); + // for(int i = 1; i < tickets.size(); i++) { + // ForgeChunkManager.releaseTicket(tickets.get(i)); + // } + // } + // } + //} + + public DynmapMod() { + instance = this; + FMLJavaModLoadingContext.get().getModEventBus().addListener(this::setup); + FMLJavaModLoadingContext.get().getModEventBus().addListener(this::init); + + MinecraftForge.EVENT_BUS.register(this); + + ModLoadingContext.get().registerExtensionPoint(IExtensionPoint.DisplayTest.class, + ()->new IExtensionPoint.DisplayTest(()->NetworkConstants.IGNORESERVERONLY, (remote, isServer)-> true)); + + Log.setLogger(new OurLog()); + org.dynmap.modsupport.ModSupportImpl.init(); + } + + public void setup(final FMLCommonSetupEvent event) + { + //TOOO + jarfile = ModList.get().getModFileById("dynmap").getFile().getFilePath().toFile(); + + ver = ModList.get().getModContainerById("dynmap").get().getModInfo().getVersion().toString(); + + //// Load configuration file - use suggested (config/WesterosBlocks.cfg) + //Configuration cfg = new Configuration(event.getSuggestedConfigurationFile()); + //try { + // cfg.load(); + // + // useforcedchunks = cfg.get("Settings", "UseForcedChunks", true).getBoolean(true); + //} + //finally + //{ + // cfg.save(); + //} + } + + public void init(FMLLoadCompleteEvent event) + { + /* Set up for chunk loading notice from chunk manager */ + //TODO + //if(useforcedchunks) { + // ForgeChunkManager.setForcedChunkLoadingCallback(DynmapMod.instance, new LoadingCallback()); + //} + //else { + // Log.info("[Dynmap] World loading using forced chunks is disabled"); + //} + } + + private MinecraftServer server; + + @SubscribeEvent + public void onServerStarting(ServerAboutToStartEvent event) { + server = event.getServer(); + if(plugin == null) + plugin = proxy.startServer(server); + plugin.onStarting(server.getCommands().getDispatcher()); + } + + @SubscribeEvent + public void onServerStarted(ServerStartedEvent event) { + DynmapCommonAPIListener.register(new APICallback()); + plugin.serverStarted(); + } + + @SubscribeEvent + public void serverStopping(ServerStoppingEvent event) + { + proxy.stopServer(plugin); + plugin = null; + } +} diff --git a/forge-1.19/src/main/java/org/dynmap/forge_1_19/DynmapPlugin.java b/forge-1.19/src/main/java/org/dynmap/forge_1_19/DynmapPlugin.java new file mode 100644 index 00000000..f069f2bf --- /dev/null +++ b/forge-1.19/src/main/java/org/dynmap/forge_1_19/DynmapPlugin.java @@ -0,0 +1,2018 @@ +package org.dynmap.forge_1_19; + +import java.io.File; +import java.io.InputStream; +import java.net.InetSocketAddress; +import java.net.SocketAddress; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Base64; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Optional; +import java.util.PriorityQueue; +import java.util.Set; +import java.util.UUID; +import java.util.concurrent.Callable; +import java.util.concurrent.CancellationException; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; +import java.util.concurrent.FutureTask; +import java.util.regex.Pattern; + +import net.minecraft.Util; +import net.minecraft.commands.CommandSource; +import net.minecraft.commands.CommandSourceStack; +import net.minecraft.commands.Commands; +import net.minecraft.core.BlockPos; +import net.minecraft.core.IdMapper; +import net.minecraft.core.Registry; +import net.minecraft.network.Connection; +import net.minecraft.network.chat.ChatType; +import net.minecraft.network.chat.Component; +import net.minecraft.network.protocol.game.ClientboundSetSubtitleTextPacket; +import net.minecraft.network.protocol.game.ClientboundSetTitleTextPacket; +import net.minecraft.network.protocol.game.ClientboundSetTitlesAnimationPacket; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ChunkHolder; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.server.network.ServerGamePacketListenerImpl; +import net.minecraft.server.players.GameProfileCache; +import net.minecraft.server.players.UserBanList; +import net.minecraft.world.entity.Pose; +import net.minecraft.world.level.ChunkPos; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.LiquidBlock; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.chunk.ChunkAccess; +import net.minecraft.world.level.chunk.ChunkStatus; +import net.minecraft.world.level.chunk.LevelChunk; +import net.minecraft.world.level.chunk.LevelChunkSection; +import net.minecraft.world.level.material.Material; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.ServerChatEvent; +import net.minecraftforge.event.TickEvent; +import net.minecraftforge.event.entity.player.PlayerEvent.PlayerChangedDimensionEvent; +import net.minecraftforge.event.entity.player.PlayerEvent.PlayerLoggedInEvent; +import net.minecraftforge.event.entity.player.PlayerEvent.PlayerLoggedOutEvent; +import net.minecraftforge.event.entity.player.PlayerEvent.PlayerRespawnEvent; +import net.minecraftforge.event.world.BlockEvent; +import net.minecraftforge.event.world.ChunkDataEvent; +import net.minecraftforge.event.world.ChunkEvent; +import net.minecraftforge.event.world.WorldEvent; +import net.minecraftforge.fml.ModList; +import net.minecraftforge.fml.ModContainer; +import net.minecraftforge.fml.loading.LoadingModList; +import net.minecraftforge.fml.loading.moddiscovery.ModFileInfo; +import net.minecraftforge.fml.loading.moddiscovery.ModInfo; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.apache.maven.artifact.versioning.ArtifactVersion; +import org.dynmap.ConfigurationNode; +import org.dynmap.DynmapChunk; +import org.dynmap.DynmapCommonAPIListener; +import org.dynmap.DynmapCore; +import org.dynmap.DynmapLocation; +import org.dynmap.DynmapWorld; +import org.dynmap.Log; +import org.dynmap.MapManager; +import org.dynmap.PlayerList; +import org.dynmap.common.BiomeMap; +import org.dynmap.common.DynmapCommandSender; +import org.dynmap.common.DynmapPlayer; +import org.dynmap.common.DynmapServerInterface; +import org.dynmap.common.DynmapListenerManager.EventType; +import org.dynmap.common.chunk.GenericChunkCache; +import org.dynmap.forge_1_19.DmapCommand; +import org.dynmap.forge_1_19.DmarkerCommand; +import org.dynmap.forge_1_19.DynmapCommand; +import org.dynmap.forge_1_19.permissions.FilePermissions; +import org.dynmap.forge_1_19.permissions.OpPermissions; +import org.dynmap.forge_1_19.permissions.PermissionProvider; +import org.dynmap.permissions.PermissionsHandler; +import org.dynmap.renderer.DynmapBlockState; +import org.dynmap.utils.DynmapLogger; +import org.dynmap.utils.MapChunkCache; +import org.dynmap.utils.VisibilityLimit; + +import com.google.common.collect.Iterables; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonParseException; +import com.mojang.authlib.GameProfile; +import com.mojang.authlib.properties.Property; +import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.arguments.StringArgumentType; +import com.mojang.brigadier.builder.RequiredArgumentBuilder; +import com.mojang.brigadier.exceptions.CommandSyntaxException; + +import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; +import it.unimi.dsi.fastutil.longs.LongOpenHashSet; +import net.minecraftforge.eventbus.api.EventPriority; +import net.minecraftforge.eventbus.api.SubscribeEvent; + +import net.minecraft.world.level.EmptyBlockGetter; + +public class DynmapPlugin +{ + private DynmapCore core; + private PermissionProvider permissions; + private boolean core_enabled; + public GenericChunkCache sscache; + public PlayerList playerList; + private MapManager mapManager; + private static net.minecraft.server.MinecraftServer server; + public static DynmapPlugin plugin; + private ChatHandler chathandler; + private HashMap sortWeights = new HashMap(); + // Drop world load ticket after 30 seconds + private long worldIdleTimeoutNS = 30 * 1000000000L; + private HashMap worlds = new HashMap(); + private LevelAccessor last_world; + private ForgeWorld last_fworld; + private Map players = new HashMap(); + //TODO private ForgeMetrics metrics; + private HashSet modsused = new HashSet(); + private ForgeServer fserver = new ForgeServer(); + private boolean tickregistered = false; + // TPS calculator + private double tps; + private long lasttick; + private long avgticklen; + // Per tick limit, in nsec + private long perTickLimit = (50000000); // 50 ms + private boolean useSaveFolder = true; + + private static final String[] TRIGGER_DEFAULTS = { "blockupdate", "chunkpopulate", "chunkgenerate" }; + + private static final Pattern patternControlCode = Pattern.compile("(?i)\\u00A7[0-9A-FK-OR]"); + + public static class BlockUpdateRec { + LevelAccessor w; + String wid; + int x, y, z; + } + ConcurrentLinkedQueue blockupdatequeue = new ConcurrentLinkedQueue(); + + public static DynmapBlockState[] stateByID; + + private Map knownloadedchunks = new HashMap(); + private boolean didInitialKnownChunks = false; + private void addKnownChunk(ForgeWorld fw, ChunkPos pos) { + LongOpenHashSet cset = knownloadedchunks.get(fw.getName()); + if (cset == null) { + cset = new LongOpenHashSet(); + knownloadedchunks.put(fw.getName(), cset); + } + cset.add(pos.toLong()); + } + private void removeKnownChunk(ForgeWorld fw, ChunkPos pos) { + LongOpenHashSet cset = knownloadedchunks.get(fw.getName()); + if (cset != null) { + cset.remove(pos.toLong()); + } + } + private boolean checkIfKnownChunk(ForgeWorld fw, ChunkPos pos) { + LongOpenHashSet cset = knownloadedchunks.get(fw.getName()); + if (cset != null) { + return cset.contains(pos.toLong()); + } + return false; + } + + private static Registry reg = null; + + private static Registry getBiomeReg() { + if (reg == null) { + reg = server.registryAccess().ownedRegistryOrThrow(Registry.BIOME_REGISTRY); + } + return reg; + } + + /** + * Initialize block states (org.dynmap.blockstate.DynmapBlockState) + */ + public void initializeBlockStates() { + stateByID = new DynmapBlockState[512*32]; // Simple map - scale as needed + Arrays.fill(stateByID, DynmapBlockState.AIR); // Default to air + + IdMapper bsids = Block.BLOCK_STATE_REGISTRY; + + DynmapBlockState basebs = null; + Block baseb = null; + int baseidx = 0; + + Iterator iter = bsids.iterator(); + DynmapBlockState.Builder bld = new DynmapBlockState.Builder(); + while (iter.hasNext()) { + BlockState bs = iter.next(); + int idx = bsids.getId(bs); + if (idx >= stateByID.length) { + int plen = stateByID.length; + stateByID = Arrays.copyOf(stateByID, idx*11/10); // grow array by 10% + Arrays.fill(stateByID, plen, stateByID.length, DynmapBlockState.AIR); + } + Block b = bs.getBlock(); + // If this is new block vs last, it's the base block state + if (b != baseb) { + basebs = null; + baseidx = idx; + baseb = b; + } + ResourceLocation ui = Registry.BLOCK.getKey(b); + + if (ui == null) { + continue; + } + String bn = ui.getNamespace() + ":" + ui.getPath(); + // Only do defined names, and not "air" + if (!bn.equals(DynmapBlockState.AIR_BLOCK)) { + Material mat = bs.getMaterial(); + String statename = ""; + for (net.minecraft.world.level.block.state.properties.Property p : bs.getProperties()) { + if (statename.length() > 0) { + statename += ","; + } + statename += p.getName() + "=" + bs.getValue(p).toString(); + } + int lightAtten = 15; + try { // Workaround for mods with broken block state logic... + lightAtten =bs.isSolidRender(EmptyBlockGetter.INSTANCE, BlockPos.ZERO) ? 15 : (bs.propagatesSkylightDown(EmptyBlockGetter.INSTANCE, BlockPos.ZERO) ? 0 : 1); + } catch (Exception x) { + Log.warning(String.format("Exception while checking lighting data for block state: %s[%s]", bn, statename)); + Log.verboseinfo("Exception: " + x.toString()); + } + //Log.info("statename=" + bn + "[" + statename + "], lightAtten=" + lightAtten); + // Fill in base attributes + bld.setBaseState(basebs).setStateIndex(idx - baseidx).setBlockName(bn).setStateName(statename).setMaterial(mat.toString()).setLegacyBlockID(idx).setAttenuatesLight(lightAtten); + if (mat.isSolid()) { bld.setSolid(); } + if (mat == Material.AIR) { bld.setAir(); } + if (mat == Material.WOOD) { bld.setLog(); } + if (mat == Material.LEAVES) { bld.setLeaves(); } + if ((!bs.getFluidState().isEmpty()) && !(bs.getBlock() instanceof LiquidBlock)) { + bld.setWaterlogged(); + } + DynmapBlockState dbs = bld.build(); // Build state + stateByID[idx] = dbs; + if (basebs == null) { basebs = dbs; } + } + } + for (int gidx = 0; gidx < DynmapBlockState.getGlobalIndexMax(); gidx++) { + DynmapBlockState bs = DynmapBlockState.getStateByGlobalIndex(gidx); + //Log.info(gidx + ":" + bs.toString() + ", gidx=" + bs.globalStateIndex + ", sidx=" + bs.stateIndex); + } + } + + //public static final Item getItemByID(int id) { + // return Item.getItemById(id); + //} + + private static Biome[] biomelist = null; + + public static final Biome[] getBiomeList() { + if (biomelist == null) { + biomelist = new Biome[256]; + Iterator iter = getBiomeReg().iterator(); + while (iter.hasNext()) { + Biome b = iter.next(); + int bidx = getBiomeReg().getId(b); + if (bidx >= biomelist.length) { + biomelist = Arrays.copyOf(biomelist, bidx + biomelist.length); + } + biomelist[bidx] = b; + } + } + return biomelist; + } + //public static final NetworkManager getNetworkManager(ServerPlayNetHandler nh) { + // return nh.netManager; + //} + + private ForgePlayer getOrAddPlayer(ServerPlayer p) { + String name = p.getName().getString(); + ForgePlayer fp = players.get(name); + if(fp != null) { + fp.player = p; + } + else { + fp = new ForgePlayer(p); + players.put(name, fp); + } + return fp; + } + + private static class TaskRecord implements Comparable + { + private long ticktorun; + private long id; + private FutureTask future; + @Override + public int compareTo(Object o) + { + TaskRecord tr = (TaskRecord)o; + + if (this.ticktorun < tr.ticktorun) + { + return -1; + } + else if (this.ticktorun > tr.ticktorun) + { + return 1; + } + else if (this.id < tr.id) + { + return -1; + } + else if (this.id > tr.id) + { + return 1; + } + else + { + return 0; + } + } + } + + private class ChatMessage { + String message; + ServerPlayer sender; + } + private ConcurrentLinkedQueue msgqueue = new ConcurrentLinkedQueue(); + + public class ChatHandler { + @SubscribeEvent + public void handleChat(ServerChatEvent event) { + String msg = event.getMessage(); + if(!msg.startsWith("/")) { + ChatMessage cm = new ChatMessage(); + cm.message = msg; + cm.sender = event.getPlayer(); + msgqueue.add(cm); + } + } + } + + /** TODO: depends on forge chunk manager + private static class WorldBusyRecord { + long last_ts; + Ticket ticket; + } + private static HashMap busy_worlds = new HashMap(); + + private void setBusy(World w) { + setBusy(w, null); + } + static void setBusy(World w, Ticket t) { + if(w == null) return; + if (!DynmapMod.useforcedchunks) return; + WorldBusyRecord wbr = busy_worlds.get(w.provider.getDimension()); + if(wbr == null) { // Not busy, make ticket and keep spawn loaded + Debug.debug("World " + w.getWorldInfo().getWorldName() + "/"+ w.provider.getDimensionType().getName() + " is busy"); + wbr = new WorldBusyRecord(); + if(t != null) + wbr.ticket = t; + else + wbr.ticket = ForgeChunkManager.requestTicket(DynmapMod.instance, w, ForgeChunkManager.Type.NORMAL); + if(wbr.ticket != null) { + BlockPos cc = w.getSpawnPoint(); + ChunkPos ccip = new ChunkPos(cc.getX() >> 4, cc.getZ() >> 4); + ForgeChunkManager.forceChunk(wbr.ticket, ccip); + busy_worlds.put(w.provider.getDimension(), wbr); // Add to busy list + } + } + wbr.last_ts = System.nanoTime(); + } + + private void doIdleOutOfWorlds() { + if (!DynmapMod.useforcedchunks) return; + long ts = System.nanoTime() - worldIdleTimeoutNS; + for(Iterator itr = busy_worlds.values().iterator(); itr.hasNext();) { + WorldBusyRecord wbr = itr.next(); + if(wbr.last_ts < ts) { + World w = wbr.ticket.world; + Debug.debug("World " + w.getWorldInfo().getWorldName() + "/" + wbr.ticket.world.provider.getDimensionType().getName() + " is idle"); + if (wbr.ticket != null) + ForgeChunkManager.releaseTicket(wbr.ticket); // Release hold on world + itr.remove(); + } + } + } + */ + + public static class OurLog implements DynmapLogger { + Logger log; + public static final String DM = "[Dynmap] "; + OurLog() { + log = LogManager.getLogger("Dynmap"); + } + @Override + public void info(String s) { + log.info(DM + s); + } + + @Override + public void severe(Throwable t) { + log.fatal(t); + } + + @Override + public void severe(String s) { + log.fatal(DM + s); + } + + @Override + public void severe(String s, Throwable t) { + log.fatal(DM + s, t); + } + + @Override + public void verboseinfo(String s) { + log.info(DM + s); + } + + @Override + public void warning(String s) { + log.warn(DM + s); + } + + @Override + public void warning(String s, Throwable t) { + log.warn(DM + s, t); + } + } + + public DynmapPlugin(MinecraftServer srv) + { + plugin = this; + this.server = srv; + } + + public boolean isOp(String player) { + String[] ops = server.getPlayerList().getOps().getUserList(); + for (String op : ops) { + if (op.equalsIgnoreCase(player)) { + return true; + } + } + return (server.isSingleplayer() && player.equalsIgnoreCase(server.getSingleplayerProfile().getName())); + } + + private boolean hasPerm(ServerPlayer psender, String permission) { + PermissionsHandler ph = PermissionsHandler.getHandler(); + if ((psender != null) && (ph != null) && ph.hasPermission(psender.getName().getString(), permission)) { + return true; + } + return permissions.has(psender, permission); + } + + private boolean hasPermNode(ServerPlayer psender, String permission) { + PermissionsHandler ph = PermissionsHandler.getHandler(); + if ((psender != null) && (ph != null) && ph.hasPermissionNode(psender.getName().getString(), permission)) { + return true; + } + return permissions.hasPermissionNode(psender, permission); + } + + private Set hasOfflinePermissions(String player, Set perms) { + Set rslt = null; + PermissionsHandler ph = PermissionsHandler.getHandler(); + if(ph != null) { + rslt = ph.hasOfflinePermissions(player, perms); + } + Set rslt2 = hasOfflinePermissions(player, perms); + if((rslt != null) && (rslt2 != null)) { + Set newrslt = new HashSet(rslt); + newrslt.addAll(rslt2); + rslt = newrslt; + } + else if(rslt2 != null) { + rslt = rslt2; + } + return rslt; + } + private boolean hasOfflinePermission(String player, String perm) { + PermissionsHandler ph = PermissionsHandler.getHandler(); + if(ph != null) { + if(ph.hasOfflinePermission(player, perm)) { + return true; + } + } + return permissions.hasOfflinePermission(player, perm); + } + + /** + * Server access abstraction class + */ + public class ForgeServer extends DynmapServerInterface + { + /* Server thread scheduler */ + private Object schedlock = new Object(); + private long cur_tick; + private long next_id; + private long cur_tick_starttime; + private PriorityQueue runqueue = new PriorityQueue(); + + public ForgeServer() { + } + + private GameProfile getProfileByName(String player) { + GameProfileCache cache = server.getProfileCache(); + Optional val = cache.get(player); + return val.isPresent() ? val.get() : null; + } + + @Override + public int getBlockIDAt(String wname, int x, int y, int z) { + return -1; + } + + @Override + public int isSignAt(String wname, int x, int y, int z) { + return -1; + } + + @Override + public void scheduleServerTask(Runnable run, long delay) + { + TaskRecord tr = new TaskRecord(); + tr.future = new FutureTask(run, null); + + /* Add task record to queue */ + synchronized (schedlock) + { + tr.id = next_id++; + tr.ticktorun = cur_tick + delay; + runqueue.add(tr); + } + } + @Override + public DynmapPlayer[] getOnlinePlayers() + { + if(server.getPlayerList() == null) + return new DynmapPlayer[0]; + List playlist = server.getPlayerList().getPlayers(); + int pcnt = playlist.size(); + DynmapPlayer[] dplay = new DynmapPlayer[pcnt]; + + for (int i = 0; i < pcnt; i++) + { + ServerPlayer p = playlist.get(i); + dplay[i] = getOrAddPlayer(p); + } + + return dplay; + } + @Override + public void reload() + { + plugin.onDisable(); + plugin.onEnable(); + plugin.onStart(); + } + @Override + public DynmapPlayer getPlayer(String name) + { + List players = server.getPlayerList().getPlayers(); + + for (ServerPlayer p : players) + { + if (p.getName().getString().equalsIgnoreCase(name)) + { + return getOrAddPlayer(p); + } + } + + return null; + } + @Override + public Set getIPBans() + { + UserBanList bl = server.getPlayerList().getBans(); + Set ips = new HashSet(); + + for (String s : bl.getUserList()) { + ips.add(s); + } + + return ips; + } + @Override + public Future callSyncMethod(Callable task) { + return callSyncMethod(task, 0); + } + public Future callSyncMethod(Callable task, long delay) + { + TaskRecord tr = new TaskRecord(); + FutureTask ft = new FutureTask(task); + tr.future = ft; + + /* Add task record to queue */ + synchronized (schedlock) + { + tr.id = next_id++; + tr.ticktorun = cur_tick + delay; + runqueue.add(tr); + } + + return ft; + } + @Override + public String getServerName() + { + String sn; + if (server.isSingleplayer()) + sn = "Integrated"; + else + sn = server.getLocalIp(); + if(sn == null) sn = "Unknown Server"; + return sn; + } + @Override + public boolean isPlayerBanned(String pid) + { + UserBanList bl = server.getPlayerList().getBans(); + return bl.isBanned(getProfileByName(pid)); + } + + @Override + public String stripChatColor(String s) + { + return patternControlCode.matcher(s).replaceAll(""); + } + private Set registered = new HashSet(); + @Override + public boolean requestEventNotification(EventType type) + { + if (registered.contains(type)) + { + return true; + } + + switch (type) + { + case WORLD_LOAD: + case WORLD_UNLOAD: + /* Already called for normal world activation/deactivation */ + break; + + case WORLD_SPAWN_CHANGE: + /*TODO + pm.registerEvents(new Listener() { + @EventHandler(priority=EventPriority.MONITOR) + public void onSpawnChange(SpawnChangeEvent evt) { + DynmapWorld w = new BukkitWorld(evt.getWorld()); + core.listenerManager.processWorldEvent(EventType.WORLD_SPAWN_CHANGE, w); + } + }, DynmapPlugin.this); + */ + break; + + case PLAYER_JOIN: + case PLAYER_QUIT: + /* Already handled */ + break; + + case PLAYER_BED_LEAVE: + /*TODO + pm.registerEvents(new Listener() { + @EventHandler(priority=EventPriority.MONITOR) + public void onPlayerBedLeave(PlayerBedLeaveEvent evt) { + DynmapPlayer p = new BukkitPlayer(evt.getPlayer()); + core.listenerManager.processPlayerEvent(EventType.PLAYER_BED_LEAVE, p); + } + }, DynmapPlugin.this); + */ + break; + + case PLAYER_CHAT: + if (chathandler == null) { + chathandler = new ChatHandler(); + MinecraftForge.EVENT_BUS.register(chathandler); + } + break; + + case BLOCK_BREAK: + /*TODO + pm.registerEvents(new Listener() { + @EventHandler(priority=EventPriority.MONITOR) + public void onBlockBreak(BlockBreakEvent evt) { + if(evt.isCancelled()) return; + Block b = evt.getBlock(); + if(b == null) return; + Location l = b.getLocation(); + core.listenerManager.processBlockEvent(EventType.BLOCK_BREAK, b.getType().getId(), + BukkitWorld.normalizeWorldName(l.getWorld().getName()), l.getBlockX(), l.getBlockY(), l.getBlockZ()); + } + }, DynmapPlugin.this); + */ + break; + + case SIGN_CHANGE: + /*TODO + pm.registerEvents(new Listener() { + @EventHandler(priority=EventPriority.MONITOR) + public void onSignChange(SignChangeEvent evt) { + if(evt.isCancelled()) return; + Block b = evt.getBlock(); + Location l = b.getLocation(); + String[] lines = evt.getLines(); + DynmapPlayer dp = null; + Player p = evt.getPlayer(); + if(p != null) dp = new BukkitPlayer(p); + core.listenerManager.processSignChangeEvent(EventType.SIGN_CHANGE, b.getType().getId(), + BukkitWorld.normalizeWorldName(l.getWorld().getName()), l.getBlockX(), l.getBlockY(), l.getBlockZ(), lines, dp); + } + }, DynmapPlugin.this); + */ + break; + + default: + Log.severe("Unhandled event type: " + type); + return false; + } + + registered.add(type); + return true; + } + @Override + public boolean sendWebChatEvent(String source, String name, String msg) + { + return DynmapCommonAPIListener.fireWebChatEvent(source, name, msg); + } + @Override + public void broadcastMessage(String msg) + { + Component component = Component.literal(msg); + server.getPlayerList().broadcastSystemMessage(component, ChatType.SYSTEM); + Log.info(stripChatColor(msg)); + } + @Override + public String[] getBiomeIDs() + { + BiomeMap[] b = BiomeMap.values(); + String[] bname = new String[b.length]; + + for (int i = 0; i < bname.length; i++) + { + bname[i] = b[i].toString(); + } + + return bname; + } + @Override + public double getCacheHitRate() + { + if(sscache != null) + return sscache.getHitRate(); + return 0.0; + } + @Override + public void resetCacheStats() + { + if(sscache != null) + sscache.resetStats(); + } + @Override + public DynmapWorld getWorldByName(String wname) + { + return DynmapPlugin.this.getWorldByName(wname); + } + @Override + public DynmapPlayer getOfflinePlayer(String name) + { + /* + OfflinePlayer op = getServer().getOfflinePlayer(name); + if(op != null) { + return new BukkitPlayer(op); + } + */ + return null; + } + @Override + public Set checkPlayerPermissions(String player, Set perms) + { + net.minecraft.server.players.PlayerList scm = server.getPlayerList(); + if (scm == null) return Collections.emptySet(); + UserBanList bl = scm.getBans(); + if (bl == null) return Collections.emptySet(); + if(bl.isBanned(getProfileByName(player))) { + return Collections.emptySet(); + } + Set rslt = hasOfflinePermissions(player, perms); + if (rslt == null) { + rslt = new HashSet(); + if(plugin.isOp(player)) { + rslt.addAll(perms); + } + } + return rslt; + } + @Override + public boolean checkPlayerPermission(String player, String perm) + { + net.minecraft.server.players.PlayerList scm = server.getPlayerList(); + if (scm == null) return false; + UserBanList bl = scm.getBans(); + if (bl == null) return false; + if(bl.isBanned(getProfileByName(player))) { + return false; + } + return hasOfflinePermission(player, perm); + } + /** + * Render processor helper - used by code running on render threads to request chunk snapshot cache from server/sync thread + */ + @Override + public MapChunkCache createMapChunkCache(DynmapWorld w, List chunks, + boolean blockdata, boolean highesty, boolean biome, boolean rawbiome) + { + ForgeMapChunkCache c = (ForgeMapChunkCache) w.getChunkCache(chunks); + if(c == null) { + return null; + } + if (w.visibility_limits != null) + { + for (VisibilityLimit limit: w.visibility_limits) + { + c.setVisibleRange(limit); + } + + c.setHiddenFillStyle(w.hiddenchunkstyle); + } + + if (w.hidden_limits != null) + { + for (VisibilityLimit limit: w.hidden_limits) + { + c.setHiddenRange(limit); + } + + c.setHiddenFillStyle(w.hiddenchunkstyle); + } + + if (chunks.size() == 0) /* No chunks to get? */ + { + c.loadChunks(0); + return c; + } + + //Now handle any chunks in server thread that are already loaded (on server thread) + final ForgeMapChunkCache cc = c; + Future f = this.callSyncMethod(new Callable() { + public Boolean call() throws Exception { + // Update busy state on world + ForgeWorld fw = (ForgeWorld)cc.getWorld(); + //TODO + //setBusy(fw.getWorld()); + cc.getLoadedChunks(); + return true; + } + }, 0); + try { + f.get(); + } + catch (CancellationException cx) { + return null; + } + catch (InterruptedException cx) { + return null; + } + catch (ExecutionException xx) { + Log.severe("Exception while loading chunks", xx.getCause()); + return null; + } + catch (Exception ix) { + Log.severe(ix); + return null; + } + if(w.isLoaded() == false) { + return null; + } + // Now, do rest of chunk reading from calling thread + c.readChunks(chunks.size()); + + return c; + } + @Override + public int getMaxPlayers() + { + return server.getMaxPlayers(); + } + @Override + public int getCurrentPlayers() + { + return server.getPlayerList().getPlayerCount(); + } + + @SubscribeEvent + public void tickEvent(TickEvent.ServerTickEvent event) { + if (event.phase == TickEvent.Phase.START) { + return; + } + cur_tick_starttime = System.nanoTime(); + long elapsed = cur_tick_starttime - lasttick; + lasttick = cur_tick_starttime; + avgticklen = ((avgticklen * 99) / 100) + (elapsed / 100); + tps = (double)1E9 / (double)avgticklen; + // Tick core + if (core != null) { + core.serverTick(tps); + } + + boolean done = false; + TaskRecord tr = null; + + while(!blockupdatequeue.isEmpty()) { + BlockUpdateRec r = blockupdatequeue.remove(); + BlockState bs = r.w.getBlockState(new BlockPos(r.x, r.y, r.z)); + int idx = Block.BLOCK_STATE_REGISTRY.getId(bs); + if((idx >= 0) && (!org.dynmap.hdmap.HDBlockModels.isChangeIgnoredBlock(stateByID[idx]))) { + if(onblockchange_with_id) + mapManager.touch(r.wid, r.x, r.y, r.z, "blockchange[" + idx + "]"); + else + mapManager.touch(r.wid, r.x, r.y, r.z, "blockchange"); + } + } + + long now; + + synchronized(schedlock) { + cur_tick++; + now = System.nanoTime(); + tr = runqueue.peek(); + /* Nothing due to run */ + if((tr == null) || (tr.ticktorun > cur_tick) || ((now - cur_tick_starttime) > perTickLimit)) { + done = true; + } + else { + tr = runqueue.poll(); + } + } + while (!done) { + tr.future.run(); + + synchronized(schedlock) { + tr = runqueue.peek(); + now = System.nanoTime(); + /* Nothing due to run */ + if((tr == null) || (tr.ticktorun > cur_tick) || ((now - cur_tick_starttime) > perTickLimit)) { + done = true; + } + else { + tr = runqueue.poll(); + } + } + } + while(!msgqueue.isEmpty()) { + ChatMessage cm = msgqueue.poll(); + DynmapPlayer dp = null; + if(cm.sender != null) + dp = getOrAddPlayer(cm.sender); + else + dp = new ForgePlayer(null); + + core.listenerManager.processChatEvent(EventType.PLAYER_CHAT, dp, cm.message); + } + // Check for generated chunks + if((cur_tick % 20) == 0) { + } + } + + @Override + public boolean isModLoaded(String name) { + boolean loaded = ModList.get().isLoaded(name); + if (loaded) { + modsused.add(name); + } + return loaded; + } + @Override + public String getModVersion(String name) { + Optional mod = ModList.get().getModContainerById(name); // Try case sensitive lookup + if (mod.isPresent()) { + ArtifactVersion vi = mod.get().getModInfo().getVersion(); + return vi.getMajorVersion() + "." + vi.getMinorVersion() + "." + vi.getIncrementalVersion(); + } + return null; + } + @Override + public double getServerTPS() { + return tps; + } + + @Override + public String getServerIP() { + if (server.isSingleplayer()) + return "0.0.0.0"; + else + return server.getLocalIp(); + } + @Override + public File getModContainerFile(String name) { + ModFileInfo mfi = LoadingModList.get().getModFileById(name); // Try case sensitive lookup + if (mfi != null) { + File f = mfi.getFile().getFilePath().toFile(); + return f; + } + return null; + } + @Override + public List getModList() { + List mil = LoadingModList.get().getMods(); + List lst = new ArrayList(); + for (ModInfo mi : mil) { + lst.add(mi.getModId()); + } + return lst; + } + + @Override + public Map getBlockIDMap() { + Map map = new HashMap(); + return map; + } + + @Override + public InputStream openResource(String modid, String rname) { + if (modid == null) modid = "minecraft"; + + Optional mc = ModList.get().getModContainerById(modid); + Object mod = (mc.isPresent()) ? mc.get().getMod() : null; + if (mod != null) { + ClassLoader cl = mod.getClass().getClassLoader(); + if (cl == null) cl = ClassLoader.getSystemClassLoader(); + InputStream is = cl.getResourceAsStream(rname); + if (is != null) { + return is; + } + } + List mcl = LoadingModList.get().getMods(); + for (ModInfo mci : mcl) { + mc = ModList.get().getModContainerById(mci.getModId()); + mod = (mc.isPresent()) ? mc.get().getMod() : null; + if (mod == null) continue; + ClassLoader cl = mod.getClass().getClassLoader(); + if (cl == null) cl = ClassLoader.getSystemClassLoader(); + InputStream is = cl.getResourceAsStream(rname); + if (is != null) { + return is; + } + } + return null; + } + /** + * Get block unique ID map (module:blockid) + */ + @Override + public Map getBlockUniqueIDMap() { + HashMap map = new HashMap(); + return map; + } + /** + * Get item unique ID map (module:itemid) + */ + @Override + public Map getItemUniqueIDMap() { + HashMap map = new HashMap(); + return map; + } + + } + private static final Gson gson = new GsonBuilder().create(); + + public class TexturesPayload { + public long timestamp; + public String profileId; + public String profileName; + public boolean isPublic; + public Map textures; + + } + public class ProfileTexture { + public String url; + } + + /** + * Player access abstraction class + */ + public class ForgePlayer extends ForgeCommandSender implements DynmapPlayer + { + private ServerPlayer player; + private final String skinurl; + private final UUID uuid; + + + public ForgePlayer(ServerPlayer p) + { + player = p; + String url = null; + if (player != null) { + uuid = player.getUUID(); + GameProfile prof = player.getGameProfile(); + if (prof != null) { + Property textureProperty = Iterables.getFirst(prof.getProperties().get("textures"), null); + + if (textureProperty != null) { + TexturesPayload result = null; + try { + String json = new String(Base64.getDecoder().decode(textureProperty.getValue()), StandardCharsets.UTF_8); + result = gson.fromJson(json, TexturesPayload.class); + } catch (JsonParseException e) { + } + if ((result != null) && (result.textures != null) && (result.textures.containsKey("SKIN"))) { + url = result.textures.get("SKIN").url; + } + } + } + } + else { + uuid = null; + } + skinurl = url; + } + @Override + public boolean isConnected() + { + return true; + } + @Override + public String getName() + { + if(player != null) { + String n = player.getName().getString();; + return n; + } + else + return "[Server]"; + } + @Override + public String getDisplayName() + { + if(player != null) { + String n = player.getDisplayName().getString(); + return n; + } + else + return "[Server]"; + } + @Override + public boolean isOnline() + { + return true; + } + @Override + public DynmapLocation getLocation() + { + if (player == null) { + return null; + } + Vec3 v = player.position(); + return toLoc(player.getLevel(), v.x, v.y, v.z); + } + @Override + public String getWorld() + { + if (player == null) + { + return null; + } + + if (player.level != null) + { + return DynmapPlugin.this.getWorld((ServerLevel)player.level).getName(); + } + + return null; + } + public static final Connection getNetworkManager(ServerGamePacketListenerImpl nh) { + return nh.connection; + } + + @Override + public InetSocketAddress getAddress() + { + if((player != null) && (player instanceof ServerPlayer)) { + ServerGamePacketListenerImpl nsh = ((ServerPlayer)player).connection; + if((nsh != null) && (getNetworkManager(nsh) != null)) { + SocketAddress sa = getNetworkManager(nsh).getRemoteAddress(); + if(sa instanceof InetSocketAddress) { + return (InetSocketAddress)sa; + } + } + } + return null; + } + @Override + public boolean isSneaking() + { + if (player != null) + { + return player.getPose() == Pose.CROUCHING; + } + + return false; + } + @Override + public double getHealth() + { + if (player != null) + { + double h = player.getHealth(); + if(h > 20) h = 20; + return h; // Scale to 20 range + } + else + { + return 0; + } + } + @Override + public int getArmorPoints() + { + if (player != null) + { + return player.getArmorValue(); + } + else + { + return 0; + } + } + @Override + public DynmapLocation getBedSpawnLocation() + { + return null; + } + @Override + public long getLastLoginTime() + { + return 0; + } + @Override + public long getFirstLoginTime() + { + return 0; + } + @Override + public boolean hasPrivilege(String privid) + { + if(player != null) + return hasPerm(player, privid); + return false; + } + @Override + public boolean isOp() + { + return DynmapPlugin.this.isOp(player.getName().getString()); + } + @Override + public void sendMessage(String msg) + { + Component ichatcomponent = Component.literal(msg); + player.sendSystemMessage(ichatcomponent); + } + @Override + public boolean isInvisible() { + if(player != null) { + return player.isInvisible(); + } + return false; + } + @Override + public int getSortWeight() { + Integer wt = sortWeights.get(getName()); + if (wt != null) + return wt; + return 0; + } + @Override + public void setSortWeight(int wt) { + if (wt == 0) { + sortWeights.remove(getName()); + } + else { + sortWeights.put(getName(), wt); + } + } + @Override + public boolean hasPermissionNode(String node) { + if(player != null) + return hasPermNode(player, node); + return false; + } + @Override + public String getSkinURL() { + return skinurl; + } + @Override + public UUID getUUID() { + return uuid; + } + /** + * Send title and subtitle text (called from server thread) + */ + @Override + public void sendTitleText(String title, String subtitle, int fadeInTicks, int stayTicks, int fadeOutTicks) { + if (player instanceof ServerPlayer) { + ServerPlayer mp = (ServerPlayer) player; + ClientboundSetTitlesAnimationPacket times = new ClientboundSetTitlesAnimationPacket(fadeInTicks, stayTicks, fadeOutTicks); + mp.connection.send(times); + if (title != null) { + ClientboundSetTitleTextPacket titlepkt = new ClientboundSetTitleTextPacket(Component.literal(title)); + mp.connection.send(titlepkt); + } + + if (subtitle != null) { + ClientboundSetSubtitleTextPacket subtitlepkt = new ClientboundSetSubtitleTextPacket(Component.literal(subtitle)); + mp.connection.send(subtitlepkt); + } + } + } + } + /* Handler for generic console command sender */ + public class ForgeCommandSender implements DynmapCommandSender + { + private CommandSourceStack sender; + + protected ForgeCommandSender() { + sender = null; + } + + public ForgeCommandSender(CommandSourceStack send) + { + sender = send; + } + + @Override + public boolean hasPrivilege(String privid) + { + return true; + } + + @Override + public void sendMessage(String msg) + { + if(sender != null) { + Component ichatcomponent = Component.literal(msg); + sender.sendSuccess(ichatcomponent, true); + } + } + + @Override + public boolean isConnected() + { + return false; + } + @Override + public boolean isOp() + { + return true; + } + @Override + public boolean hasPermissionNode(String node) { + return true; + } + } + + public void loadExtraBiomes(String mcver) { + int cnt = 0; + BiomeMap.loadWellKnownByVersion(mcver); + + Biome[] list = getBiomeList(); + + for (int i = 0; i < list.length; i++) { + Biome bb = list[i]; + if (bb != null) { + ResourceLocation regid = getBiomeReg().getKey(bb); + String id = regid.getPath(); + String rl = regid.toString(); + float tmp = bb.getBaseTemperature(), hum = bb.getDownfall(); + int watermult = bb.getWaterColor(); + Log.verboseinfo("biome[" + i + "]: hum=" + hum + ", tmp=" + tmp + ", mult=" + Integer.toHexString(watermult)); + + BiomeMap bmap = BiomeMap.NULL; + if (rl != null) { // If resource location, lookup by this + bmap = BiomeMap.byBiomeResourceLocation(rl); + } + else { + bmap = BiomeMap.byBiomeID(i); + } + if (bmap.isDefault() || (bmap == BiomeMap.NULL)) { + bmap = new BiomeMap((rl != null) ? BiomeMap.NO_INDEX : i, id, tmp, hum, rl); + Log.verboseinfo("Add custom biome [" + bmap.toString() + "] (" + i + ")"); + cnt++; + } + else { + bmap.setTemperature(tmp); + bmap.setRainfall(hum); + } + if (watermult != -1) { + bmap.setWaterColorMultiplier(watermult); + Log.verboseinfo("Set watercolormult for " + bmap.toString() + " (" + i + ") to " + Integer.toHexString(watermult)); + } + } + } + if(cnt > 0) + Log.info("Added " + cnt + " custom biome mappings"); + } + + private String[] getBiomeNames() { + Biome[] list = getBiomeList(); + String[] lst = new String[list.length]; + for(int i = 0; i < list.length; i++) { + Biome bb = list[i]; + if (bb != null) { + lst[i] = bb.toString(); + } + } + return lst; + } + + public void onEnable() + { + /* Get MC version */ + String mcver = server.getServerVersion(); + /* Load extra biomes */ + loadExtraBiomes(mcver); + /* Set up player login/quit event handler */ + registerPlayerLoginListener(); + + /* Initialize permissions handler */ + permissions = FilePermissions.create(); + if(permissions == null) { + permissions = new OpPermissions(new String[] { "webchat", "marker.icons", "marker.list", "webregister", "stats", "hide.self", "show.self" }); + } + /* Get and initialize data folder */ + File dataDirectory = new File("dynmap"); + + if (dataDirectory.exists() == false) + { + dataDirectory.mkdirs(); + } + + /* Instantiate core */ + if (core == null) + { + core = new DynmapCore(); + } + + /* Inject dependencies */ + core.setPluginJarFile(DynmapMod.jarfile); + core.setPluginVersion(DynmapMod.ver); + core.setMinecraftVersion(mcver); + core.setDataFolder(dataDirectory); + core.setServer(fserver); + core.setTriggerDefault(TRIGGER_DEFAULTS); + core.setBiomeNames(getBiomeNames()); + + if(!core.initConfiguration(null)) + { + return; + } + // Extract default permission example, if needed + File filepermexample = new File(core.getDataFolder(), "permissions.yml.example"); + core.createDefaultFileFromResource("/permissions.yml.example", filepermexample); + + DynmapCommonAPIListener.apiInitialized(core); + } + + private static int test(CommandSource source) throws CommandSyntaxException + { + Log.warning(source.toString()); + return 1; + } + + private DynmapCommand dynmapCmd; + private DmapCommand dmapCmd; + private DmarkerCommand dmarkerCmd; + private DynmapExpCommand dynmapexpCmd; + + public void onStarting(CommandDispatcher cd) { + /* Register command hander */ + dynmapCmd = new DynmapCommand(this); + dmapCmd = new DmapCommand(this); + dmarkerCmd = new DmarkerCommand(this); + dynmapexpCmd = new DynmapExpCommand(this); + dynmapCmd.register(cd); + dmapCmd.register(cd); + dmarkerCmd.register(cd); + dynmapexpCmd.register(cd); + + Log.info("Register commands"); + } + + public void onStart() { + initializeBlockStates(); + /* Enable core */ + if (!core.enableCore(null)) + { + return; + } + core_enabled = true; + VersionCheck.runCheck(core); + // Get per tick time limit + perTickLimit = core.getMaxTickUseMS() * 1000000; + // Prep TPS + lasttick = System.nanoTime(); + tps = 20.0; + + /* Register tick handler */ + if(!tickregistered) { + MinecraftForge.EVENT_BUS.register(fserver); + tickregistered = true; + } + + playerList = core.playerList; + sscache = new GenericChunkCache(core.getSnapShotCacheSize(), core.useSoftRefInSnapShotCache()); + /* Get map manager from core */ + mapManager = core.getMapManager(); + + /* Load saved world definitions */ + loadWorlds(); + + /* Initialized the currently loaded worlds */ + for (ServerLevel world : server.getAllLevels()) { + ForgeWorld w = this.getWorld(world); + } + for(ForgeWorld w : worlds.values()) { + if (core.processWorldLoad(w)) { /* Have core process load first - fire event listeners if good load after */ + if(w.isLoaded()) { + core.listenerManager.processWorldEvent(EventType.WORLD_LOAD, w); + } + } + } + core.updateConfigHashcode(); + + /* Register our update trigger events */ + registerEvents(); + Log.info("Register events"); + + //DynmapCommonAPIListener.apiInitialized(core); + + Log.info("Enabled"); + } + + public void onDisable() + { + DynmapCommonAPIListener.apiTerminated(); + + //if (metrics != null) { + // metrics.stop(); + // metrics = null; + //} + /* Save worlds */ + saveWorlds(); + + /* Purge tick queue */ + fserver.runqueue.clear(); + + /* Disable core */ + core.disableCore(); + core_enabled = false; + + if (sscache != null) + { + sscache.cleanup(); + sscache = null; + } + + Log.info("Disabled"); + } + + void onCommand(CommandSourceStack commandSourceStack, String cmd, String[] args) + { + DynmapCommandSender dsender; + ServerPlayer psender; + try { + psender = commandSourceStack.getPlayerOrException(); + } catch (com.mojang.brigadier.exceptions.CommandSyntaxException x) { + psender = null; + } + + if (psender != null) + { + dsender = new ForgePlayer(psender); + } + else + { + dsender = new ForgeCommandSender(commandSourceStack); + } + try { + core.processCommand(dsender, cmd, cmd, args); + } catch (Exception x) { + dsender.sendMessage("Command internal error: " + x.getMessage()); + Log.severe("Error with command: " + cmd + Arrays.deepToString(args), x); + } + } + + private DynmapLocation toLoc(ServerLevel level, double x, double y, double z) + { + return new DynmapLocation(DynmapPlugin.this.getWorld(level).getName(), x, y, z); + } + + public class PlayerTracker { + @SubscribeEvent + public void onPlayerLogin(PlayerLoggedInEvent event) { + if(!core_enabled) return; + final DynmapPlayer dp = getOrAddPlayer((ServerPlayer)event.getPlayer()); + /* This event can be called from off server thread, so push processing there */ + core.getServer().scheduleServerTask(new Runnable() { + public void run() { + core.listenerManager.processPlayerEvent(EventType.PLAYER_JOIN, dp); + } + }, 2); + } + @SubscribeEvent + public void onPlayerLogout(PlayerLoggedOutEvent event) { + if(!core_enabled) return; + final DynmapPlayer dp = getOrAddPlayer((ServerPlayer)event.getPlayer()); + final String name = event.getPlayer().getName().getString(); + /* This event can be called from off server thread, so push processing there */ + core.getServer().scheduleServerTask(new Runnable() { + public void run() { + core.listenerManager.processPlayerEvent(EventType.PLAYER_QUIT, dp); + players.remove(name); + } + }, 0); + } + @SubscribeEvent + public void onPlayerChangedDimension(PlayerChangedDimensionEvent event) { + if(!core_enabled) return; + getOrAddPlayer((ServerPlayer)event.getPlayer()); // Freshen player object reference + } + @SubscribeEvent + public void onPlayerRespawn(PlayerRespawnEvent event) { + if(!core_enabled) return; + getOrAddPlayer((ServerPlayer)event.getPlayer()); // Freshen player object reference + } + } + private PlayerTracker playerTracker = null; + + private void registerPlayerLoginListener() + { + if (playerTracker == null) { + playerTracker = new PlayerTracker(); + MinecraftForge.EVENT_BUS.register(playerTracker); + } + } + + public class WorldTracker { + @SubscribeEvent(priority=EventPriority.LOWEST) + public void handleWorldLoad(WorldEvent.Load event) { + if(!core_enabled) return; + LevelAccessor w = event.getWorld(); + if(!(w instanceof ServerLevel)) return; + final ForgeWorld fw = getWorld((ServerLevel)w); + // This event can be called from off server thread, so push processing there + core.getServer().scheduleServerTask(new Runnable() { + public void run() { + if(core.processWorldLoad(fw)) // Have core process load first - fire event listeners if good load after + core.listenerManager.processWorldEvent(EventType.WORLD_LOAD, fw); + } + }, 0); + } + @SubscribeEvent(priority=EventPriority.LOWEST) + public void handleWorldUnload(WorldEvent.Unload event) { + if(!core_enabled) return; + LevelAccessor w = event.getWorld(); + if(!(w instanceof ServerLevel)) return; + final ForgeWorld fw = getWorld((ServerLevel)w); + if(fw != null) { + // This event can be called from off server thread, so push processing there + core.getServer().scheduleServerTask(new Runnable() { + public void run() { + core.listenerManager.processWorldEvent(EventType.WORLD_UNLOAD, fw); + core.processWorldUnload(fw); + } + }, 0); + // Set world unloaded (needs to be immediate, since it may be invalid after event) + fw.setWorldUnloaded(); + // Clean up tracker + //WorldUpdateTracker wut = updateTrackers.remove(fw.getName()); + //if(wut != null) wut.world = null; + } + } + + @SubscribeEvent(priority=EventPriority.LOWEST) + public void handleChunkLoad(ChunkEvent.Load event) { + if(!onchunkgenerate) return; + + LevelAccessor w = event.getWorld(); + if(!(w instanceof ServerLevel)) return; + ChunkAccess c = event.getChunk(); + if ((c != null) && (c.getStatus() == ChunkStatus.FULL) && (c instanceof LevelChunk)) { + ForgeWorld fw = getWorld((ServerLevel)w, false); + if (fw != null) { + addKnownChunk(fw, c.getPos()); + } + } + } + @SubscribeEvent(priority=EventPriority.LOWEST) + public void handleChunkUnload(ChunkEvent.Unload event) { + if(!onchunkgenerate) return; + + LevelAccessor w = event.getWorld(); + if(!(w instanceof ServerLevel)) return; + ChunkAccess c = event.getChunk(); + if (c != null) { + ForgeWorld fw = getWorld((ServerLevel)w, false); + ChunkPos cp = c.getPos(); + if (fw != null) { + if (!checkIfKnownChunk(fw, cp)) { + int ymax = Integer.MIN_VALUE; + int ymin = Integer.MAX_VALUE; + LevelChunkSection[] sections = c.getSections(); + for(int i = 0; i < sections.length; i++) { + if((sections[i] != null) && (sections[i].hasOnlyAir() == false)) { + int sy = sections[i].bottomBlockY(); + if (sy < ymin) ymin = sy; + if ((sy+16) > ymax) ymax = sy + 16; + } + } + int x = cp.x << 4; + int z = cp.z << 4; + // If not empty AND not initial scan + if (ymax != Integer.MIN_VALUE) { + //Log.info(String.format("chunkkeyerate(unload)(%s,%d,%d,%d,%d,%d,%s)", fw.getName(), x, ymin, z, x+15, ymax, z+15)); + mapManager.touchVolume(fw.getName(), x, ymin, z, x+15, ymax, z+15, "chunkgenerate"); + } + } + removeKnownChunk(fw, cp); + } + } + } + @SubscribeEvent(priority=EventPriority.LOWEST) + public void handleChunkDataSave(ChunkDataEvent.Save event) { + if(!onchunkgenerate) return; + + LevelAccessor w = event.getWorld(); + if(!(w instanceof ServerLevel)) return; + ChunkAccess c = event.getChunk(); + if (c != null) { + ForgeWorld fw = getWorld((ServerLevel)w, false); + ChunkPos cp = c.getPos(); + if (fw != null) { + if (!checkIfKnownChunk(fw, cp)) { + int ymax = Integer.MIN_VALUE; + int ymin = Integer.MAX_VALUE; + LevelChunkSection[] sections = c.getSections(); + for(int i = 0; i < sections.length; i++) { + if((sections[i] != null) && (sections[i].hasOnlyAir() == false)) { + int sy = sections[i].bottomBlockY(); + if (sy < ymin) ymin = sy; + if ((sy+16) > ymax) ymax = sy + 16; + } + } + int x = cp.x << 4; + int z = cp.z << 4; + // If not empty AND not initial scan + if (ymax != Integer.MIN_VALUE) { + //Log.info(String.format("chunkkeyerate(save)(%s,%d,%d,%d,%d,%d,%s)", fw.getName(), x, ymin, z, x+15, ymax, z+15)); + mapManager.touchVolume(fw.getName(), x, ymin, z, x+15, ymax, z+15, "chunkgenerate"); + } + // If cooked, add to known + if ((c.getStatus() == ChunkStatus.FULL) && (c instanceof LevelChunk)) { + addKnownChunk(fw, cp); + } + } + } + } + } + @SubscribeEvent(priority=EventPriority.LOWEST) + public void handleBlockEvent(BlockEvent event) { + if(!core_enabled) return; + if(!onblockchange) return; + BlockUpdateRec r = new BlockUpdateRec(); + r.w = event.getWorld(); + if(!(r.w instanceof ServerLevel)) return; // band-aid to prevent errors in unsupported 'running in client' scenario + ForgeWorld fw = getWorld((ServerLevel)r.w, false); + if (fw == null) return; + r.wid = fw.getName(); + BlockPos p = event.getPos(); + r.x = p.getX(); + r.y = p.getY(); + r.z = p.getZ(); + blockupdatequeue.add(r); + } + } + private WorldTracker worldTracker = null; + private boolean onblockchange = false; + private boolean onchunkpopulate = false; + private boolean onchunkgenerate = false; + private boolean onblockchange_with_id = false; + + private void registerEvents() + { + // To trigger rendering. + onblockchange = core.isTrigger("blockupdate"); + onchunkpopulate = core.isTrigger("chunkpopulate"); + onchunkgenerate = core.isTrigger("chunkgenerate"); + onblockchange_with_id = core.isTrigger("blockupdate-with-id"); + if(onblockchange_with_id) + onblockchange = true; + if ((worldTracker == null) && (onblockchange || onchunkpopulate || onchunkgenerate)) { + worldTracker = new WorldTracker(); + MinecraftForge.EVENT_BUS.register(worldTracker); + } + // Prime the known full chunks + if (onchunkgenerate && (server.getAllLevels() != null)) { + for (ServerLevel world : server.getAllLevels()) { + ForgeWorld fw = getWorld(world); + if (fw == null) continue; + Long2ObjectLinkedOpenHashMap chunks = world.getChunkSource().chunkMap.visibleChunkMap; + for (Entry k : chunks.long2ObjectEntrySet()) { + long key = k.getKey().longValue(); + ChunkHolder ch = k.getValue(); + ChunkAccess c = null; + try { + c = ch.getLastAvailable(); + } catch (Exception x) { } + if (c == null) continue; + ChunkStatus cs = c.getStatus(); + ChunkPos pos = ch.getPos(); + if (cs == ChunkStatus.FULL) { // Cooked? + // Add it as known + addKnownChunk(fw, pos); + } + } + } + } + } + + private ForgeWorld getWorldByName(String name) { + return worlds.get(name); + } + + private ForgeWorld getWorld(ServerLevel w) { + return getWorld(w, true); + } + + private ForgeWorld getWorld(ServerLevel w, boolean add_if_not_found) { + if(last_world == w) { + return last_fworld; + } + String wname = ForgeWorld.getWorldName(w); + + for(ForgeWorld fw : worlds.values()) { + if(fw.getRawName().equals(wname)) { + last_world = w; + last_fworld = fw; + if(fw.isLoaded() == false) { + fw.setWorldLoaded(w); + } + fw.updateWorld(w); + return fw; + } + } + ForgeWorld fw = null; + if(add_if_not_found) { + /* Add to list if not found */ + fw = new ForgeWorld(w); + worlds.put(fw.getName(), fw); + } + last_world = w; + last_fworld = fw; + return fw; + } + + private void saveWorlds() { + File f = new File(core.getDataFolder(), "forgeworlds.yml"); + ConfigurationNode cn = new ConfigurationNode(f); + ArrayList> lst = new ArrayList>(); + for(DynmapWorld fw : core.mapManager.getWorlds()) { + HashMap vals = new HashMap(); + vals.put("name", fw.getRawName()); + vals.put("height", fw.worldheight); + vals.put("miny", fw.minY); + vals.put("sealevel", fw.sealevel); + vals.put("nether", fw.isNether()); + vals.put("the_end", ((ForgeWorld)fw).isTheEnd()); + vals.put("title", fw.getTitle()); + lst.add(vals); + } + cn.put("worlds", lst); + cn.put("useSaveFolderAsName", useSaveFolder); + cn.put("maxWorldHeight", ForgeWorld.getMaxWorldHeight()); + + cn.save(); + } + private void loadWorlds() { + File f = new File(core.getDataFolder(), "forgeworlds.yml"); + if(f.canRead() == false) { + useSaveFolder = true; + return; + } + ConfigurationNode cn = new ConfigurationNode(f); + cn.load(); + // If defined, use maxWorldHeight + ForgeWorld.setMaxWorldHeight(cn.getInteger("maxWorldHeight", 256)); + + // If setting defined, use it + if (cn.containsKey("useSaveFolderAsName")) { + useSaveFolder = cn.getBoolean("useSaveFolderAsName", useSaveFolder); + } + List> lst = cn.getMapList("worlds"); + if(lst == null) { + Log.warning("Discarding bad forgeworlds.yml"); + return; + } + + for(Map world : lst) { + try { + String name = (String)world.get("name"); + int height = (Integer)world.get("height"); + Integer miny = (Integer) world.get("miny"); + int sealevel = (Integer)world.get("sealevel"); + boolean nether = (Boolean)world.get("nether"); + boolean theend = (Boolean)world.get("the_end"); + String title = (String)world.get("title"); + if(name != null) { + ForgeWorld fw = new ForgeWorld(name, height, sealevel, nether, theend, title, (miny != null) ? miny : 0); + fw.setWorldUnloaded(); + core.processWorldLoad(fw); + worlds.put(fw.getName(), fw); + } + } catch (Exception x) { + Log.warning("Unable to load saved worlds from forgeworlds.yml"); + return; + } + } + } + public void serverStarted() { + this.onStart(); + if (core != null) { + core.serverStarted(); + } + } + public MinecraftServer getMCServer() { + return server; + } +} + +class DynmapCommandHandler +{ + private String cmd; + private DynmapPlugin plugin; + + public DynmapCommandHandler(String cmd, DynmapPlugin p) + { + this.cmd = cmd; + this.plugin = p; + } + + public void register(CommandDispatcher cd) { + cd.register(Commands.literal(cmd). + then(RequiredArgumentBuilder. argument("args", StringArgumentType.greedyString()). + executes((ctx) -> this.execute(plugin.getMCServer(), ctx.getSource(), ctx.getInput()))). + executes((ctx) -> this.execute(plugin.getMCServer(), ctx.getSource(), ctx.getInput()))); + } + +// @Override + public int execute(MinecraftServer server, CommandSourceStack commandSourceStack, + String cmdline) { + String[] args = cmdline.split("\\s+"); + plugin.onCommand(commandSourceStack, cmd, Arrays.copyOfRange(args, 1, args.length)); + return 1; + } + +// @Override + public String getUsage(CommandSource arg0) { + return "Run /" + cmd + " help for details on using command"; + } +} + +class DynmapCommand extends DynmapCommandHandler { + DynmapCommand(DynmapPlugin p) { + super("dynmap", p); + } +} +class DmapCommand extends DynmapCommandHandler { + DmapCommand(DynmapPlugin p) { + super("dmap", p); + } +} +class DmarkerCommand extends DynmapCommandHandler { + DmarkerCommand(DynmapPlugin p) { + super("dmarker", p); + } +} +class DynmapExpCommand extends DynmapCommandHandler { + DynmapExpCommand(DynmapPlugin p) { + super("dynmapexp", p); + } +} + diff --git a/forge-1.19/src/main/java/org/dynmap/forge_1_19/ForgeMapChunkCache.java b/forge-1.19/src/main/java/org/dynmap/forge_1_19/ForgeMapChunkCache.java new file mode 100644 index 00000000..7231843b --- /dev/null +++ b/forge-1.19/src/main/java/org/dynmap/forge_1_19/ForgeMapChunkCache.java @@ -0,0 +1,90 @@ +package org.dynmap.forge_1_19; + +import java.util.List; +import java.util.NoSuchElementException; + +import org.dynmap.DynmapChunk; +import org.dynmap.Log; +import org.dynmap.common.chunk.GenericChunk; +import org.dynmap.common.chunk.GenericChunkCache; +import org.dynmap.common.chunk.GenericMapChunkCache; + +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerChunkCache; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.level.ChunkPos; +import net.minecraft.world.level.chunk.ChunkAccess; +import net.minecraft.world.level.chunk.ChunkStatus; +import net.minecraft.world.level.chunk.storage.ChunkSerializer; + +/** + * Container for managing chunks - dependent upon using chunk snapshots, since + * rendering is off server thread + */ +public class ForgeMapChunkCache extends GenericMapChunkCache { + private ServerLevel w; + private ServerChunkCache cps; + /** + * Construct empty cache + */ + public ForgeMapChunkCache(GenericChunkCache cc) { + super(cc); + } + + // Load generic chunk from existing and already loaded chunk + protected GenericChunk getLoadedChunk(DynmapChunk chunk) { + GenericChunk gc = null; + ChunkAccess ch = cps.getChunk(chunk.x, chunk.z, ChunkStatus.FULL, false); + if (ch != null) { + CompoundTag nbt = ChunkSerializer.write(w, ch); + if (nbt != null) { + gc = parseChunkFromNBT(new NBT.NBTCompound(nbt)); + } + } + return gc; + } + // Load generic chunk from unloaded chunk + protected GenericChunk loadChunk(DynmapChunk chunk) { + GenericChunk gc = null; + CompoundTag nbt = readChunk(chunk.x, chunk.z); + // If read was good + if (nbt != null) { + gc = parseChunkFromNBT(new NBT.NBTCompound(nbt)); + } + return gc; + } + + public void setChunks(ForgeWorld dw, List chunks) { + this.w = dw.getWorld(); + if (dw.isLoaded()) { + /* Check if world's provider is ServerChunkProvider */ + cps = this.w.getChunkSource(); + } + super.setChunks(dw, chunks); + } + + private CompoundTag readChunk(int x, int z) { + try { + CompoundTag rslt = cps.chunkMap.readChunk(new ChunkPos(x, z)).join().get(); + if (rslt.contains("Level")) { + rslt = rslt.getCompound("Level"); + } + // Don't load uncooked chunks + String stat = rslt.getString("Status"); + ChunkStatus cs = ChunkStatus.byName(stat); + if ((stat == null) || + // Needs to be at least lighted + (!cs.isOrAfter(ChunkStatus.LIGHT))) { + rslt = null; + } + // Log.info(String.format("loadChunk(%d,%d)=%s", x, z, (rslt != null) ? + // rslt.toString() : "null")); + return rslt; + } catch (NoSuchElementException nsex) { + return null; + } catch (Exception exc) { + Log.severe(String.format("Error reading chunk: %s,%d,%d", dw.getName(), x, z), exc); + return null; + } + } +} diff --git a/forge-1.19/src/main/java/org/dynmap/forge_1_19/ForgeWorld.java b/forge-1.19/src/main/java/org/dynmap/forge_1_19/ForgeWorld.java new file mode 100644 index 00000000..02ea2f64 --- /dev/null +++ b/forge-1.19/src/main/java/org/dynmap/forge_1_19/ForgeWorld.java @@ -0,0 +1,249 @@ +package org.dynmap.forge_1_19; +/** + * Forge specific implementation of DynmapWorld + */ +import java.util.List; + +import net.minecraft.world.level.ServerLevelAccessor; +import net.minecraft.world.level.border.WorldBorder; +import net.minecraft.world.level.levelgen.Heightmap; +import net.minecraft.core.BlockPos; +import net.minecraft.resources.ResourceKey; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LightLayer; + +import org.dynmap.DynmapChunk; +import org.dynmap.DynmapLocation; +import org.dynmap.DynmapWorld; +import org.dynmap.utils.MapChunkCache; +import org.dynmap.utils.Polygon; + +public class ForgeWorld extends DynmapWorld +{ + private ServerLevelAccessor world; + private final boolean skylight; + private final boolean isnether; + private final boolean istheend; + private final String env; + private DynmapLocation spawnloc = new DynmapLocation(); + private static int maxWorldHeight = 320; // Maximum allows world height + + public static int getMaxWorldHeight() { + return maxWorldHeight; + } + public static void setMaxWorldHeight(int h) { + maxWorldHeight = h; + } + + public static String getWorldName(ServerLevelAccessor w) { + ResourceKey rk = w.getLevel().dimension(); + String id = rk.location().getNamespace() + "_" + rk.location().getPath(); + if (id.equals("minecraft_overworld")) { // Overworld? + return w.getLevel().serverLevelData.getLevelName(); + } + else if (id.equals("minecraft_the_end")) { + return "DIM1"; + } + else if (id.equals("minecraft_the_nether")) { + return "DIM-1"; + } + else { + return id; + } + } + + public void updateWorld(ServerLevelAccessor w) { + this.updateWorldHeights(w.getLevel().getHeight(), w.getLevel().dimensionType().minY(), w.getLevel().getSeaLevel()); + } + + public ForgeWorld(ServerLevelAccessor w) + { + this(getWorldName(w), + w.getLevel().getHeight(), + w.getLevel().getSeaLevel(), + w.getLevel().dimension() == Level.NETHER, + w.getLevel().dimension() == Level.END, + getWorldName(w), + w.getLevel().dimensionType().minY()); + setWorldLoaded(w); + } + public ForgeWorld(String name, int height, int sealevel, boolean nether, boolean the_end, String deftitle, int miny) + { + super(name, (height > maxWorldHeight)?maxWorldHeight:height, sealevel, miny); + world = null; + setTitle(deftitle); + isnether = nether; + istheend = the_end; + skylight = !(isnether || istheend); + + if (isnether) + { + env = "nether"; + } + else if (istheend) + { + env = "the_end"; + } + else + { + env = "normal"; + } + //Log.info(getName() + ": skylight=" + skylight + ", height=" + this.worldheight + ", isnether=" + isnether + ", istheend=" + istheend); + } + /* Test if world is nether */ + @Override + public boolean isNether() + { + return isnether; + } + public boolean isTheEnd() + { + return istheend; + } + /* Get world spawn location */ + @Override + public DynmapLocation getSpawnLocation() + { + if(world != null) { + BlockPos p = world.getLevel().getSharedSpawnPos(); + spawnloc.x = p.getX(); + spawnloc.y = p.getY(); + spawnloc.z = p.getZ(); + spawnloc.world = this.getName(); + } + return spawnloc; + } + /* Get world time */ + @Override + public long getTime() + { + if(world != null) + return world.getLevel().getDayTime(); + else + return -1; + } + /* World is storming */ + @Override + public boolean hasStorm() + { + if(world != null) + return world.getLevel().isRaining(); + else + return false; + } + /* World is thundering */ + @Override + public boolean isThundering() + { + if(world != null) + return world.getLevel().isThundering(); + else + return false; + } + /* World is loaded */ + @Override + public boolean isLoaded() + { + return (world != null); + } + /* Set world to unloaded */ + @Override + public void setWorldUnloaded() + { + getSpawnLocation(); + world = null; + } + /* Set world to loaded */ + public void setWorldLoaded(ServerLevelAccessor w) { + world = w; + this.sealevel = w.getLevel().getSeaLevel(); // Read actual current sealevel from world + // Update lighting table + for (int i = 0; i < 16; i++) { + // Algorithm based on LightmapTextureManager.getBrightness() + // We can't call that method because it's client-only. + // This means the code below can stop being correct if Mojang ever + // updates the curve; in that case we should reflect the changes. + float value = (float) i / 15.0f; + float brightness = value / (4.0f - 3.0f * value); + this.setBrightnessTableEntry(i, brightness); + //Log.info(getName() + ": light " + i + " = " + light); + } + } + /* Get light level of block */ + @Override + public int getLightLevel(int x, int y, int z) + { + if(world != null) + return world.getLevel().getLightEngine().getRawBrightness(new BlockPos(x, y, z), 0); + else + return -1; + } + /* Get highest Y coord of given location */ + @Override + public int getHighestBlockYAt(int x, int z) + { + if(world != null) { + return world.getLevel().getChunk(x >> 4, z >> 4).getHeight(Heightmap.Types.MOTION_BLOCKING, x & 15, z & 15); + } + else + return -1; + } + /* Test if sky light level is requestable */ + @Override + public boolean canGetSkyLightLevel() + { + return skylight; + } + /* Return sky light level */ + @Override + public int getSkyLightLevel(int x, int y, int z) + { + if(world != null) { + return world.getLevel().getBrightness(LightLayer.SKY, new BlockPos(x, y, z)); + } + else + return -1; + } + /** + * Get world environment ID (lower case - normal, the_end, nether) + */ + @Override + public String getEnvironment() + { + return env; + } + /** + * Get map chunk cache for world + */ + @Override + public MapChunkCache getChunkCache(List chunks) + { + if (world != null) { + ForgeMapChunkCache c = new ForgeMapChunkCache(DynmapPlugin.plugin.sscache); + c.setChunks(this, chunks); + return c; + } + return null; + } + + public ServerLevel getWorld() + { + return world.getLevel(); + } + @Override + public Polygon getWorldBorder() { + if (world != null) { + WorldBorder wb = world.getWorldBorder(); + if ((wb != null) && (wb.getSize() < 5.9E7)) { + Polygon p = new Polygon(); + p.addVertex(wb.getMinX(), wb.getMinZ()); + p.addVertex(wb.getMinX(), wb.getMaxZ()); + p.addVertex(wb.getMaxX(), wb.getMaxZ()); + p.addVertex(wb.getMaxX(), wb.getMinZ()); + return p; + } + } + return null; + } +} diff --git a/forge-1.19/src/main/java/org/dynmap/forge_1_19/NBT.java b/forge-1.19/src/main/java/org/dynmap/forge_1_19/NBT.java new file mode 100644 index 00000000..aad82091 --- /dev/null +++ b/forge-1.19/src/main/java/org/dynmap/forge_1_19/NBT.java @@ -0,0 +1,126 @@ +package org.dynmap.forge_1_19; + +import org.dynmap.common.chunk.GenericBitStorage; +import org.dynmap.common.chunk.GenericNBTCompound; +import org.dynmap.common.chunk.GenericNBTList; + +import java.util.Set; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.ListTag; +import net.minecraft.util.SimpleBitStorage; + +public class NBT { + + public static class NBTCompound implements GenericNBTCompound { + private final CompoundTag obj; + public NBTCompound(CompoundTag t) { + this.obj = t; + } + @Override + public Set getAllKeys() { + return obj.getAllKeys(); + } + @Override + public boolean contains(String s) { + return obj.contains(s); + } + @Override + public boolean contains(String s, int i) { + return obj.contains(s, i); + } + @Override + public byte getByte(String s) { + return obj.getByte(s); + } + @Override + public short getShort(String s) { + return obj.getShort(s); + } + @Override + public int getInt(String s) { + return obj.getInt(s); + } + @Override + public long getLong(String s) { + return obj.getLong(s); + } + @Override + public float getFloat(String s) { + return obj.getFloat(s); + } + @Override + public double getDouble(String s) { + return obj.getDouble(s); + } + @Override + public String getString(String s) { + return obj.getString(s); + } + @Override + public byte[] getByteArray(String s) { + return obj.getByteArray(s); + } + @Override + public int[] getIntArray(String s) { + return obj.getIntArray(s); + } + @Override + public long[] getLongArray(String s) { + return obj.getLongArray(s); + } + @Override + public GenericNBTCompound getCompound(String s) { + return new NBTCompound(obj.getCompound(s)); + } + @Override + public GenericNBTList getList(String s, int i) { + return new NBTList(obj.getList(s, i)); + } + @Override + public boolean getBoolean(String s) { + return obj.getBoolean(s); + } + @Override + public String getAsString(String s) { + return obj.get(s).getAsString(); + } + @Override + public GenericBitStorage makeBitStorage(int bits, int count, long[] data) { + return new OurBitStorage(bits, count, data); + } + public String toString() { + return obj.toString(); + } + } + public static class NBTList implements GenericNBTList { + private final ListTag obj; + public NBTList(ListTag t) { + obj = t; + } + @Override + public int size() { + return obj.size(); + } + @Override + public String getString(int idx) { + return obj.getString(idx); + } + @Override + public GenericNBTCompound getCompound(int idx) { + return new NBTCompound(obj.getCompound(idx)); + } + public String toString() { + return obj.toString(); + } + } + public static class OurBitStorage implements GenericBitStorage { + private final SimpleBitStorage bs; + public OurBitStorage(int bits, int count, long[] data) { + bs = new SimpleBitStorage(bits, count, data); + } + @Override + public int get(int idx) { + return bs.get(idx); + } + } +} diff --git a/forge-1.19/src/main/java/org/dynmap/forge_1_19/Proxy.java b/forge-1.19/src/main/java/org/dynmap/forge_1_19/Proxy.java new file mode 100644 index 00000000..c2b6ee29 --- /dev/null +++ b/forge-1.19/src/main/java/org/dynmap/forge_1_19/Proxy.java @@ -0,0 +1,24 @@ +package org.dynmap.forge_1_19; + +import net.minecraft.server.MinecraftServer; + +/** + * Server side proxy - methods for creating and cleaning up plugin + */ +public class Proxy +{ + public Proxy() + { + } + public DynmapPlugin startServer(MinecraftServer srv) { + DynmapPlugin plugin = DynmapPlugin.plugin; + if (plugin == null) { + plugin = new DynmapPlugin(srv); + plugin.onEnable(); + } + return plugin; + } + public void stopServer(DynmapPlugin plugin) { + plugin.onDisable(); + } +} diff --git a/forge-1.19/src/main/java/org/dynmap/forge_1_19/VersionCheck.java b/forge-1.19/src/main/java/org/dynmap/forge_1_19/VersionCheck.java new file mode 100644 index 00000000..044e2df3 --- /dev/null +++ b/forge-1.19/src/main/java/org/dynmap/forge_1_19/VersionCheck.java @@ -0,0 +1,97 @@ +package org.dynmap.forge_1_19; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URL; + +import org.dynmap.DynmapCore; +import org.dynmap.Log; + +public class VersionCheck { + private static final String VERSION_URL = "http://mikeprimm.com/dynmap/releases.php"; + public static void runCheck(final DynmapCore core) { + new Thread(new Runnable() { + public void run() { + doCheck(core); + } + }).start(); + } + + private static int getReleaseVersion(String s) { + int index = s.lastIndexOf('-'); + if(index < 0) + index = s.lastIndexOf('.'); + if(index >= 0) + s = s.substring(0, index); + String[] split = s.split("\\."); + int v = 0; + try { + for(int i = 0; (i < split.length) && (i < 3); i++) { + v += Integer.parseInt(split[i]) << (8 * (2 - i)); + } + } catch (NumberFormatException nfx) {} + return v; + } + + private static int getBuildNumber(String s) { + int index = s.lastIndexOf('-'); + if(index < 0) + index = s.lastIndexOf('.'); + if(index >= 0) + s = s.substring(index+1); + try { + return Integer.parseInt(s); + } catch (NumberFormatException nfx) { + return 99999999; + } + } + + private static void doCheck(DynmapCore core) { + String pluginver = core.getDynmapPluginVersion(); + String platform = core.getDynmapPluginPlatform(); + String platver = core.getDynmapPluginPlatformVersion(); + if((pluginver == null) || (platform == null) || (platver == null)) + return; + HttpURLConnection conn = null; + String loc = VERSION_URL; + int cur_ver = getReleaseVersion(pluginver); + int cur_bn = getBuildNumber(pluginver); + try { + while((loc != null) && (!loc.isEmpty())) { + URL url = new URL(loc); + conn = (HttpURLConnection) url.openConnection(); + conn.setRequestProperty("User-Agent", "Dynmap (" + platform + "/" + platver + "/" + pluginver); + conn.connect(); + loc = conn.getHeaderField("Location"); + } + BufferedReader rdr = new BufferedReader(new InputStreamReader(conn.getInputStream())); + String line = null; + while((line = rdr.readLine()) != null) { + String[] split = line.split(":"); + if(split.length < 4) continue; + /* If our platform and version, or wildcard platform version */ + if(split[0].equals(platform) && (split[1].equals("*") || split[1].equals(platver))) { + int recommended_ver = getReleaseVersion(split[2]); + int recommended_bn = getBuildNumber(split[2]); + if((recommended_ver > cur_ver) || ((recommended_ver == cur_ver) && (recommended_bn > cur_bn))) { /* Newer recommended build */ + Log.info("Version obsolete: new recommended version " + split[2] + " is available."); + } + else if(cur_ver > recommended_ver) { /* Running dev or prerelease? */ + int prerel_ver = getReleaseVersion(split[3]); + int prerel_bn = getBuildNumber(split[3]); + if((prerel_ver > cur_ver) || ((prerel_ver == cur_ver) && (prerel_bn > cur_bn))) { + Log.info("Version obsolete: new prerelease version " + split[3] + " is available."); + } + } + } + } + } catch (Exception x) { + Log.info("Error checking for latest version"); + } finally { + if(conn != null) { + conn.disconnect(); + } + } + } +} diff --git a/forge-1.19/src/main/java/org/dynmap/forge_1_19/permissions/FilePermissions.java b/forge-1.19/src/main/java/org/dynmap/forge_1_19/permissions/FilePermissions.java new file mode 100644 index 00000000..c3121bd3 --- /dev/null +++ b/forge-1.19/src/main/java/org/dynmap/forge_1_19/permissions/FilePermissions.java @@ -0,0 +1,103 @@ +package org.dynmap.forge_1_19.permissions; + +import java.io.File; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.dynmap.ConfigurationNode; +import org.dynmap.Log; +import org.dynmap.forge_1_19.DynmapPlugin; + +import net.minecraft.server.level.ServerPlayer; + +public class FilePermissions implements PermissionProvider { + private HashMap> perms; + private Set defperms; + + public static FilePermissions create() { + File f = new File("dynmap/permissions.yml"); + if(!f.exists()) + return null; + ConfigurationNode cfg = new ConfigurationNode(f); + cfg.load(); + + Log.info("Using permissions.yml for access control"); + + return new FilePermissions(cfg); + } + + private FilePermissions(ConfigurationNode cfg) { + perms = new HashMap>(); + for(String k : cfg.keySet()) { + List p = cfg.getStrings(k, null); + if(p != null) { + k = k.toLowerCase(); + HashSet pset = new HashSet(); + for(String perm : p) { + pset.add(perm.toLowerCase()); + } + perms.put(k, pset); + if(k.equals("defaultuser")) { + defperms = pset; + } + } + } + } + + private boolean hasPerm(String player, String perm) { + Set ps = perms.get(player); + if((ps != null) && (ps.contains(perm))) { + return true; + } + if(defperms.contains(perm)) { + return true; + } + return false; + } + @Override + public Set hasOfflinePermissions(String player, Set perms) { + player = player.toLowerCase(); + HashSet rslt = new HashSet(); + if(DynmapPlugin.plugin.isOp(player)) { + rslt.addAll(perms); + } + else { + for(String p : perms) { + if(hasPerm(player, p)) { + rslt.add(p); + } + } + } + return rslt; + } + @Override + public boolean hasOfflinePermission(String player, String perm) { + player = player.toLowerCase(); + if(DynmapPlugin.plugin.isOp(player)) { + return true; + } + else { + return hasPerm(player, perm); + } + } + + @Override + public boolean has(ServerPlayer psender, String permission) { + if(psender != null) { + String n = psender.getName().getString().toLowerCase(); + return hasPerm(n, permission); + } + return true; + } + @Override + public boolean hasPermissionNode(ServerPlayer psender, String permission) { + if(psender != null) { + String player = psender.getName().getString().toLowerCase(); + return DynmapPlugin.plugin.isOp(player); + } + return false; + } + +} diff --git a/forge-1.19/src/main/java/org/dynmap/forge_1_19/permissions/OpPermissions.java b/forge-1.19/src/main/java/org/dynmap/forge_1_19/permissions/OpPermissions.java new file mode 100644 index 00000000..ddbe5c78 --- /dev/null +++ b/forge-1.19/src/main/java/org/dynmap/forge_1_19/permissions/OpPermissions.java @@ -0,0 +1,51 @@ +package org.dynmap.forge_1_19.permissions; + +import java.util.HashSet; +import java.util.Set; + +import org.dynmap.Log; +import org.dynmap.forge_1_19.DynmapPlugin; + +import net.minecraft.server.level.ServerPlayer; + +public class OpPermissions implements PermissionProvider { + public HashSet usrCommands = new HashSet(); + + public OpPermissions(String[] usrCommands) { + for (String usrCommand : usrCommands) { + this.usrCommands.add(usrCommand); + } + Log.info("Using ops.txt for access control"); + } + + @Override + public Set hasOfflinePermissions(String player, Set perms) { + HashSet rslt = new HashSet(); + if(DynmapPlugin.plugin.isOp(player)) { + rslt.addAll(perms); + } + return rslt; + } + @Override + public boolean hasOfflinePermission(String player, String perm) { + return DynmapPlugin.plugin.isOp(player); + } + + @Override + public boolean has(ServerPlayer psender, String permission) { + if(psender != null) { + if(usrCommands.contains(permission)) { + return true; + } + return DynmapPlugin.plugin.isOp(psender.getName().getString()); + } + return true; + } + @Override + public boolean hasPermissionNode(ServerPlayer psender, String permission) { + if(psender != null) { + return DynmapPlugin.plugin.isOp(psender.getName().getString()); + } + return true; + } +} diff --git a/forge-1.19/src/main/java/org/dynmap/forge_1_19/permissions/PermissionProvider.java b/forge-1.19/src/main/java/org/dynmap/forge_1_19/permissions/PermissionProvider.java new file mode 100644 index 00000000..d41a772d --- /dev/null +++ b/forge-1.19/src/main/java/org/dynmap/forge_1_19/permissions/PermissionProvider.java @@ -0,0 +1,15 @@ +package org.dynmap.forge_1_19.permissions; + +import java.util.Set; + +import net.minecraft.server.level.ServerPlayer; + +public interface PermissionProvider { + boolean has(ServerPlayer sender, String permission); + boolean hasPermissionNode(ServerPlayer sender, String permission); + + Set hasOfflinePermissions(String player, Set perms); + + boolean hasOfflinePermission(String player, String perm); + +} diff --git a/forge-1.19/src/main/resources/META-INF/accesstransformer.cfg b/forge-1.19/src/main/resources/META-INF/accesstransformer.cfg new file mode 100644 index 00000000..58a91d30 --- /dev/null +++ b/forge-1.19/src/main/resources/META-INF/accesstransformer.cfg @@ -0,0 +1,4 @@ +public net.minecraft.world.level.biome.BiomeSpecialEffects$Builder f_47928_ # waterColor +public net.minecraft.server.level.ServerLevel f_8549_ # serverLevelData +public net.minecraft.server.level.ChunkMap f_140130_ # visibleChunkMap +public net.minecraft.server.level.ChunkMap m_214963_(Lnet/minecraft/world/level/ChunkPos;)Ljava/util/concurrent/CompletableFuture; # readChunk( diff --git a/forge-1.19/src/main/resources/META-INF/mods.toml b/forge-1.19/src/main/resources/META-INF/mods.toml new file mode 100644 index 00000000..17241af4 --- /dev/null +++ b/forge-1.19/src/main/resources/META-INF/mods.toml @@ -0,0 +1,26 @@ +modLoader="javafml" +loaderVersion="[41,)" +issueTrackerURL="https://github.com/webbukkit/dynmap/issues" +license="Apache Public License v2" +[[mods]] +modId="dynmap" +version="${version}" +displayName="Dynmap" +authors="mikeprimm" +description=''' +Dynamic, Google-maps style rendered maps for your Minecraft server +''' + +[[dependencies.dynmap]] + modId="forge" + mandatory=true + versionRange="[41,)" + ordering="NONE" + # Side this dependency is applied on - BOTH, CLIENT or SERVER + side="SERVER" +[[dependencies.dynmap]] + modId="minecraft" + mandatory=true + versionRange="[1.19,1.20)" + ordering="NONE" + side="SERVER" diff --git a/forge-1.19/src/main/resources/configuration.txt b/forge-1.19/src/main/resources/configuration.txt new file mode 100644 index 00000000..161202ed --- /dev/null +++ b/forge-1.19/src/main/resources/configuration.txt @@ -0,0 +1,496 @@ +# All paths in this configuration file are relative to Dynmap's data-folder: minecraft_server/dynmap/ + +# All map templates are defined in the templates directory +# To use the HDMap very-low-res (2 ppb) map templates as world defaults, set value to vlowres +# The definitions of these templates are in normal-vlowres.txt, nether-vlowres.txt, and the_end-vlowres.txt +# To use the HDMap low-res (4 ppb) map templates as world defaults, set value to lowres +# The definitions of these templates are in normal-lowres.txt, nether-lowres.txt, and the_end-lowres.txt +# To use the HDMap hi-res (16 ppb) map templates (these can take a VERY long time for initial fullrender), set value to hires +# The definitions of these templates are in normal-hires.txt, nether-hires.txt, and the_end-hires.txt +# To use the HDMap low-res (4 ppb) map templates, with support for boosting resolution selectively to hi-res (16 ppb), set value to low_boost_hi +# The definitions of these templates are in normal-low_boost_hi.txt, nether-low_boost_hi.txt, and the_end-low_boost_hi.txt +# To use the HDMap hi-res (16 ppb) map templates, with support for boosting resolution selectively to vhi-res (32 ppb), set value to hi_boost_vhi +# The definitions of these templates are in normal-hi_boost_vhi.txt, nether-hi_boost_vhi.txt, and the_end-hi_boost_vhi.txt +# To use the HDMap hi-res (16 ppb) map templates, with support for boosting resolution selectively to xhi-res (64 ppb), set value to hi_boost_xhi +# The definitions of these templates are in normal-hi_boost_xhi.txt, nether-hi_boost_xhi.txt, and the_end-hi_boost_xhi.txt +deftemplatesuffix: hires + +# Set default tile scale (0 = 128px x 128x, 1 = 256px x 256px, 2 = 512px x 512px, 3 = 1024px x 1024px, 4 = 2048px x 2048px) - 0 is default +# Note: changing this value will result in all maps that use the default value being required to be fully rendered +#defaulttilescale: 0 + +# Map storage scheme: only uncommoent one 'type' value +# filetree: classic and default scheme: tree of files, with all map data under the directory indicated by 'tilespath' setting +# sqlite: single SQLite database file (this can get VERY BIG), located at 'dbfile' setting (default is file dynmap.db in data directory) +# mysql: MySQL database, at hostname:port in database, accessed via userid with password +# mariadb: MariaDB database, at hostname:port in database, accessed via userid with password +# postgres: PostgreSQL database, at hostname:port in database, accessed via userid with password +storage: + # Filetree storage (standard tree of image files for maps) + type: filetree + # SQLite db for map storage (uses dbfile as storage location) + #type: sqlite + #dbfile: dynmap.db + # MySQL DB for map storage (at 'hostname':'port' in database 'database' using user 'userid' password 'password' and table prefix 'prefix' + #type: mysql + #hostname: localhost + #port: 3306 + #database: dynmap + #userid: dynmap + #password: dynmap + #prefix: "" + # + # AWS S3 backet web site + #type: aws_s3 + #bucketname: "dynmap-bucket-name" + #region: us-east-1 + #aws_access_key_id: "" + #aws_secret_access_key: "" + #prefix: "" + +components: + - class: org.dynmap.ClientConfigurationComponent + + - class: org.dynmap.InternalClientUpdateComponent + sendhealth: true + sendposition: true + allowwebchat: true + webchat-interval: 5 + hidewebchatip: false + trustclientname: false + includehiddenplayers: false + # (optional) if true, color codes in player display names are used + use-name-colors: false + # (optional) if true, player login IDs will be used for web chat when their IPs match + use-player-login-ip: true + # (optional) if use-player-login-ip is true, setting this to true will cause chat messages not matching a known player IP to be ignored + require-player-login-ip: false + # (optional) block player login IDs that are banned from chatting + block-banned-player-chat: true + # Require login for web-to-server chat (requires login-enabled: true) + webchat-requires-login: false + # If set to true, users must have dynmap.webchat permission in order to chat + webchat-permissions: false + # Limit length of single chat messages + chatlengthlimit: 256 + # # Optional - make players hidden when they are inside/underground/in shadows (#=light level: 0=full shadow,15=sky) + # hideifshadow: 4 + # # Optional - make player hidden when they are under cover (#=sky light level,0=underground,15=open to sky) + # hideifundercover: 14 + # # (Optional) if true, players that are crouching/sneaking will be hidden + hideifsneaking: false + # If true, player positions/status is protected (login with ID with dynmap.playermarkers.seeall permission required for info other than self) + protected-player-info: false + # If true, hide players with invisibility potion effects active + hide-if-invisiblity-potion: true + # If true, player names are not shown on map, chat, list + hidenames: false + #- class: org.dynmap.JsonFileClientUpdateComponent + # writeinterval: 1 + # sendhealth: true + # sendposition: true + # allowwebchat: true + # webchat-interval: 5 + # hidewebchatip: false + # includehiddenplayers: false + # use-name-colors: false + # use-player-login-ip: false + # require-player-login-ip: false + # block-banned-player-chat: true + # hideifshadow: 0 + # hideifundercover: 0 + # hideifsneaking: false + # # Require login for web-to-server chat (requires login-enabled: true) + # webchat-requires-login: false + # # If set to true, users must have dynmap.webchat permission in order to chat + # webchat-permissions: false + # # Limit length of single chat messages + # chatlengthlimit: 256 + # hide-if-invisiblity-potion: true + # hidenames: false + + - class: org.dynmap.SimpleWebChatComponent + allowchat: true + # If true, web UI users can supply name for chat using 'playername' URL parameter. 'trustclientname' must also be set true. + allowurlname: false + + # Note: this component is needed for the dmarker commands, and for the Marker API to be available to other plugins + - class: org.dynmap.MarkersComponent + type: markers + showlabel: false + enablesigns: false + # Default marker set for sign markers + default-sign-set: markers + # (optional) add spawn point markers to standard marker layer + showspawn: true + spawnicon: world + spawnlabel: "Spawn" + # (optional) layer for showing offline player's positions (for 'maxofflinetime' minutes after logoff) + showofflineplayers: false + offlinelabel: "Offline" + offlineicon: offlineuser + offlinehidebydefault: true + offlineminzoom: 0 + maxofflinetime: 30 + # (optional) layer for showing player's spawn beds + showspawnbeds: false + spawnbedlabel: "Spawn Beds" + spawnbedicon: bed + spawnbedhidebydefault: true + spawnbedminzoom: 0 + spawnbedformat: "%name%'s bed" + # (optional) Show world border (vanilla 1.8+) + showworldborder: true + worldborderlabel: "Border" + + - class: org.dynmap.ClientComponent + type: chat + allowurlname: false + - class: org.dynmap.ClientComponent + type: chatballoon + focuschatballoons: false + - class: org.dynmap.ClientComponent + type: chatbox + showplayerfaces: true + messagettl: 5 + # Optional: set number of lines in scrollable message history: if set, messagettl is not used to age out messages + #scrollback: 100 + # Optional: set maximum number of lines visible for chatbox + #visiblelines: 10 + # Optional: send push button + sendbutton: false + - class: org.dynmap.ClientComponent + type: playermarkers + showplayerfaces: true + showplayerhealth: true + # If true, show player body too (only valid if showplayerfaces=true) + showplayerbody: false + # Option to make player faces small - don't use with showplayerhealth or largeplayerfaces + smallplayerfaces: false + # Option to make player faces larger - don't use with showplayerhealth or smallplayerfaces + largeplayerfaces: false + # Optional - make player faces layer hidden by default + hidebydefault: false + # Optional - ordering priority in layer menu (low goes before high - default is 0) + layerprio: 0 + # Optional - label for player marker layer (default is 'Players') + label: "Players" + + #- class: org.dynmap.ClientComponent + # type: digitalclock + - class: org.dynmap.ClientComponent + type: link + + - class: org.dynmap.ClientComponent + type: timeofdayclock + showdigitalclock: true + #showweather: true + # Mouse pointer world coordinate display + - class: org.dynmap.ClientComponent + type: coord + label: "Location" + hidey: false + show-mcr: false + show-chunk: false + + # Note: more than one logo component can be defined + #- class: org.dynmap.ClientComponent + # type: logo + # text: "Dynmap" + # #logourl: "images/block_surface.png" + # linkurl: "http://forums.bukkit.org/threads/dynmap.489/" + # # Valid positions: top-left, top-right, bottom-left, bottom-right + # position: bottom-right + + #- class: org.dynmap.ClientComponent + # type: inactive + # timeout: 1800 # in seconds (1800 seconds = 30 minutes) + # redirecturl: inactive.html + # #showmessage: 'You were inactive for too long.' + + #- class: org.dynmap.TestComponent + # stuff: "This is some configuration-value" + +# Treat hiddenplayers.txt as a whitelist for players to be shown on the map? (Default false) +display-whitelist: false + +# How often a tile gets rendered (in seconds). +renderinterval: 1 + +# How many tiles on update queue before accelerate render interval +renderacceleratethreshold: 60 + +# How often to render tiles when backlog is above renderacceleratethreshold +renderaccelerateinterval: 0.2 + +# How many update tiles to work on at once (if not defined, default is 1/2 the number of cores) +tiles-rendered-at-once: 2 + +# If true, use normal priority threads for rendering (versus low priority) - this can keep rendering +# from starving on busy Windows boxes (Linux JVMs pretty much ignore thread priority), but may result +# in more competition for CPU resources with other processes +usenormalthreadpriority: true + +# Save and restore pending tile renders - prevents their loss on server shutdown or /reload +saverestorepending: true + +# Save period for pending jobs (in seconds): periodic saving for crash recovery of jobs +save-pending-period: 900 + +# Zoom-out tile update period - how often to scan for and process tile updates into zoom-out tiles (in seconds) +zoomoutperiod: 30 + +# Control whether zoom out tiles are validated on startup (can be needed if zoomout processing is interrupted, but can be expensive on large maps) +initial-zoomout-validate: true + +# Default delay on processing of updated tiles, in seconds. This can reduce potentially expensive re-rendering +# of frequently updated tiles (such as due to machines, pistons, quarries or other automation). Values can +# also be set on individual worlds and individual maps. +tileupdatedelay: 30 + +# Tile hashing is used to minimize tile file updates when no changes have occurred - set to false to disable +enabletilehash: true + +# Optional - hide ores: render as normal stone (so that they aren't revealed by maps) +#hideores: true + +# Optional - enabled BetterGrass style rendering of grass and snow block sides +#better-grass: true + +# Optional - enable smooth lighting by default on all maps supporting it (can be set per map as lighting option) +smooth-lighting: true + +# Optional - use world provider lighting table (good for custom worlds with custom lighting curves, like nether) +# false=classic Dynmap lighting curve +use-brightness-table: true + +# Optional - render specific block names using the textures and models of another block name: can be used to hide/disguise specific +# blocks (e.g. make ores look like stone, hide chests) or to provide simple support for rendering unsupported custom blocks +block-alias: +# "minecraft:quartz_ore": "stone" +# "diamond_ore": "coal_ore" + +# Default image format for HDMaps (png, jpg, jpg-q75, jpg-q80, jpg-q85, jpg-q90, jpg-q95, jpg-q100, webp, webp-q75, webp-q80, webp-q85, webp-q90, webp-q95, webp-q100), +# Note: any webp format requires the presence of the 'webp command line tools' (cwebp, dwebp) (https://developers.google.com/speed/webp/download) +# +# Has no effect on maps with explicit format settings +image-format: jpg-q90 + +# If cwebp or dwebp are not on the PATH, use these settings to provide their full path. Do not use these settings if the tools are on the PATH +# For Windows, include .exe +# +#cwebpPath: /usr/bin/cwebp +#dwebpPath: /usr/bin/dwebp + +# use-generated-textures: if true, use generated textures (same as client); false is static water/lava textures +# correct-water-lighting: if true, use corrected water lighting (same as client); false is legacy water (darker) +# transparent-leaves: if true, leaves are transparent (lighting-wise): false is needed for some Spout versions that break lighting on leaf blocks +use-generated-textures: true +correct-water-lighting: true +transparent-leaves: true + +# ctm-support: if true, Connected Texture Mod (CTM) in texture packs is enabled (default) +ctm-support: true +# custom-colors-support: if true, Custom Colors in texture packs is enabled (default) +custom-colors-support: true + +# Control loading of player faces (if set to false, skins are never fetched) +#fetchskins: false + +# Control updating of player faces, once loaded (if faces are being managed by other apps or manually) +#refreshskins: false + +# Customize URL used for fetching player skins (%player% is macro for name, %uuid% for UUID) +skin-url: "http://skins.minecraft.net/MinecraftSkins/%player%.png" + +# Control behavior for new (1.0+) compass orientation (sunrise moved 90 degrees: east is now what used to be south) +# default is 'newrose' (preserve pre-1.0 maps, rotate rose) +# 'newnorth' is used to rotate maps and rose (requires fullrender of any HDMap map - same as 'newrose' for FlatMap or KzedMap) +compass-mode: newnorth + +# Triggers for automatic updates : blockupdate-with-id is debug for breaking down updates by ID:meta +# To disable, set just 'none' and comment/delete the rest +render-triggers: + - blockupdate + #- blockupdate-with-id + #- lightingupdate + - chunkpopulate + - chunkgenerate + #- none + +# Title for the web page - if not specified, defaults to the server's name (unless it is the default of 'Unknown Server') +#webpage-title: "My Awesome Server Map" + +# The path where the tile-files are placed. +tilespath: web/tiles + +# The path where the web-files are located. +webpath: web + +# If set to false, disable extraction of webpath content (good if using custom web UI or 3rd party web UI) +# Note: web interface is unsupported in this configuration - you're on your own +update-webpath-files: true + +# The path were the /dynmapexp command exports OBJ ZIP files +exportpath: export + +# The network-interface the webserver will bind to (0.0.0.0 for all interfaces, 127.0.0.1 for only local access). +# If not set, uses same setting as server in server.properties (or 0.0.0.0 if not specified) +#webserver-bindaddress: 0.0.0.0 + +# The TCP-port the webserver will listen on. +webserver-port: 8123 + +# Maximum concurrent session on internal web server - limits resources used in Bukkit server +max-sessions: 30 + +# Disables Webserver portion of Dynmap (Advanced users only) +disable-webserver: false + +# Enable/disable having the web server allow symbolic links (true=compatible with existing code, false=more secure (default)) +allow-symlinks: true + +# Enable login support +login-enabled: false +# Require login to access website (requires login-enabled: true) +login-required: false + +# Period between tile renders for fullrender, in seconds (non-zero to pace fullrenders, lessen CPU load) +timesliceinterval: 0.0 + +# Maximum chunk loads per server tick (1/20th of a second) - reducing this below 90 will impact render performance, but also will reduce server thread load +maxchunkspertick: 200 + +# Progress report interval for fullrender/radiusrender, in tiles. Must be 100 or greater +progressloginterval: 100 + +# Parallel fullrender: if defined, number of concurrent threads used for fullrender or radiusrender +# Note: setting this will result in much more intensive CPU use, some additional memory use. Caution should be used when +# setting this to equal or exceed the number of physical cores on the system. +#parallelrendercnt: 4 + +# Interval the browser should poll for updates. +updaterate: 2000 + +# If nonzero, server will pause fullrender/radiusrender processing when 'fullrenderplayerlimit' or more users are logged in +fullrenderplayerlimit: 0 +# If nonzero, server will pause update render processing when 'updateplayerlimit' or more users are logged in +updateplayerlimit: 0 +# Target limit on server thread use - msec per tick +per-tick-time-limit: 50 +# If TPS of server is below this setting, update renders processing is paused +update-min-tps: 18.0 +# If TPS of server is below this setting, full/radius renders processing is paused +fullrender-min-tps: 18.0 +# If TPS of server is below this setting, zoom out processing is paused +zoomout-min-tps: 18.0 + +showplayerfacesinmenu: true + +# Control whether players that are hidden or not on current map are grayed out (true=yes) +grayplayerswhenhidden: true + +# Set sidebaropened: 'true' to pin menu sidebar opened permanently, 'pinned' to default the sidebar to pinned, but allow it to unpin +#sidebaropened: true + +# Customized HTTP response headers - add 'id: value' pairs to all HTTP response headers (internal web server only) +#http-response-headers: +# Access-Control-Allow-Origin: "my-domain.com" +# X-Custom-Header-Of-Mine: "MyHeaderValue" + +# Trusted proxies for web server - which proxy addresses are trusted to supply valid X-Forwarded-For fields +# This now supports both IP address, and subnet ranges (e.g. 192.168.1.0/24 or 202.24.0.0/14 ) +trusted-proxies: + - "127.0.0.1" + - "0:0:0:0:0:0:0:1" + +joinmessage: "%playername% joined" +quitmessage: "%playername% quit" +spammessage: "You may only chat once every %interval% seconds." +# format for messages from web: %playername% substitutes sender ID (typically IP), %message% includes text +webmsgformat: "&color;2[WEB] %playername%: &color;f%message%" + +# Control whether layer control is presented on the UI (default is true) +showlayercontrol: true + +# Enable checking for banned IPs via banned-ips.txt (internal web server only) +check-banned-ips: true + +# Default selection when map page is loaded +defaultzoom: 0 +defaultworld: world +defaultmap: flat +# (optional) Zoom level and map to switch to when following a player, if possible +#followzoom: 3 +#followmap: surface + +# If true, make persistent record of IP addresses used by player logins, to support web IP to player matching +persist-ids-by-ip: true + +# If true, map text to cyrillic +cyrillic-support: false + +# Messages to customize +msg: + maptypes: "Map Types" + players: "Players" + chatrequireslogin: "Chat Requires Login" + chatnotallowed: "You are not permitted to send chat messages" + hiddennamejoin: "Player joined" + hiddennamequit: "Player quit" + +# URL for client configuration (only need to be tailored for proxies or other non-standard configurations) +url: + # configuration URL + #configuration: "up/configuration" + # update URL + #update: "up/world/{world}/{timestamp}" + # sendmessage URL + #sendmessage: "up/sendmessage" + # login URL + #login: "up/login" + # register URL + #register: "up/register" + # tiles base URL + #tiles: "tiles/" + # markers base URL + #markers: "tiles/" + # Snapshot cache size, in chunks +snapshotcachesize: 500 +# Snapshot cache uses soft references (true), else weak references (false) +soft-ref-cache: true + +# Player enter/exit title messages for map markers +# +# Processing period - how often to check player positions vs markers - default is 1000ms (1 second) +#enterexitperiod: 1000 +# Title message fade in time, in ticks (0.05 second intervals) - default is 10 (1/2 second) +#titleFadeIn: 10 +# Title message stay time, in ticks (0.05 second intervals) - default is 70 (3.5 seconds) +#titleStay: 70 +# Title message fade out time, in ticks (0.05 seocnd intervals) - default is 20 (1 second) +#titleFadeOut: 20 +# Enter/exit messages use on screen titles (true - default), if false chat messages are sent instead +#enterexitUseTitle: true +# Set true if new enter messages should supercede pending exit messages (vs being queued in order), default false +#enterReplacesExits: true + +# Published public URL for Dynmap server (allows users to use 'dynmap url' command to get public URL usable to access server +# If not set, 'dynmap url' will not return anything. URL should be fully qualified (e.g. https://mc.westeroscraft.com/) +#publicURL: http://my.greatserver.com/dynmap + +# Send this message if the player does not have permission to use the command +noPermissionMsg: "You don't have permission to use this command!" + +# Set to true to enable verbose startup messages - can help with debugging map configuration problems +# Set to false for a much quieter startup log +verbose: false + +# Enables debugging. +#debuggers: +# - class: org.dynmap.debug.LogDebugger +# Debug: dump blocks missing render data +dump-missing-blocks: false + +# Log4J defense: string substituted for attempts to use macros in web chat +hackAttemptBlurb: "(IaM5uchA1337Haxr-Ban Me!)" diff --git a/forge-1.19/src/main/resources/pack.mcmeta b/forge-1.19/src/main/resources/pack.mcmeta new file mode 100644 index 00000000..8ae5db1a --- /dev/null +++ b/forge-1.19/src/main/resources/pack.mcmeta @@ -0,0 +1,6 @@ +{ + "pack": { + "description": "Dynmap resources", + "pack_format": 8 + } +} diff --git a/forge-1.19/src/main/resources/permissions.yml.example b/forge-1.19/src/main/resources/permissions.yml.example new file mode 100644 index 00000000..a25f9adc --- /dev/null +++ b/forge-1.19/src/main/resources/permissions.yml.example @@ -0,0 +1,27 @@ +# +# Sample permissions.yml for dynmap - trivial, flat-file based permissions for dynmap features +# To use, copy this file to dynmap/permissions.yml, and edit appropriate. File is YAML format. +# +# All operators have full permissions to all functions. +# All users receive the permissions under the 'defaultuser' section +# Specific users can be given more permissions by defining a section with their name containing their permisssions +# All permissions correspond to those documented here (https://github.com/webbukkit/dynmap/wiki/Permissions), but +# do NOT have the 'dynmap.' prefix when used here (e.g. 'dynmap.fullrender' permission is just 'fullrender' here). +# +defaultuser: + - render + - show.self + - hide.self + - sendtoweb + - stats + - marker.list + - marker.listsets + - marker.icons + - webregister + - webchat + #- marker.sign + +#playername1: +# - fullrender +# - cancelrender +# - radiusrender diff --git a/settings.gradle b/settings.gradle index b3dee950..23f38e16 100644 --- a/settings.gradle +++ b/settings.gradle @@ -31,6 +31,7 @@ include ':fabric-1.17.1' include ':fabric-1.16.4' include ':fabric-1.15.2' include ':fabric-1.14.4' +include ':forge-1.19' include ':forge-1.18.2' include ':forge-1.18' include ':forge-1.17.1' @@ -61,6 +62,7 @@ project(':fabric-1.17.1').projectDir = "$rootDir/fabric-1.17.1" as File project(':fabric-1.16.4').projectDir = "$rootDir/fabric-1.16.4" as File project(':fabric-1.15.2').projectDir = "$rootDir/fabric-1.15.2" as File project(':fabric-1.14.4').projectDir = "$rootDir/fabric-1.14.4" as File +project(':forge-1.19').projectDir = "$rootDir/forge-1.19" as File project(':forge-1.18.2').projectDir = "$rootDir/forge-1.18.2" as File project(':forge-1.18').projectDir = "$rootDir/forge-1.18" as File project(':forge-1.17.1').projectDir = "$rootDir/forge-1.17.1" as File From 57b48ba56f943f0d82c34f7dd9af42ad7f56183d Mon Sep 17 00:00:00 2001 From: Mike Primm Date: Wed, 8 Jun 2022 00:42:08 -0500 Subject: [PATCH 24/27] Add 1.19 blocks and textures --- DynmapCore/src/main/resources/models_1.txt | 485 ++++++++++++++++ DynmapCore/src/main/resources/texture_1.txt | 532 ++++++++++++++++++ .../minecraft/textures/block/frogspawn.png | Bin 0 -> 157 bytes .../textures/block/mangrove_door_bottom.png | Bin 0 -> 278 bytes .../textures/block/mangrove_door_top.png | Bin 0 -> 273 bytes .../textures/block/mangrove_leaves.png | Bin 0 -> 279 bytes .../minecraft/textures/block/mangrove_log.png | Bin 0 -> 242 bytes .../textures/block/mangrove_log_top.png | Bin 0 -> 285 bytes .../textures/block/mangrove_planks.png | Bin 0 -> 266 bytes .../textures/block/mangrove_propagule.png | Bin 0 -> 160 bytes .../block/mangrove_propagule_hanging.png | Bin 0 -> 258 bytes .../textures/block/mangrove_roots_side.png | Bin 0 -> 250 bytes .../textures/block/mangrove_roots_top.png | Bin 0 -> 266 bytes .../textures/block/mangrove_trapdoor.png | Bin 0 -> 261 bytes .../assets/minecraft/textures/block/mud.png | Bin 0 -> 283 bytes .../minecraft/textures/block/mud_bricks.png | Bin 0 -> 209 bytes .../block/muddy_mangrove_roots_side.png | Bin 0 -> 330 bytes .../block/muddy_mangrove_roots_top.png | Bin 0 -> 336 bytes .../textures/block/ochre_froglight_side.png | Bin 0 -> 260 bytes .../textures/block/ochre_froglight_top.png | Bin 0 -> 205 bytes .../minecraft/textures/block/packed_mud.png | Bin 0 -> 265 bytes .../block/pearlescent_froglight_side.png | Bin 0 -> 257 bytes .../block/pearlescent_froglight_top.png | Bin 0 -> 204 bytes .../block/reinforced_deepslate_bottom.png | Bin 0 -> 273 bytes .../block/reinforced_deepslate_side.png | Bin 0 -> 321 bytes .../block/reinforced_deepslate_top.png | Bin 0 -> 299 bytes .../assets/minecraft/textures/block/sculk.png | Bin 0 -> 370 bytes .../minecraft/textures/block/sculk.png.mcmeta | 6 + .../textures/block/sculk_catalyst_bottom.png | Bin 0 -> 274 bytes .../textures/block/sculk_catalyst_side.png | Bin 0 -> 314 bytes .../block/sculk_catalyst_side_bloom.png | Bin 0 -> 465 bytes .../sculk_catalyst_side_bloom.png.mcmeta | 5 + .../textures/block/sculk_catalyst_top.png | Bin 0 -> 245 bytes .../block/sculk_catalyst_top_bloom.png | Bin 0 -> 806 bytes .../block/sculk_catalyst_top_bloom.png.mcmeta | 5 + .../textures/block/sculk_shrieker_bottom.png | Bin 0 -> 240 bytes .../sculk_shrieker_can_summon_inner_top.png | Bin 0 -> 724 bytes ...k_shrieker_can_summon_inner_top.png.mcmeta | 6 + .../block/sculk_shrieker_inner_top.png | Bin 0 -> 729 bytes .../block/sculk_shrieker_inner_top.png.mcmeta | 6 + .../textures/block/sculk_shrieker_side.png | Bin 0 -> 309 bytes .../textures/block/sculk_shrieker_top.png | Bin 0 -> 125 bytes .../minecraft/textures/block/sculk_vein.png | Bin 0 -> 423 bytes .../textures/block/sculk_vein.png.mcmeta | 6 + .../textures/block/stripped_mangrove_log.png | Bin 0 -> 253 bytes .../block/stripped_mangrove_log_top.png | Bin 0 -> 261 bytes .../textures/block/verdant_froglight_side.png | Bin 0 -> 258 bytes .../textures/block/verdant_froglight_top.png | Bin 0 -> 205 bytes .../textures/entity/signs/mangrove.png | Bin 0 -> 506 bytes 49 files changed, 1051 insertions(+) create mode 100644 DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/frogspawn.png create mode 100644 DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/mangrove_door_bottom.png create mode 100644 DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/mangrove_door_top.png create mode 100644 DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/mangrove_leaves.png create mode 100644 DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/mangrove_log.png create mode 100644 DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/mangrove_log_top.png create mode 100644 DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/mangrove_planks.png create mode 100644 DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/mangrove_propagule.png create mode 100644 DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/mangrove_propagule_hanging.png create mode 100644 DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/mangrove_roots_side.png create mode 100644 DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/mangrove_roots_top.png create mode 100644 DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/mangrove_trapdoor.png create mode 100644 DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/mud.png create mode 100644 DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/mud_bricks.png create mode 100644 DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/muddy_mangrove_roots_side.png create mode 100644 DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/muddy_mangrove_roots_top.png create mode 100644 DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/ochre_froglight_side.png create mode 100644 DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/ochre_froglight_top.png create mode 100644 DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/packed_mud.png create mode 100644 DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/pearlescent_froglight_side.png create mode 100644 DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/pearlescent_froglight_top.png create mode 100644 DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/reinforced_deepslate_bottom.png create mode 100644 DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/reinforced_deepslate_side.png create mode 100644 DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/reinforced_deepslate_top.png create mode 100644 DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/sculk.png create mode 100644 DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/sculk.png.mcmeta create mode 100644 DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/sculk_catalyst_bottom.png create mode 100644 DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/sculk_catalyst_side.png create mode 100644 DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/sculk_catalyst_side_bloom.png create mode 100644 DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/sculk_catalyst_side_bloom.png.mcmeta create mode 100644 DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/sculk_catalyst_top.png create mode 100644 DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/sculk_catalyst_top_bloom.png create mode 100644 DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/sculk_catalyst_top_bloom.png.mcmeta create mode 100644 DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/sculk_shrieker_bottom.png create mode 100644 DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/sculk_shrieker_can_summon_inner_top.png create mode 100644 DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/sculk_shrieker_can_summon_inner_top.png.mcmeta create mode 100644 DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/sculk_shrieker_inner_top.png create mode 100644 DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/sculk_shrieker_inner_top.png.mcmeta create mode 100644 DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/sculk_shrieker_side.png create mode 100644 DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/sculk_shrieker_top.png create mode 100644 DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/sculk_vein.png create mode 100644 DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/sculk_vein.png.mcmeta create mode 100644 DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/stripped_mangrove_log.png create mode 100644 DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/stripped_mangrove_log_top.png create mode 100644 DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/verdant_froglight_side.png create mode 100644 DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/verdant_froglight_top.png create mode 100644 DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/entity/signs/mangrove.png diff --git a/DynmapCore/src/main/resources/models_1.txt b/DynmapCore/src/main/resources/models_1.txt index 3696eea8..77730a93 100644 --- a/DynmapCore/src/main/resources/models_1.txt +++ b/DynmapCore/src/main/resources/models_1.txt @@ -355,15 +355,19 @@ patchblock:id=ladder,data=6,data=7,patch0=VertX0In # Wall sign - facing east [-1.13.2]patchblock:id=wall_sign,data=0-1,patch0=WSignFront,patch1=WSignBack,patch2=WSignTop,patch3=WSignBottom,patch4=WSignLeft,patch5=WSignRight [1.14-]patchblock:id=oak_wall_sign,id=birch_wall_sign,id=spruce_wall_sign,id=acacia_wall_sign,id=jungle_wall_sign,id=dark_oak_wall_sign,data=0-1,patch0=WSignFront,patch1=WSignBack,patch2=WSignTop,patch3=WSignBottom,patch4=WSignLeft,patch5=WSignRight +[1.19-]patchblock:id=mangrove_wall_sign,data=0-1,patch0=WSignFront,patch1=WSignBack,patch2=WSignTop,patch3=WSignBottom,patch4=WSignLeft,patch5=WSignRight # Wall sign - facing west [-1.13.2]patchblock:id=wall_sign,data=2-3,patch0=WSignFront@180,patch1=WSignBack@180,patch2=WSignTop@180,patch3=WSignBottom@180,patch4=WSignLeft@180,patch5=WSignRight@180 [1.14-]patchblock:id=oak_wall_sign,id=birch_wall_sign,id=spruce_wall_sign,id=acacia_wall_sign,id=jungle_wall_sign,id=dark_oak_wall_sign,data=2-3,patch0=WSignFront@180,patch1=WSignBack@180,patch2=WSignTop@180,patch3=WSignBottom@180,patch4=WSignLeft@180,patch5=WSignRight@180 +[1.19-]patchblock:id=mangrove_wall_sign,data=2-3,patch0=WSignFront@180,patch1=WSignBack@180,patch2=WSignTop@180,patch3=WSignBottom@180,patch4=WSignLeft@180,patch5=WSignRight@180 # Wall sign - facing north [-1.13.2]patchblock:id=wall_sign,data=4-5,patch0=WSignFront@270,patch1=WSignBack@270,patch2=WSignTop@270,patch3=WSignBottom@270,patch4=WSignLeft@270,patch5=WSignRight@270 [1.14-]patchblock:id=oak_wall_sign,id=birch_wall_sign,id=spruce_wall_sign,id=acacia_wall_sign,id=jungle_wall_sign,id=dark_oak_wall_sign,data=4-5,patch0=WSignFront@270,patch1=WSignBack@270,patch2=WSignTop@270,patch3=WSignBottom@270,patch4=WSignLeft@270,patch5=WSignRight@270 +[1.19-]patchblock:id=mangrove_wall_sign,data=4-5,patch0=WSignFront@270,patch1=WSignBack@270,patch2=WSignTop@270,patch3=WSignBottom@270,patch4=WSignLeft@270,patch5=WSignRight@270 # Wall sign - facing south [-1.13.2]patchblock:id=wall_sign,data=6-7,patch0=WSignFront@90,patch1=WSignBack@90,patch2=WSignTop@90,patch3=WSignBottom@90,patch4=WSignLeft@90,patch5=WSignRight@90 [1.14-]patchblock:id=oak_wall_sign,id=birch_wall_sign,id=spruce_wall_sign,id=acacia_wall_sign,id=jungle_wall_sign,id=dark_oak_wall_sign,data=6-7,patch0=WSignFront@90,patch1=WSignBack@90,patch2=WSignTop@90,patch3=WSignBottom@90,patch4=WSignLeft@90,patch5=WSignRight@90 +[1.19-]patchblock:id=mangrove_wall_sign,data=6-7,patch0=WSignFront@90,patch1=WSignBack@90,patch2=WSignTop@90,patch3=WSignBottom@90,patch4=WSignLeft@90,patch5=WSignRight@90 # Redstone wire customblock:id=redstone_wire,class=org.dynmap.hdmap.renderer.RedstoneWireStateRenderer @@ -372,51 +376,67 @@ ignore-updates:id=redstone_wire # Signpost - facing west [-1.13.2]patchblock:id=sign,data=0-1,patch0=SignFront@180,patch1=SignBack@180,patch2=SignTop@180,patch3=SignBottom@180,patch4=SignLeft@180,patch5=SignRight@180,patch6=PostFront@180,patch7=PostBack@180,patch8=PostLeft@180,patch9=PostRight@180 [1.14-]patchblock:id=oak_sign,id=spruce_sign,id=birch_sign,id=acacia_sign,id=jungle_sign,id=dark_oak_sign,data=0-1,patch0=SignFront@180,patch1=SignBack@180,patch2=SignTop@180,patch3=SignBottom@180,patch4=SignLeft@180,patch5=SignRight@180,patch6=PostFront@180,patch7=PostBack@180,patch8=PostLeft@180,patch9=PostRight@180 +[1.19-]patchblock:id=mangrove_sign,data=0-1,patch0=SignFront@180,patch1=SignBack@180,patch2=SignTop@180,patch3=SignBottom@180,patch4=SignLeft@180,patch5=SignRight@180,patch6=PostFront@180,patch7=PostBack@180,patch8=PostLeft@180,patch9=PostRight@180 # Signpost - facing north [-1.13.2]patchblock:id=sign,data=8-9,patch0=SignFront@270,patch1=SignBack@270,patch2=SignTop@270,patch3=SignBottom@270,patch4=SignLeft@270,patch5=SignRight@270,patch6=PostFront@270,patch7=PostBack@270,patch8=PostLeft@270,patch9=PostRight@270 [1.14-]patchblock:id=oak_sign,id=spruce_sign,id=birch_sign,id=acacia_sign,id=jungle_sign,id=dark_oak_sign,data=8-9,patch0=SignFront@270,patch1=SignBack@270,patch2=SignTop@270,patch3=SignBottom@270,patch4=SignLeft@270,patch5=SignRight@270,patch6=PostFront@270,patch7=PostBack@270,patch8=PostLeft@270,patch9=PostRight@270 +[1.19-]patchblock:id=mangrove_sign,data=8-9,patch0=SignFront@270,patch1=SignBack@270,patch2=SignTop@270,patch3=SignBottom@270,patch4=SignLeft@270,patch5=SignRight@270,patch6=PostFront@270,patch7=PostBack@270,patch8=PostLeft@270,patch9=PostRight@270 # Signpost - facing east [-1.13.2]patchblock:id=sign,data=16-17,patch0=SignFront,patch1=SignBack,patch2=SignTop,patch3=SignBottom,patch4=SignLeft,patch5=SignRight,patch6=PostFront,patch7=PostBack,patch8=PostLeft,patch9=PostRight [1.14-]patchblock:id=oak_sign,id=spruce_sign,id=birch_sign,id=acacia_sign,id=jungle_sign,id=dark_oak_sign,data=16-17,patch0=SignFront,patch1=SignBack,patch2=SignTop,patch3=SignBottom,patch4=SignLeft,patch5=SignRight,patch6=PostFront,patch7=PostBack,patch8=PostLeft,patch9=PostRight +[1.19-]patchblock:id=mangrove_sign,data=16-17,patch0=SignFront,patch1=SignBack,patch2=SignTop,patch3=SignBottom,patch4=SignLeft,patch5=SignRight,patch6=PostFront,patch7=PostBack,patch8=PostLeft,patch9=PostRight # Signpost - facing south [-1.13.2]patchblock:id=sign,data=24-25,patch0=SignFront@90,patch1=SignBack@90,patch2=SignTop@90,patch3=SignBottom@90,patch4=SignLeft@90,patch5=SignRight@90,patch6=PostFront@90,patch7=PostBack@90,patch8=PostLeft@90,patch9=PostRight@90 [1.14-]patchblock:id=oak_sign,id=spruce_sign,id=birch_sign,id=acacia_sign,id=jungle_sign,id=dark_oak_sign,data=24-25,patch0=SignFront@90,patch1=SignBack@90,patch2=SignTop@90,patch3=SignBottom@90,patch4=SignLeft@90,patch5=SignRight@90,patch6=PostFront@90,patch7=PostBack@90,patch8=PostLeft@90,patch9=PostRight@90 +[1.19-]patchblock:id=mangrove_sign,data=24-25,patch0=SignFront@90,patch1=SignBack@90,patch2=SignTop@90,patch3=SignBottom@90,patch4=SignLeft@90,patch5=SignRight@90,patch6=PostFront@90,patch7=PostBack@90,patch8=PostLeft@90,patch9=PostRight@90 # Signpost - facing northwest [-1.13.2]patchblock:id=sign,data=4-5,patch0=SignFront@225,patch1=SignBack@225,patch2=SignTop@225,patch3=SignBottom@225,patch4=SignLeft@225,patch5=SignRight@225,patch6=PostFront@225,patch7=PostBack@225,patch8=PostLeft@225,patch9=PostRight@225 [1.14-]patchblock:id=oak_sign,id=spruce_sign,id=birch_sign,id=acacia_sign,id=jungle_sign,id=dark_oak_sign,data=4-5,patch0=SignFront@225,patch1=SignBack@225,patch2=SignTop@225,patch3=SignBottom@225,patch4=SignLeft@225,patch5=SignRight@225,patch6=PostFront@225,patch7=PostBack@225,patch8=PostLeft@225,patch9=PostRight@225 +[1.19-]patchblock:id=mangrove_sign,data=4-5,patch0=SignFront@225,patch1=SignBack@225,patch2=SignTop@225,patch3=SignBottom@225,patch4=SignLeft@225,patch5=SignRight@225,patch6=PostFront@225,patch7=PostBack@225,patch8=PostLeft@225,patch9=PostRight@225 # Signpost - facing northeast [-1.13.2]patchblock:id=sign,data=12-13,patch0=SignFront@315,patch1=SignBack@315,patch2=SignTop@315,patch3=SignBottom@315,patch4=SignLeft@315,patch5=SignRight@315,patch6=PostFront@315,patch7=PostBack@315,patch8=PostLeft@315,patch9=PostRight@315 [1.14-]patchblock:id=oak_sign,id=spruce_sign,id=birch_sign,id=acacia_sign,id=jungle_sign,id=dark_oak_sign,data=12-13,patch0=SignFront@315,patch1=SignBack@315,patch2=SignTop@315,patch3=SignBottom@315,patch4=SignLeft@315,patch5=SignRight@315,patch6=PostFront@315,patch7=PostBack@315,patch8=PostLeft@315,patch9=PostRight@315 +[1.19-]patchblock:id=mangrove_sign,data=12-13,patch0=SignFront@315,patch1=SignBack@315,patch2=SignTop@315,patch3=SignBottom@315,patch4=SignLeft@315,patch5=SignRight@315,patch6=PostFront@315,patch7=PostBack@315,patch8=PostLeft@315,patch9=PostRight@315 # Signpost - facing southeast [-1.13.2]patchblock:id=sign,data=20-21,patch0=SignFront@45,patch1=SignBack@45,patch2=SignTop@45,patch3=SignBottom@45,patch4=SignLeft@45,patch5=SignRight@45,patch6=PostFront@45,patch7=PostBack@45,patch8=PostLeft@45,patch9=PostRight@45 [1.14-]patchblock:id=oak_sign,id=spruce_sign,id=birch_sign,id=acacia_sign,id=jungle_sign,id=dark_oak_sign,data=20-21,patch0=SignFront@45,patch1=SignBack@45,patch2=SignTop@45,patch3=SignBottom@45,patch4=SignLeft@45,patch5=SignRight@45,patch6=PostFront@45,patch7=PostBack@45,patch8=PostLeft@45,patch9=PostRight@45 +[1.19-]patchblock:id=mangrove_sign,data=20-21,patch0=SignFront@45,patch1=SignBack@45,patch2=SignTop@45,patch3=SignBottom@45,patch4=SignLeft@45,patch5=SignRight@45,patch6=PostFront@45,patch7=PostBack@45,patch8=PostLeft@45,patch9=PostRight@45 # Signpost - facing southwest [-1.13.2]patchblock:id=sign,data=28-29,patch0=SignFront@135,patch1=SignBack@135,patch2=SignTop@135,patch3=SignBottom@135,patch4=SignLeft@135,patch5=SignRight@135,patch6=PostFront@135,patch7=PostBack@135,patch8=PostLeft@135,patch9=PostRight@135 [1.14-]patchblock:id=oak_sign,id=spruce_sign,id=birch_sign,id=acacia_sign,id=jungle_sign,id=dark_oak_sign,data=28-29,patch0=SignFront@135,patch1=SignBack@135,patch2=SignTop@135,patch3=SignBottom@135,patch4=SignLeft@135,patch5=SignRight@135,patch6=PostFront@135,patch7=PostBack@135,patch8=PostLeft@135,patch9=PostRight@135 +[1.19-]patchblock:id=mangrove_sign,data=28-29,patch0=SignFront@135,patch1=SignBack@135,patch2=SignTop@135,patch3=SignBottom@135,patch4=SignLeft@135,patch5=SignRight@135,patch6=PostFront@135,patch7=PostBack@135,patch8=PostLeft@135,patch9=PostRight@135 # Signpost - facing west-northwest [-1.13.2]patchblock:id=sign,data=2-3,patch0=SignFront@203,patch1=SignBack@203,patch2=SignTop@203,patch3=SignBottom@203,patch4=SignLeft@203,patch5=SignRight@203,patch6=PostFront@203,patch7=PostBack@203,patch8=PostLeft@203,patch9=PostRight@203 [1.14-]patchblock:id=oak_sign,id=spruce_sign,id=birch_sign,id=acacia_sign,id=jungle_sign,id=dark_oak_sign,data=2-3,patch0=SignFront@203,patch1=SignBack@203,patch2=SignTop@203,patch3=SignBottom@203,patch4=SignLeft@203,patch5=SignRight@203,patch6=PostFront@203,patch7=PostBack@203,patch8=PostLeft@203,patch9=PostRight@203 +[1.19-]patchblock:id=mangrove_sign,data=2-3,patch0=SignFront@203,patch1=SignBack@203,patch2=SignTop@203,patch3=SignBottom@203,patch4=SignLeft@203,patch5=SignRight@203,patch6=PostFront@203,patch7=PostBack@203,patch8=PostLeft@203,patch9=PostRight@203 # Signpost - facing north-northeast [-1.13.2]patchblock:id=sign,data=10-11,patch0=SignFront@293,patch1=SignBack@293,patch2=SignTop@293,patch3=SignBottom@293,patch4=SignLeft@293,patch5=SignRight@293,patch6=PostFront@293,patch7=PostBack@293,patch8=PostLeft@293,patch9=PostRight@293 [1.14-]patchblock:id=oak_sign,id=spruce_sign,id=birch_sign,id=acacia_sign,id=jungle_sign,id=dark_oak_sign,data=10-11,patch0=SignFront@293,patch1=SignBack@293,patch2=SignTop@293,patch3=SignBottom@293,patch4=SignLeft@293,patch5=SignRight@293,patch6=PostFront@293,patch7=PostBack@293,patch8=PostLeft@293,patch9=PostRight@293 +[1.19-]patchblock:id=mangrove_sign,data=10-11,patch0=SignFront@293,patch1=SignBack@293,patch2=SignTop@293,patch3=SignBottom@293,patch4=SignLeft@293,patch5=SignRight@293,patch6=PostFront@293,patch7=PostBack@293,patch8=PostLeft@293,patch9=PostRight@293 # Signpost - facing north-northeast [-1.13.2]patchblock:id=sign,data=18-19,patch0=SignFront@23,patch1=SignBack@23,patch2=SignTop@23,patch3=SignBottom@23,patch4=SignLeft@23,patch5=SignRight@23,patch6=PostFront@23,patch7=PostBack@23,patch8=PostLeft@23,patch9=PostRight@23 [1.14-]patchblock:id=oak_sign,id=spruce_sign,id=birch_sign,id=acacia_sign,id=jungle_sign,id=dark_oak_sign,data=18-19,patch0=SignFront@23,patch1=SignBack@23,patch2=SignTop@23,patch3=SignBottom@23,patch4=SignLeft@23,patch5=SignRight@23,patch6=PostFront@23,patch7=PostBack@23,patch8=PostLeft@23,patch9=PostRight@23 +[1.19-]patchblock:id=mangrove_sign,data=18-19,patch0=SignFront@23,patch1=SignBack@23,patch2=SignTop@23,patch3=SignBottom@23,patch4=SignLeft@23,patch5=SignRight@23,patch6=PostFront@23,patch7=PostBack@23,patch8=PostLeft@23,patch9=PostRight@23 # Signpost - facing north-northeast [-1.13.2]patchblock:id=sign,data=26-27,patch0=SignFront@113,patch1=SignBack@113,patch2=SignTop@113,patch3=SignBottom@113,patch4=SignLeft@113,patch5=SignRight@113,patch6=PostFront@113,patch7=PostBack@113,patch8=PostLeft@113,patch9=PostRight@113 [1.14-]patchblock:id=oak_sign,id=spruce_sign,id=birch_sign,id=acacia_sign,id=jungle_sign,id=dark_oak_sign,data=26-27,patch0=SignFront@113,patch1=SignBack@113,patch2=SignTop@113,patch3=SignBottom@113,patch4=SignLeft@113,patch5=SignRight@113,patch6=PostFront@113,patch7=PostBack@113,patch8=PostLeft@113,patch9=PostRight@113 +[1.19-]patchblock:id=mangrove_sign,data=26-27,patch0=SignFront@113,patch1=SignBack@113,patch2=SignTop@113,patch3=SignBottom@113,patch4=SignLeft@113,patch5=SignRight@113,patch6=PostFront@113,patch7=PostBack@113,patch8=PostLeft@113,patch9=PostRight@113 # Signpost - facing west-southwest [-1.13.2]patchblock:id=sign,data=30-31,patch0=SignFront@157,patch1=SignBack@157,patch2=SignTop@157,patch3=SignBottom@157,patch4=SignLeft@157,patch5=SignRight@157,patch6=PostFront@157,patch7=PostBack@157,patch8=PostLeft@157,patch9=PostRight@157 [1.14-]patchblock:id=oak_sign,id=spruce_sign,id=birch_sign,id=acacia_sign,id=jungle_sign,id=dark_oak_sign,data=30-31,patch0=SignFront@157,patch1=SignBack@157,patch2=SignTop@157,patch3=SignBottom@157,patch4=SignLeft@157,patch5=SignRight@157,patch6=PostFront@157,patch7=PostBack@157,patch8=PostLeft@157,patch9=PostRight@157 +[1.19-]patchblock:id=mangrove_sign,data=30-31,patch0=SignFront@157,patch1=SignBack@157,patch2=SignTop@157,patch3=SignBottom@157,patch4=SignLeft@157,patch5=SignRight@157,patch6=PostFront@157,patch7=PostBack@157,patch8=PostLeft@157,patch9=PostRight@157 # Signpost - facing north-northwest [-1.13.2]patchblock:id=sign,data=6-7,patch0=SignFront@247,patch1=SignBack@247,patch2=SignTop@247,patch3=SignBottom@247,patch4=SignLeft@247,patch5=SignRight@247,patch6=PostFront@247,patch7=PostBack@247,patch8=PostLeft@247,patch9=PostRight@247 [1.14-]patchblock:id=oak_sign,id=spruce_sign,id=birch_sign,id=acacia_sign,id=jungle_sign,id=dark_oak_sign,data=6-7,patch0=SignFront@247,patch1=SignBack@247,patch2=SignTop@247,patch3=SignBottom@247,patch4=SignLeft@247,patch5=SignRight@247,patch6=PostFront@247,patch7=PostBack@247,patch8=PostLeft@247,patch9=PostRight@247 +[1.19-]patchblock:id=mangrove_sign,data=6-7,patch0=SignFront@247,patch1=SignBack@247,patch2=SignTop@247,patch3=SignBottom@247,patch4=SignLeft@247,patch5=SignRight@247,patch6=PostFront@247,patch7=PostBack@247,patch8=PostLeft@247,patch9=PostRight@247 # Signpost - facing east-northeast [-1.13.2]patchblock:id=sign,data=14-15,patch0=SignFront@337,patch1=SignBack@337,patch2=SignTop@337,patch3=SignBottom@337,patch4=SignLeft@337,patch5=SignRight@337,patch6=PostFront@337,patch7=PostBack@337,patch8=PostLeft@337,patch9=PostRight@337 [1.14-]patchblock:id=oak_sign,id=spruce_sign,id=birch_sign,id=acacia_sign,id=jungle_sign,id=dark_oak_sign,data=14-15,patch0=SignFront@337,patch1=SignBack@337,patch2=SignTop@337,patch3=SignBottom@337,patch4=SignLeft@337,patch5=SignRight@337,patch6=PostFront@337,patch7=PostBack@337,patch8=PostLeft@337,patch9=PostRight@337 +[1.19-]patchblock:id=mangrove_sign,data=14-15,patch0=SignFront@337,patch1=SignBack@337,patch2=SignTop@337,patch3=SignBottom@337,patch4=SignLeft@337,patch5=SignRight@337,patch6=PostFront@337,patch7=PostBack@337,patch8=PostLeft@337,patch9=PostRight@337 # Signpost - facing south-southeast [-1.13.2]patchblock:id=sign,data=22-23,patch0=SignFront@67,patch1=SignBack@67,patch2=SignTop@67,patch3=SignBottom@67,patch4=SignLeft@67,patch5=SignRight@67,patch6=PostFront@67,patch7=PostBack@67,patch8=PostLeft@67,patch9=PostRight@67 [1.14-]patchblock:id=oak_sign,id=spruce_sign,id=birch_sign,id=acacia_sign,id=jungle_sign,id=dark_oak_sign,data=22-23,patch0=SignFront@67,patch1=SignBack@67,patch2=SignTop@67,patch3=SignBottom@67,patch4=SignLeft@67,patch5=SignRight@67,patch6=PostFront@67,patch7=PostBack@67,patch8=PostLeft@67,patch9=PostRight@67 +[1.19-]patchblock:id=mangrove_sign,data=22-23,patch0=SignFront@67,patch1=SignBack@67,patch2=SignTop@67,patch3=SignBottom@67,patch4=SignLeft@67,patch5=SignRight@67,patch6=PostFront@67,patch7=PostBack@67,patch8=PostLeft@67,patch9=PostRight@67 # Fire modellist:id=fire,box=0/0/8.8/false:16/16/8.8/-22.5/0/0:s/0/0/0/16/16,box=0/0/7.2/false:16/16/7.2/22.5/0/0:n/0/0/0/16/16,box=8.8/0/0/false:8.8/16/16/0/0/-22/5:w/0/0/0/16/16,box=7.2/0/0/false:7.2/16/16/0/0/22.5:e/0/0/0/16/16,box=0/0/0.01/false:16/16/0.01:s/0/0/0/16/16:n/0/0/0/16/16,box=0/0/0.01/false:16/16/0.01/0/90/0:s/0/0/0/16/16:n/0/0/0/16/16,box=0/0/0.01/false:16/16/0.01/0/180/0:s/0/0/0/16/16:n/0/0/0/16/16,box=0/0/0.01/false:16/16/0.01/0/270/0:s/0/0/0/16/16:n/0/0/0/16/16 @@ -2243,3 +2263,468 @@ modellist:id=%dropper,state=facing:south,box=0.000000/0.000000/0.000000:16.00000 modellist:id=%dropper,state=facing:west,box=0.000000/0.000000/0.000000:16.000000/16.000000/16.000000:d/2:w/1:e/1:n/0:u/2:s/1:R/0/270/0 modellist:id=%dropper,state=facing:down,box=0.000000/0.000000/0.000000:16.000000/16.000000/16.000000:d/0:w/0:e/0:n/0:u/1:s/0:R/180/0/0 + +[1.19-]modellist:id=%mangrove_propagule,state=hanging:true/age:0,box=7.000000/13.611040/10.071930:9.000000/13.611040/12.071930/22.500000/0.000000/0.000000/8.000000/16.000000/8.000000:n/0/0.000000/0.000000/2.000000/0.000000:d/0/6.000000/3.000000/8.000000/5.000000:w/0/0.000000/0.000000/2.000000/0.000000:e/0/0.000000/0.000000/2.000000/0.000000:s/0/0.000000/0.000000/2.000000/0.000000:u180/0/8.000000/3.000000/10.000000/5.000000,box=10.071930/13.611040/7.000000:12.071930/13.611040/9.000000/0.000000/0.000000/-22.500000/8.000000/16.000000/8.000000:n/0/0.000000/0.000000/2.000000/0.000000:d90/0/6.000000/3.000000/8.000000/5.000000:w/0/0.000000/0.000000/2.000000/0.000000:e/0/0.000000/0.000000/2.000000/0.000000:s/0/0.000000/0.000000/2.000000/0.000000:u90/0/8.000000/3.000000/10.000000/5.000000,box=7.000000/13.611040/3.928070:9.000000/13.611040/5.928070/-22.500000/0.000000/0.000000/8.000000/16.000000/8.000000:n/0/0.000000/0.000000/2.000000/0.000000:d180/0/6.000000/3.000000/8.000000/5.000000:w/0/0.000000/0.000000/2.000000/0.000000:e/0/0.000000/0.000000/2.000000/0.000000:s/0/0.000000/0.000000/2.000000/0.000000:u/0/8.000000/3.000000/10.000000/5.000000,box=3.928070/13.611040/7.000000:5.928070/13.611040/9.000000/0.000000/0.000000/22.500000/8.000000/16.000000/8.000000:n/0/0.000000/0.000000/2.000000/0.000000:d270/0/6.000000/3.000000/8.000000/5.000000:w/0/0.000000/0.000000/2.000000/0.000000:e/0/0.000000/0.000000/2.000000/0.000000:s/0/0.000000/0.000000/2.000000/0.000000:u270/0/8.000000/3.000000/10.000000/5.000000,box=7.000000/13.000000/7.000000:9.000000/14.000000/9.000000:n/0/0.000000/2.000000/2.000000/3.000000:d/0/0.000000/3.000000/2.000000/5.000000:w/0/0.000000/2.000000/2.000000/3.000000:e/0/0.000000/2.000000/2.000000/3.000000:s/0/0.000000/2.000000/2.000000/3.000000:u/0/0.000000/0.000000/2.000000/2.000000,box=7.000000/14.000000/8.000000:9.000000/16.000000/8.000000/0.000000/-45.000000/0.000000/8.000000/16.000000/8.000000:n/0/0.000000/0.000000/2.000000/2.000000:d/0/0.000000/0.000000/2.000000/0.000000:w/0/0.000000/0.000000/0.000000/2.000000:e/0/0.000000/0.000000/0.000000/2.000000:s/0/0.000000/0.000000/2.000000/2.000000:u/0/0.000000/0.000000/2.000000/0.000000,box=7.000000/14.000000/8.000000:9.000000/16.000000/8.000000/0.000000/45.000000/0.000000/8.000000/16.000000/8.000000:n/0/0.000000/0.000000/2.000000/2.000000:d/0/0.000000/0.000000/2.000000/0.000000:w/0/0.000000/0.000000/0.000000/2.000000:e/0/0.000000/0.000000/0.000000/2.000000:s/0/0.000000/0.000000/2.000000/2.000000:u/0/0.000000/0.000000/2.000000/0.000000 +[1.19-]modellist:id=%mangrove_propagule,state=hanging:false/age:0,box=4.500000/9.000000/8.000000:11.500000/15.000000/8.000000/0.000000/45.000000/0.000000/8.000000/0.000000/8.000000:n/0/4.000000/1.000000/11.000000/7.000000:s/0/4.000000/1.000000/11.000000/7.000000,box=8.000000/9.000000/4.500000:8.000000/15.000000/11.500000/0.000000/45.000000/0.000000/8.000000/0.000000/8.000000:w/0/4.000000/1.000000/11.000000/7.000000:e/0/4.000000/1.000000/11.000000/7.000000,box=8.000000/0.000000/7.000000:8.000000/9.000000/9.000000/0.000000/45.000000/0.000000/8.000000/0.000000/8.000000:w/0/7.000000/7.000000/9.000000/16.000000:e/0/7.000000/7.000000/9.000000/16.000000,box=7.000000/0.000000/8.000000:9.000000/9.000000/8.000000/0.000000/45.000000/0.000000/8.000000/0.000000/8.000000:n/0/7.000000/7.000000/9.000000/16.000000:s/0/7.000000/7.000000/9.000000/16.000000 +[1.19-]modellist:id=%mangrove_propagule,state=hanging:true/age:1,box=7.000000/10.000000/7.000000:9.000000/13.000000/9.000000:n/0/0.000000/7.000000/2.000000/10.000000:d/0/0.000000/5.000000/2.000000/7.000000:w/0/0.000000/7.000000/2.000000/10.000000:e/0/0.000000/7.000000/2.000000/10.000000:s/0/0.000000/7.000000/2.000000/10.000000:u/0/0.000000/5.000000/2.000000/7.000000,box=7.000000/13.611040/10.071930:9.000000/13.611040/12.071930/22.500000/0.000000/0.000000/8.000000/16.000000/8.000000:n/0/0.000000/0.000000/2.000000/0.000000:d/0/6.000000/3.000000/8.000000/5.000000:w/0/0.000000/0.000000/2.000000/0.000000:e/0/0.000000/0.000000/2.000000/0.000000:s/0/0.000000/0.000000/2.000000/0.000000:u180/0/8.000000/3.000000/10.000000/5.000000,box=10.071930/13.611040/7.000000:12.071930/13.611040/9.000000/0.000000/0.000000/-22.500000/8.000000/16.000000/8.000000:n/0/0.000000/0.000000/2.000000/0.000000:d90/0/6.000000/3.000000/8.000000/5.000000:w/0/0.000000/0.000000/2.000000/0.000000:e/0/0.000000/0.000000/2.000000/0.000000:s/0/0.000000/0.000000/2.000000/0.000000:u90/0/8.000000/3.000000/10.000000/5.000000,box=7.000000/13.611040/3.928070:9.000000/13.611040/5.928070/-22.500000/0.000000/0.000000/8.000000/16.000000/8.000000:n/0/0.000000/0.000000/2.000000/0.000000:d180/0/6.000000/3.000000/8.000000/5.000000:w/0/0.000000/0.000000/2.000000/0.000000:e/0/0.000000/0.000000/2.000000/0.000000:s/0/0.000000/0.000000/2.000000/0.000000:u/0/8.000000/3.000000/10.000000/5.000000,box=3.928070/13.611040/7.000000:5.928070/13.611040/9.000000/0.000000/0.000000/22.500000/8.000000/16.000000/8.000000:n/0/0.000000/0.000000/2.000000/0.000000:d270/0/6.000000/3.000000/8.000000/5.000000:w/0/0.000000/0.000000/2.000000/0.000000:e/0/0.000000/0.000000/2.000000/0.000000:s/0/0.000000/0.000000/2.000000/0.000000:u270/0/8.000000/3.000000/10.000000/5.000000,box=7.000000/13.000000/7.000000:9.000000/14.000000/9.000000:n/0/0.000000/2.000000/2.000000/3.000000:d/0/0.000000/3.000000/2.000000/5.000000:w/0/0.000000/2.000000/2.000000/3.000000:e/0/0.000000/2.000000/2.000000/3.000000:s/0/0.000000/2.000000/2.000000/3.000000:u/0/0.000000/0.000000/2.000000/2.000000,box=7.000000/14.000000/8.000000:9.000000/16.000000/8.000000/0.000000/-45.000000/0.000000/8.000000/16.000000/8.000000:n/0/0.000000/0.000000/2.000000/2.000000:d/0/0.000000/0.000000/2.000000/0.000000:w/0/0.000000/0.000000/0.000000/2.000000:e/0/0.000000/0.000000/0.000000/2.000000:s/0/0.000000/0.000000/2.000000/2.000000:u/0/0.000000/0.000000/2.000000/0.000000,box=7.000000/14.000000/8.000000:9.000000/16.000000/8.000000/0.000000/45.000000/0.000000/8.000000/16.000000/8.000000:n/0/0.000000/0.000000/2.000000/2.000000:d/0/0.000000/0.000000/2.000000/0.000000:w/0/0.000000/0.000000/0.000000/2.000000:e/0/0.000000/0.000000/0.000000/2.000000:s/0/0.000000/0.000000/2.000000/2.000000:u/0/0.000000/0.000000/2.000000/0.000000 +[1.19-]modellist:id=%mangrove_propagule,state=hanging:false/age:1,box=4.500000/9.000000/8.000000:11.500000/15.000000/8.000000/0.000000/45.000000/0.000000/8.000000/0.000000/8.000000:n/0/4.000000/1.000000/11.000000/7.000000:s/0/4.000000/1.000000/11.000000/7.000000,box=8.000000/9.000000/4.500000:8.000000/15.000000/11.500000/0.000000/45.000000/0.000000/8.000000/0.000000/8.000000:w/0/4.000000/1.000000/11.000000/7.000000:e/0/4.000000/1.000000/11.000000/7.000000,box=8.000000/0.000000/7.000000:8.000000/9.000000/9.000000/0.000000/45.000000/0.000000/8.000000/0.000000/8.000000:w/0/7.000000/7.000000/9.000000/16.000000:e/0/7.000000/7.000000/9.000000/16.000000,box=7.000000/0.000000/8.000000:9.000000/9.000000/8.000000/0.000000/45.000000/0.000000/8.000000/0.000000/8.000000:n/0/7.000000/7.000000/9.000000/16.000000:s/0/7.000000/7.000000/9.000000/16.000000 +[1.19-]modellist:id=%mangrove_propagule,state=hanging:true/age:2,box=7.000000/10.000000/7.000000:9.000000/13.000000/9.000000:n/0/0.000000/7.000000/2.000000/10.000000:d/0/0.000000/10.000000/2.000000/12.000000:w/0/0.000000/7.000000/2.000000/10.000000:e/0/0.000000/7.000000/2.000000/10.000000:s/0/0.000000/7.000000/2.000000/10.000000:u/0/0.000000/5.000000/2.000000/7.000000,box=7.000000/13.611040/10.071930:9.000000/13.611040/12.071930/22.500000/0.000000/0.000000/8.000000/16.000000/8.000000:n/0/0.000000/0.000000/2.000000/0.000000:d/0/6.000000/3.000000/8.000000/5.000000:w/0/0.000000/0.000000/2.000000/0.000000:e/0/0.000000/0.000000/2.000000/0.000000:s/0/0.000000/0.000000/2.000000/0.000000:u180/0/8.000000/3.000000/10.000000/5.000000,box=10.071930/13.611040/7.000000:12.071930/13.611040/9.000000/0.000000/0.000000/-22.500000/8.000000/16.000000/8.000000:n/0/0.000000/0.000000/2.000000/0.000000:d90/0/6.000000/3.000000/8.000000/5.000000:w/0/0.000000/0.000000/2.000000/0.000000:e/0/0.000000/0.000000/2.000000/0.000000:s/0/0.000000/0.000000/2.000000/0.000000:u90/0/8.000000/3.000000/10.000000/5.000000,box=7.000000/13.611040/3.928070:9.000000/13.611040/5.928070/-22.500000/0.000000/0.000000/8.000000/16.000000/8.000000:n/0/0.000000/0.000000/2.000000/0.000000:d180/0/6.000000/3.000000/8.000000/5.000000:w/0/0.000000/0.000000/2.000000/0.000000:e/0/0.000000/0.000000/2.000000/0.000000:s/0/0.000000/0.000000/2.000000/0.000000:u/0/8.000000/3.000000/10.000000/5.000000,box=3.928070/13.611040/7.000000:5.928070/13.611040/9.000000/0.000000/0.000000/22.500000/8.000000/16.000000/8.000000:n/0/0.000000/0.000000/2.000000/0.000000:d270/0/6.000000/3.000000/8.000000/5.000000:w/0/0.000000/0.000000/2.000000/0.000000:e/0/0.000000/0.000000/2.000000/0.000000:s/0/0.000000/0.000000/2.000000/0.000000:u270/0/8.000000/3.000000/10.000000/5.000000,box=7.000000/13.000000/7.000000:9.000000/14.000000/9.000000:n/0/0.000000/2.000000/2.000000/3.000000:d/0/0.000000/3.000000/2.000000/5.000000:w/0/0.000000/2.000000/2.000000/3.000000:e/0/0.000000/2.000000/2.000000/3.000000:s/0/0.000000/2.000000/2.000000/3.000000:u/0/0.000000/0.000000/2.000000/2.000000,box=7.000000/14.000000/8.000000:9.000000/16.000000/8.000000/0.000000/-45.000000/0.000000/8.000000/16.000000/8.000000:n/0/0.000000/0.000000/2.000000/2.000000:d/0/0.000000/0.000000/2.000000/0.000000:w/0/0.000000/0.000000/0.000000/2.000000:e/0/0.000000/0.000000/0.000000/2.000000:s/0/0.000000/0.000000/2.000000/2.000000:u/0/0.000000/0.000000/2.000000/0.000000,box=7.000000/14.000000/8.000000:9.000000/16.000000/8.000000/0.000000/45.000000/0.000000/8.000000/16.000000/8.000000:n/0/0.000000/0.000000/2.000000/2.000000:d/0/0.000000/0.000000/2.000000/0.000000:w/0/0.000000/0.000000/0.000000/2.000000:e/0/0.000000/0.000000/0.000000/2.000000:s/0/0.000000/0.000000/2.000000/2.000000:u/0/0.000000/0.000000/2.000000/0.000000,box=7.000000/7.000000/8.000000:9.000000/10.000000/8.000000/0.000000/45.000000/0.000000/8.000000/16.000000/8.000000:n/0/3.000000/7.000000/5.000000/10.000000:d/0/11.000000/10.000000/13.000000/10.000000:w/0/11.000000/0.000000/11.000000/10.000000:e/0/13.000000/0.000000/13.000000/10.000000:s/0/3.000000/7.000000/5.000000/10.000000:u/0/11.000000/0.000000/13.000000/0.000000,box=7.000000/7.000000/8.000000:9.000000/10.000000/8.000000/0.000000/-45.000000/0.000000/8.000000/16.000000/8.000000:n/0/3.000000/7.000000/5.000000/10.000000:d180/0/11.000000/10.000000/13.000000/10.000000:w/0/13.000000/0.000000/13.000000/10.000000:e/0/11.000000/0.000000/11.000000/10.000000:s/0/3.000000/7.000000/5.000000/10.000000:u180/0/11.000000/0.000000/13.000000/0.000000 +[1.19-]modellist:id=%mangrove_propagule,state=hanging:false/age:2,box=4.500000/9.000000/8.000000:11.500000/15.000000/8.000000/0.000000/45.000000/0.000000/8.000000/0.000000/8.000000:n/0/4.000000/1.000000/11.000000/7.000000:s/0/4.000000/1.000000/11.000000/7.000000,box=8.000000/9.000000/4.500000:8.000000/15.000000/11.500000/0.000000/45.000000/0.000000/8.000000/0.000000/8.000000:w/0/4.000000/1.000000/11.000000/7.000000:e/0/4.000000/1.000000/11.000000/7.000000,box=8.000000/0.000000/7.000000:8.000000/9.000000/9.000000/0.000000/45.000000/0.000000/8.000000/0.000000/8.000000:w/0/7.000000/7.000000/9.000000/16.000000:e/0/7.000000/7.000000/9.000000/16.000000,box=7.000000/0.000000/8.000000:9.000000/9.000000/8.000000/0.000000/45.000000/0.000000/8.000000/0.000000/8.000000:n/0/7.000000/7.000000/9.000000/16.000000:s/0/7.000000/7.000000/9.000000/16.000000 +[1.19-]modellist:id=%mangrove_propagule,state=hanging:true/age:3,box=7.000000/10.000000/7.000000:9.000000/13.000000/9.000000:n/0/0.000000/7.000000/2.000000/10.000000:d/0/0.000000/10.000000/2.000000/12.000000:w/0/0.000000/7.000000/2.000000/10.000000:e/0/0.000000/7.000000/2.000000/10.000000:s/0/0.000000/7.000000/2.000000/10.000000:u/0/0.000000/5.000000/2.000000/7.000000,box=7.000000/13.611040/10.071930:9.000000/13.611040/12.071930/22.500000/0.000000/0.000000/8.000000/16.000000/8.000000:n/0/0.000000/0.000000/2.000000/0.000000:d/0/6.000000/3.000000/8.000000/5.000000:w/0/0.000000/0.000000/2.000000/0.000000:e/0/0.000000/0.000000/2.000000/0.000000:s/0/0.000000/0.000000/2.000000/0.000000:u180/0/8.000000/3.000000/10.000000/5.000000,box=10.071930/13.611040/7.000000:12.071930/13.611040/9.000000/0.000000/0.000000/-22.500000/8.000000/16.000000/8.000000:n/0/0.000000/0.000000/2.000000/0.000000:d90/0/6.000000/3.000000/8.000000/5.000000:w/0/0.000000/0.000000/2.000000/0.000000:e/0/0.000000/0.000000/2.000000/0.000000:s/0/0.000000/0.000000/2.000000/0.000000:u90/0/8.000000/3.000000/10.000000/5.000000,box=7.000000/13.611040/3.928070:9.000000/13.611040/5.928070/-22.500000/0.000000/0.000000/8.000000/16.000000/8.000000:n/0/0.000000/0.000000/2.000000/0.000000:d180/0/6.000000/3.000000/8.000000/5.000000:w/0/0.000000/0.000000/2.000000/0.000000:e/0/0.000000/0.000000/2.000000/0.000000:s/0/0.000000/0.000000/2.000000/0.000000:u/0/8.000000/3.000000/10.000000/5.000000,box=3.928070/13.611040/7.000000:5.928070/13.611040/9.000000/0.000000/0.000000/22.500000/8.000000/16.000000/8.000000:n/0/0.000000/0.000000/2.000000/0.000000:d270/0/6.000000/3.000000/8.000000/5.000000:w/0/0.000000/0.000000/2.000000/0.000000:e/0/0.000000/0.000000/2.000000/0.000000:s/0/0.000000/0.000000/2.000000/0.000000:u270/0/8.000000/3.000000/10.000000/5.000000,box=7.000000/13.000000/7.000000:9.000000/14.000000/9.000000:n/0/0.000000/2.000000/2.000000/3.000000:d/0/0.000000/3.000000/2.000000/5.000000:w/0/0.000000/2.000000/2.000000/3.000000:e/0/0.000000/2.000000/2.000000/3.000000:s/0/0.000000/2.000000/2.000000/3.000000:u/0/0.000000/0.000000/2.000000/2.000000,box=7.000000/14.000000/8.000000:9.000000/16.000000/8.000000/0.000000/-45.000000/0.000000/8.000000/16.000000/8.000000:n/0/0.000000/0.000000/2.000000/2.000000:d/0/0.000000/0.000000/2.000000/0.000000:w/0/0.000000/0.000000/0.000000/2.000000:e/0/0.000000/0.000000/0.000000/2.000000:s/0/0.000000/0.000000/2.000000/2.000000:u/0/0.000000/0.000000/2.000000/0.000000,box=7.000000/14.000000/8.000000:9.000000/16.000000/8.000000/0.000000/45.000000/0.000000/8.000000/16.000000/8.000000:n/0/0.000000/0.000000/2.000000/2.000000:d/0/0.000000/0.000000/2.000000/0.000000:w/0/0.000000/0.000000/0.000000/2.000000:e/0/0.000000/0.000000/0.000000/2.000000:s/0/0.000000/0.000000/2.000000/2.000000:u/0/0.000000/0.000000/2.000000/0.000000,box=7.000000/3.000000/8.000000:9.000000/10.000000/8.000000/0.000000/45.000000/0.000000/8.000000/16.000000/8.000000:n/0/3.000000/3.000000/5.000000/10.000000:d/0/11.000000/10.000000/13.000000/10.000000:w/0/11.000000/0.000000/11.000000/10.000000:e/0/13.000000/0.000000/13.000000/10.000000:s/0/3.000000/3.000000/5.000000/10.000000:u/0/11.000000/0.000000/13.000000/0.000000,box=7.000000/3.000000/8.000000:9.000000/10.000000/8.000000/0.000000/-45.000000/0.000000/8.000000/16.000000/8.000000:n/0/3.000000/3.000000/5.000000/10.000000:d180/0/11.000000/10.000000/13.000000/10.000000:w/0/13.000000/0.000000/13.000000/10.000000:e/0/11.000000/0.000000/11.000000/10.000000:s/0/3.000000/3.000000/5.000000/10.000000:u180/0/11.000000/0.000000/13.000000/0.000000 +[1.19-]modellist:id=%mangrove_propagule,state=hanging:false/age:3,box=4.500000/9.000000/8.000000:11.500000/15.000000/8.000000/0.000000/45.000000/0.000000/8.000000/0.000000/8.000000:n/0/4.000000/1.000000/11.000000/7.000000:s/0/4.000000/1.000000/11.000000/7.000000,box=8.000000/9.000000/4.500000:8.000000/15.000000/11.500000/0.000000/45.000000/0.000000/8.000000/0.000000/8.000000:w/0/4.000000/1.000000/11.000000/7.000000:e/0/4.000000/1.000000/11.000000/7.000000,box=8.000000/0.000000/7.000000:8.000000/9.000000/9.000000/0.000000/45.000000/0.000000/8.000000/0.000000/8.000000:w/0/7.000000/7.000000/9.000000/16.000000:e/0/7.000000/7.000000/9.000000/16.000000,box=7.000000/0.000000/8.000000:9.000000/9.000000/8.000000/0.000000/45.000000/0.000000/8.000000/0.000000/8.000000:n/0/7.000000/7.000000/9.000000/16.000000:s/0/7.000000/7.000000/9.000000/16.000000 +[1.19-]modellist:id=%mangrove_propagule,state=hanging:true/age:4,box=7.000000/10.000000/7.000000:9.000000/13.000000/9.000000:n/0/0.000000/7.000000/2.000000/10.000000:d/0/0.000000/10.000000/2.000000/12.000000:w/0/0.000000/7.000000/2.000000/10.000000:e/0/0.000000/7.000000/2.000000/10.000000:s/0/0.000000/7.000000/2.000000/10.000000:u/0/0.000000/5.000000/2.000000/7.000000,box=7.000000/13.611040/10.071930:9.000000/13.611040/12.071930/22.500000/0.000000/0.000000/8.000000/16.000000/8.000000:n/0/0.000000/0.000000/2.000000/0.000000:d/0/6.000000/3.000000/8.000000/5.000000:w/0/0.000000/0.000000/2.000000/0.000000:e/0/0.000000/0.000000/2.000000/0.000000:s/0/0.000000/0.000000/2.000000/0.000000:u180/0/8.000000/3.000000/10.000000/5.000000,box=10.071930/13.611040/7.000000:12.071930/13.611040/9.000000/0.000000/0.000000/-22.500000/8.000000/16.000000/8.000000:n/0/0.000000/0.000000/2.000000/0.000000:d90/0/6.000000/3.000000/8.000000/5.000000:w/0/0.000000/0.000000/2.000000/0.000000:e/0/0.000000/0.000000/2.000000/0.000000:s/0/0.000000/0.000000/2.000000/0.000000:u90/0/8.000000/3.000000/10.000000/5.000000,box=7.000000/13.611040/3.928070:9.000000/13.611040/5.928070/-22.500000/0.000000/0.000000/8.000000/16.000000/8.000000:n/0/0.000000/0.000000/2.000000/0.000000:d180/0/6.000000/3.000000/8.000000/5.000000:w/0/0.000000/0.000000/2.000000/0.000000:e/0/0.000000/0.000000/2.000000/0.000000:s/0/0.000000/0.000000/2.000000/0.000000:u/0/8.000000/3.000000/10.000000/5.000000,box=3.928070/13.611040/7.000000:5.928070/13.611040/9.000000/0.000000/0.000000/22.500000/8.000000/16.000000/8.000000:n/0/0.000000/0.000000/2.000000/0.000000:d270/0/6.000000/3.000000/8.000000/5.000000:w/0/0.000000/0.000000/2.000000/0.000000:e/0/0.000000/0.000000/2.000000/0.000000:s/0/0.000000/0.000000/2.000000/0.000000:u270/0/8.000000/3.000000/10.000000/5.000000,box=7.000000/13.000000/7.000000:9.000000/14.000000/9.000000:n/0/0.000000/2.000000/2.000000/3.000000:d/0/0.000000/3.000000/2.000000/5.000000:w/0/0.000000/2.000000/2.000000/3.000000:e/0/0.000000/2.000000/2.000000/3.000000:s/0/0.000000/2.000000/2.000000/3.000000:u/0/0.000000/0.000000/2.000000/2.000000,box=7.000000/14.000000/8.000000:9.000000/16.000000/8.000000/0.000000/-45.000000/0.000000/8.000000/16.000000/8.000000:n/0/0.000000/0.000000/2.000000/2.000000:d/0/0.000000/0.000000/2.000000/0.000000:w/0/0.000000/0.000000/0.000000/2.000000:e/0/0.000000/0.000000/0.000000/2.000000:s/0/0.000000/0.000000/2.000000/2.000000:u/0/0.000000/0.000000/2.000000/0.000000,box=7.000000/14.000000/8.000000:9.000000/16.000000/8.000000/0.000000/45.000000/0.000000/8.000000/16.000000/8.000000:n/0/0.000000/0.000000/2.000000/2.000000:d/0/0.000000/0.000000/2.000000/0.000000:w/0/0.000000/0.000000/0.000000/2.000000:e/0/0.000000/0.000000/0.000000/2.000000:s/0/0.000000/0.000000/2.000000/2.000000:u/0/0.000000/0.000000/2.000000/0.000000,box=7.000000/0.000000/8.000000:9.000000/10.000000/8.000000/0.000000/45.000000/0.000000/8.000000/16.000000/8.000000:n/0/3.000000/0.000000/5.000000/10.000000:d/0/11.000000/10.000000/13.000000/10.000000:w/0/11.000000/0.000000/11.000000/10.000000:e/0/13.000000/0.000000/13.000000/10.000000:s/0/3.000000/0.000000/5.000000/10.000000:u/0/11.000000/0.000000/13.000000/0.000000,box=7.000000/0.000000/8.000000:9.000000/10.000000/8.000000/0.000000/-45.000000/0.000000/8.000000/16.000000/8.000000:n/0/3.000000/0.000000/5.000000/10.000000:d180/0/11.000000/10.000000/13.000000/10.000000:w/0/13.000000/0.000000/13.000000/10.000000:e/0/11.000000/0.000000/11.000000/10.000000:s/0/3.000000/0.000000/5.000000/10.000000:u180/0/11.000000/0.000000/13.000000/0.000000 +[1.19-]modellist:id=%mangrove_propagule,state=hanging:false/age:4,box=4.500000/9.000000/8.000000:11.500000/15.000000/8.000000/0.000000/45.000000/0.000000/8.000000/0.000000/8.000000:n/0/4.000000/1.000000/11.000000/7.000000:s/0/4.000000/1.000000/11.000000/7.000000,box=8.000000/9.000000/4.500000:8.000000/15.000000/11.500000/0.000000/45.000000/0.000000/8.000000/0.000000/8.000000:w/0/4.000000/1.000000/11.000000/7.000000:e/0/4.000000/1.000000/11.000000/7.000000,box=8.000000/0.000000/7.000000:8.000000/9.000000/9.000000/0.000000/45.000000/0.000000/8.000000/0.000000/8.000000:w/0/7.000000/7.000000/9.000000/16.000000:e/0/7.000000/7.000000/9.000000/16.000000,box=7.000000/0.000000/8.000000:9.000000/9.000000/8.000000/0.000000/45.000000/0.000000/8.000000/0.000000/8.000000:n/0/7.000000/7.000000/9.000000/16.000000:s/0/7.000000/7.000000/9.000000/16.000000 +[1.19-]modellist:id=%mangrove_log,state=axis:x,box=0.000000/0.000000/0.000000:16.000000/16.000000/16.000000:n/0:d/1:w/0:e/0:s/0:u180/1:R/90/90/0 +[1.19-]modellist:id=%mangrove_log,state=axis:z,box=0.000000/0.000000/0.000000:16.000000/16.000000/16.000000:n/0:d/1:w/0:e/0:s/0:u180/1:R/90/0/0 +[1.19-]modellist:id=%mangrove_roots,box=0.000000/0.000000/8.000000:16.000000/16.000000/8.000000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000,box=8.000000/0.000000/0.000000:8.000000/16.000000/16.000000:w/0/0.000000/0.000000/16.000000/16.000000:e/0/0.000000/0.000000/16.000000/16.000000,box=0.000000/15.998000/0.000000:16.000000/16.000000/16.000000:d/1/0.000000/16.000000/16.000000/0.000000:u/1/0.000000/0.000000/16.000000/16.000000,box=0.000000/0.000000/0.000000:16.000000/0.002000/16.000000:d/1/0.000000/0.000000/16.000000/16.000000:u/1/0.000000/16.000000/16.000000/0.000000,box=0.000000/0.000000/0.000000:16.000000/16.000000/0.002000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/16.000000/0.000000/0.000000/16.000000,box=0.000000/0.000000/15.998000:16.000000/16.000000/16.000000:n/0/16.000000/0.000000/0.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000,box=0.000000/0.000000/0.000000:0.002000/16.000000/16.000000:w/0/0.000000/0.000000/16.000000/16.000000:e/0/16.000000/0.000000/0.000000/16.000000,box=15.998000/0.000000/0.000000:16.000000/16.000000/16.000000:w/0/16.000000/0.000000/0.000000/16.000000:e/0/0.000000/0.000000/16.000000/16.000000 +[1.19-]modellist:id=%muddy_mangrove_roots,state=axis:x,box=0.000000/0.000000/0.000000:16.000000/16.000000/16.000000:n/0:d/1:w/0:e/0:s/0:u/1:R/90/90/0 +[1.19-]modellist:id=%muddy_mangrove_roots,state=axis:z,box=0.000000/0.000000/0.000000:16.000000/16.000000/16.000000:n/0:d/1:w/0:e/0:s/0:u/1:R/90/0/0 +[1.19-]modellist:id=%stripped_mangrove_log,state=axis:x,box=0.000000/0.000000/0.000000:16.000000/16.000000/16.000000:n/0:d/1:w/0:e/0:s/0:u180/1:R/90/90/0 +[1.19-]modellist:id=%stripped_mangrove_log,state=axis:z,box=0.000000/0.000000/0.000000:16.000000/16.000000/16.000000:n/0:d/1:w/0:e/0:s/0:u180/1:R/90/0/0 +[1.19-]modellist:id=%mangrove_wood,state=axis:x,box=0.000000/0.000000/0.000000:16.000000/16.000000/16.000000:n/0:d/0:w/0:e/0:s/0:u/0:R/90/90/0 +[1.19-]modellist:id=%mangrove_wood,state=axis:z,box=0.000000/0.000000/0.000000:16.000000/16.000000/16.000000:n/0:d/0:w/0:e/0:s/0:u/0:R/90/0/0 +[1.19-]modellist:id=%stripped_mangrove_wood,state=axis:x,box=0.000000/0.000000/0.000000:16.000000/16.000000/16.000000:n/0:d/0:w/0:e/0:s/0:u/0:R/90/90/0 +[1.19-]modellist:id=%stripped_mangrove_wood,state=axis:z,box=0.000000/0.000000/0.000000:16.000000/16.000000/16.000000:n/0:d/0:w/0:e/0:s/0:u/0:R/90/0/0 +[1.19-]modellist:id=%mangrove_pressure_plate,state=powered:true,box=1.000000/0.000000/1.000000:15.000000/0.500000/15.000000:n/0/1.000000/15.000000/15.000000/15.500000:d/0/1.000000/1.000000/15.000000/15.000000:w/0/1.000000/15.000000/15.000000/15.500000:e/0/1.000000/15.000000/15.000000/15.500000:s/0/1.000000/15.000000/15.000000/15.500000:u/0/1.000000/1.000000/15.000000/15.000000 +[1.19-]modellist:id=%mangrove_pressure_plate,state=powered:false,box=1.000000/0.000000/1.000000:15.000000/1.000000/15.000000:n/0/1.000000/15.000000/15.000000/16.000000:d/0/1.000000/1.000000/15.000000/15.000000:w/0/1.000000/15.000000/15.000000/16.000000:e/0/1.000000/15.000000/15.000000/16.000000:s/0/1.000000/15.000000/15.000000/16.000000:u/0/1.000000/1.000000/15.000000/15.000000 +[1.19-]modellist:id=%mangrove_trapdoor,state=facing:north/half:top/open:true,box=0.000000/0.000000/13.000000:16.000000/16.000000/16.000000:n/0/0.000000/16.000000/16.000000/0.000000:d/0/0.000000/0.000000/16.000000/3.000000:w90/0/0.000000/0.000000/16.000000/3.000000:e90/0/0.000000/3.000000/16.000000/0.000000:s/0/0.000000/16.000000/16.000000/0.000000:u/0/0.000000/3.000000/16.000000/0.000000:R/180/180/0 +[1.19-]modellist:id=%mangrove_trapdoor,state=facing:north/half:top/open:false,box=0.000000/13.000000/0.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/16.000000/3.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/0.000000/16.000000/3.000000:e/0/0.000000/0.000000/16.000000/3.000000:s/0/0.000000/0.000000/16.000000/3.000000:u/0/0.000000/16.000000/16.000000/0.000000 +[1.19-]modellist:id=%mangrove_trapdoor,state=facing:north/half:bottom/open:true,box=0.000000/0.000000/13.000000:16.000000/16.000000/16.000000:n/0/0.000000/16.000000/16.000000/0.000000:d/0/0.000000/0.000000/16.000000/3.000000:w90/0/0.000000/0.000000/16.000000/3.000000:e90/0/0.000000/3.000000/16.000000/0.000000:s/0/0.000000/16.000000/16.000000/0.000000:u/0/0.000000/3.000000/16.000000/0.000000 +[1.19-]modellist:id=%mangrove_trapdoor,state=facing:north/half:bottom/open:false,box=0.000000/0.000000/0.000000:16.000000/3.000000/16.000000:n/0/0.000000/0.000000/16.000000/3.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/0.000000/16.000000/3.000000:e/0/0.000000/0.000000/16.000000/3.000000:s/0/0.000000/0.000000/16.000000/3.000000:u/0/0.000000/16.000000/16.000000/0.000000 +[1.19-]modellist:id=%mangrove_trapdoor,state=facing:south/half:top/open:true,box=0.000000/0.000000/13.000000:16.000000/16.000000/16.000000:n/0/0.000000/16.000000/16.000000/0.000000:d/0/0.000000/0.000000/16.000000/3.000000:w90/0/0.000000/0.000000/16.000000/3.000000:e90/0/0.000000/3.000000/16.000000/0.000000:s/0/0.000000/16.000000/16.000000/0.000000:u/0/0.000000/3.000000/16.000000/0.000000:R/180/0/0 +[1.19-]modellist:id=%mangrove_trapdoor,state=facing:south/half:top/open:false,box=0.000000/13.000000/0.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/16.000000/3.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/0.000000/16.000000/3.000000:e/0/0.000000/0.000000/16.000000/3.000000:s/0/0.000000/0.000000/16.000000/3.000000:u/0/0.000000/16.000000/16.000000/0.000000:R/0/180/0 +[1.19-]modellist:id=%mangrove_trapdoor,state=facing:south/half:bottom/open:true,box=0.000000/0.000000/13.000000:16.000000/16.000000/16.000000:n/0/0.000000/16.000000/16.000000/0.000000:d/0/0.000000/0.000000/16.000000/3.000000:w90/0/0.000000/0.000000/16.000000/3.000000:e90/0/0.000000/3.000000/16.000000/0.000000:s/0/0.000000/16.000000/16.000000/0.000000:u/0/0.000000/3.000000/16.000000/0.000000:R/0/180/0 +[1.19-]modellist:id=%mangrove_trapdoor,state=facing:south/half:bottom/open:false,box=0.000000/0.000000/0.000000:16.000000/3.000000/16.000000:n/0/0.000000/0.000000/16.000000/3.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/0.000000/16.000000/3.000000:e/0/0.000000/0.000000/16.000000/3.000000:s/0/0.000000/0.000000/16.000000/3.000000:u/0/0.000000/16.000000/16.000000/0.000000:R/0/180/0 +[1.19-]modellist:id=%mangrove_trapdoor,state=facing:west/half:top/open:true,box=0.000000/0.000000/13.000000:16.000000/16.000000/16.000000:n/0/0.000000/16.000000/16.000000/0.000000:d/0/0.000000/0.000000/16.000000/3.000000:w90/0/0.000000/0.000000/16.000000/3.000000:e90/0/0.000000/3.000000/16.000000/0.000000:s/0/0.000000/16.000000/16.000000/0.000000:u/0/0.000000/3.000000/16.000000/0.000000:R/180/90/0 +[1.19-]modellist:id=%mangrove_trapdoor,state=facing:west/half:top/open:false,box=0.000000/13.000000/0.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/16.000000/3.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/0.000000/16.000000/3.000000:e/0/0.000000/0.000000/16.000000/3.000000:s/0/0.000000/0.000000/16.000000/3.000000:u/0/0.000000/16.000000/16.000000/0.000000:R/0/270/0 +[1.19-]modellist:id=%mangrove_trapdoor,state=facing:west/half:bottom/open:true,box=0.000000/0.000000/13.000000:16.000000/16.000000/16.000000:n/0/0.000000/16.000000/16.000000/0.000000:d/0/0.000000/0.000000/16.000000/3.000000:w90/0/0.000000/0.000000/16.000000/3.000000:e90/0/0.000000/3.000000/16.000000/0.000000:s/0/0.000000/16.000000/16.000000/0.000000:u/0/0.000000/3.000000/16.000000/0.000000:R/0/270/0 +[1.19-]modellist:id=%mangrove_trapdoor,state=facing:west/half:bottom/open:false,box=0.000000/0.000000/0.000000:16.000000/3.000000/16.000000:n/0/0.000000/0.000000/16.000000/3.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/0.000000/16.000000/3.000000:e/0/0.000000/0.000000/16.000000/3.000000:s/0/0.000000/0.000000/16.000000/3.000000:u/0/0.000000/16.000000/16.000000/0.000000:R/0/270/0 +[1.19-]modellist:id=%mangrove_trapdoor,state=facing:east/half:top/open:true,box=0.000000/0.000000/13.000000:16.000000/16.000000/16.000000:n/0/0.000000/16.000000/16.000000/0.000000:d/0/0.000000/0.000000/16.000000/3.000000:w90/0/0.000000/0.000000/16.000000/3.000000:e90/0/0.000000/3.000000/16.000000/0.000000:s/0/0.000000/16.000000/16.000000/0.000000:u/0/0.000000/3.000000/16.000000/0.000000:R/180/270/0 +[1.19-]modellist:id=%mangrove_trapdoor,state=facing:east/half:top/open:false,box=0.000000/13.000000/0.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/16.000000/3.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/0.000000/16.000000/3.000000:e/0/0.000000/0.000000/16.000000/3.000000:s/0/0.000000/0.000000/16.000000/3.000000:u/0/0.000000/16.000000/16.000000/0.000000:R/0/90/0 +[1.19-]modellist:id=%mangrove_trapdoor,state=facing:east/half:bottom/open:true,box=0.000000/0.000000/13.000000:16.000000/16.000000/16.000000:n/0/0.000000/16.000000/16.000000/0.000000:d/0/0.000000/0.000000/16.000000/3.000000:w90/0/0.000000/0.000000/16.000000/3.000000:e90/0/0.000000/3.000000/16.000000/0.000000:s/0/0.000000/16.000000/16.000000/0.000000:u/0/0.000000/3.000000/16.000000/0.000000:R/0/90/0 +[1.19-]modellist:id=%mangrove_trapdoor,state=facing:east/half:bottom/open:false,box=0.000000/0.000000/0.000000:16.000000/3.000000/16.000000:n/0/0.000000/0.000000/16.000000/3.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/0.000000/16.000000/3.000000:e/0/0.000000/0.000000/16.000000/3.000000:s/0/0.000000/0.000000/16.000000/3.000000:u/0/0.000000/16.000000/16.000000/0.000000:R/0/90/0 +[1.19-]modellist:id=%potted_mangrove_propagule,box=4.500000/9.000000/8.000000:11.500000/15.000000/8.000000/0.000000/45.000000/0.000000/8.000000/0.000000/8.000000:n/0/11.000000/1.000000/4.000000/7.000000:s/0/4.000000/1.000000/11.000000/7.000000,box=8.000000/9.000000/4.500000:8.000000/15.000000/11.500000/0.000000/45.000000/0.000000/8.000000/0.000000/8.000000:w/0/4.000000/1.000000/11.000000/7.000000:e/0/11.000000/1.000000/4.000000/7.000000,box=8.000000/0.000000/7.000000:8.000000/9.000000/9.000000/0.000000/45.000000/0.000000/8.000000/0.000000/8.000000:w/0/7.000000/7.000000/9.000000/16.000000:e/0/7.000000/7.000000/9.000000/16.000000,box=7.000000/0.000000/8.000000:9.000000/9.000000/8.000000/0.000000/45.000000/0.000000/8.000000/0.000000/8.000000:n/0/7.000000/7.000000/9.000000/16.000000:s/0/7.000000/7.000000/9.000000/16.000000,box=5.000000/0.000000/5.000000:6.000000/6.000000/11.000000:n/1/10.000000/10.000000/11.000000/16.000000:d/1/5.000000/5.000000/6.000000/11.000000:w/1/5.000000/10.000000/11.000000/16.000000:e/1/5.000000/10.000000/11.000000/16.000000:s/1/5.000000/10.000000/6.000000/16.000000:u/1/5.000000/5.000000/6.000000/11.000000,box=10.000000/0.000000/5.000000:11.000000/6.000000/11.000000:n/1/5.000000/10.000000/6.000000/16.000000:d/1/10.000000/5.000000/11.000000/11.000000:w/1/5.000000/10.000000/11.000000/16.000000:e/1/5.000000/10.000000/11.000000/16.000000:s/1/10.000000/10.000000/11.000000/16.000000:u/1/10.000000/5.000000/11.000000/11.000000,box=6.000000/0.000000/5.000000:10.000000/6.000000/6.000000:n/1/6.000000/10.000000/10.000000/16.000000:d/1/6.000000/10.000000/10.000000/11.000000:s/1/6.000000/10.000000/10.000000/16.000000:u/1/6.000000/5.000000/10.000000/6.000000,box=6.000000/0.000000/10.000000:10.000000/6.000000/11.000000:n/1/6.000000/10.000000/10.000000/16.000000:d/1/6.000000/5.000000/10.000000/6.000000:s/1/6.000000/10.000000/10.000000/16.000000:u/1/6.000000/10.000000/10.000000/11.000000,box=6.000000/0.000000/6.000000:10.000000/4.000000/10.000000:d/1/6.000000/12.000000/10.000000/16.000000:u/2/6.000000/6.000000/10.000000/10.000000 +[1.19-]modellist:id=%mangrove_button,state=facing:north/face:floor/powered:true,box=5.000000/0.000000/6.000000:11.000000/1.000000/10.000000:n/0/5.000000/14.000000/11.000000/15.000000:d/0/5.000000/6.000000/11.000000/10.000000:w/0/6.000000/14.000000/10.000000/15.000000:e/0/6.000000/14.000000/10.000000/15.000000:s/0/5.000000/14.000000/11.000000/15.000000:u/0/5.000000/10.000000/11.000000/6.000000 +[1.19-]modellist:id=%mangrove_button,state=facing:north/face:floor/powered:false,box=5.000000/0.000000/6.000000:11.000000/2.000000/10.000000:n/0/5.000000/14.000000/11.000000/16.000000:d/0/5.000000/6.000000/11.000000/10.000000:w/0/6.000000/14.000000/10.000000/16.000000:e/0/6.000000/14.000000/10.000000/16.000000:s/0/5.000000/14.000000/11.000000/16.000000:u/0/5.000000/10.000000/11.000000/6.000000 +[1.19-]modellist:id=%mangrove_button,state=facing:south/face:floor/powered:true,box=5.000000/0.000000/6.000000:11.000000/1.000000/10.000000:n/0/5.000000/14.000000/11.000000/15.000000:d/0/5.000000/6.000000/11.000000/10.000000:w/0/6.000000/14.000000/10.000000/15.000000:e/0/6.000000/14.000000/10.000000/15.000000:s/0/5.000000/14.000000/11.000000/15.000000:u/0/5.000000/10.000000/11.000000/6.000000:R/0/180/0 +[1.19-]modellist:id=%mangrove_button,state=facing:south/face:floor/powered:false,box=5.000000/0.000000/6.000000:11.000000/2.000000/10.000000:n/0/5.000000/14.000000/11.000000/16.000000:d/0/5.000000/6.000000/11.000000/10.000000:w/0/6.000000/14.000000/10.000000/16.000000:e/0/6.000000/14.000000/10.000000/16.000000:s/0/5.000000/14.000000/11.000000/16.000000:u/0/5.000000/10.000000/11.000000/6.000000:R/0/180/0 +[1.19-]modellist:id=%mangrove_button,state=facing:west/face:floor/powered:true,box=5.000000/0.000000/6.000000:11.000000/1.000000/10.000000:n/0/5.000000/14.000000/11.000000/15.000000:d/0/5.000000/6.000000/11.000000/10.000000:w/0/6.000000/14.000000/10.000000/15.000000:e/0/6.000000/14.000000/10.000000/15.000000:s/0/5.000000/14.000000/11.000000/15.000000:u/0/5.000000/10.000000/11.000000/6.000000:R/0/270/0 +[1.19-]modellist:id=%mangrove_button,state=facing:west/face:floor/powered:false,box=5.000000/0.000000/6.000000:11.000000/2.000000/10.000000:n/0/5.000000/14.000000/11.000000/16.000000:d/0/5.000000/6.000000/11.000000/10.000000:w/0/6.000000/14.000000/10.000000/16.000000:e/0/6.000000/14.000000/10.000000/16.000000:s/0/5.000000/14.000000/11.000000/16.000000:u/0/5.000000/10.000000/11.000000/6.000000:R/0/270/0 +[1.19-]modellist:id=%mangrove_button,state=facing:east/face:floor/powered:true,box=5.000000/0.000000/6.000000:11.000000/1.000000/10.000000:n/0/5.000000/14.000000/11.000000/15.000000:d/0/5.000000/6.000000/11.000000/10.000000:w/0/6.000000/14.000000/10.000000/15.000000:e/0/6.000000/14.000000/10.000000/15.000000:s/0/5.000000/14.000000/11.000000/15.000000:u/0/5.000000/10.000000/11.000000/6.000000:R/0/90/0 +[1.19-]modellist:id=%mangrove_button,state=facing:east/face:floor/powered:false,box=5.000000/0.000000/6.000000:11.000000/2.000000/10.000000:n/0/5.000000/14.000000/11.000000/16.000000:d/0/5.000000/6.000000/11.000000/10.000000:w/0/6.000000/14.000000/10.000000/16.000000:e/0/6.000000/14.000000/10.000000/16.000000:s/0/5.000000/14.000000/11.000000/16.000000:u/0/5.000000/10.000000/11.000000/6.000000:R/0/90/0 +[1.19-]modellist:id=%mangrove_button,state=facing:north/face:wall/powered:true,box=5.000000/0.000000/6.000000:11.000000/1.000000/10.000000:n/0/5.000000/14.000000/11.000000/15.000000:d/0/5.000000/6.000000/11.000000/10.000000:w/0/6.000000/14.000000/10.000000/15.000000:e/0/6.000000/14.000000/10.000000/15.000000:s/0/5.000000/14.000000/11.000000/15.000000:u/0/5.000000/10.000000/11.000000/6.000000:R/90/0/0 +[1.19-]modellist:id=%mangrove_button,state=facing:north/face:wall/powered:false,box=5.000000/0.000000/6.000000:11.000000/2.000000/10.000000:n/0/5.000000/14.000000/11.000000/16.000000:d/0/5.000000/6.000000/11.000000/10.000000:w/0/6.000000/14.000000/10.000000/16.000000:e/0/6.000000/14.000000/10.000000/16.000000:s/0/5.000000/14.000000/11.000000/16.000000:u/0/5.000000/10.000000/11.000000/6.000000:R/90/0/0 +[1.19-]modellist:id=%mangrove_button,state=facing:south/face:wall/powered:true,box=5.000000/0.000000/6.000000:11.000000/1.000000/10.000000:n/0/5.000000/14.000000/11.000000/15.000000:d/0/5.000000/6.000000/11.000000/10.000000:w/0/6.000000/14.000000/10.000000/15.000000:e/0/6.000000/14.000000/10.000000/15.000000:s/0/5.000000/14.000000/11.000000/15.000000:u/0/5.000000/10.000000/11.000000/6.000000:R/90/180/0 +[1.19-]modellist:id=%mangrove_button,state=facing:south/face:wall/powered:false,box=5.000000/0.000000/6.000000:11.000000/2.000000/10.000000:n/0/5.000000/14.000000/11.000000/16.000000:d/0/5.000000/6.000000/11.000000/10.000000:w/0/6.000000/14.000000/10.000000/16.000000:e/0/6.000000/14.000000/10.000000/16.000000:s/0/5.000000/14.000000/11.000000/16.000000:u/0/5.000000/10.000000/11.000000/6.000000:R/90/180/0 +[1.19-]modellist:id=%mangrove_button,state=facing:west/face:wall/powered:true,box=5.000000/0.000000/6.000000:11.000000/1.000000/10.000000:n/0/5.000000/14.000000/11.000000/15.000000:d/0/5.000000/6.000000/11.000000/10.000000:w/0/6.000000/14.000000/10.000000/15.000000:e/0/6.000000/14.000000/10.000000/15.000000:s/0/5.000000/14.000000/11.000000/15.000000:u/0/5.000000/10.000000/11.000000/6.000000:R/90/270/0 +[1.19-]modellist:id=%mangrove_button,state=facing:west/face:wall/powered:false,box=5.000000/0.000000/6.000000:11.000000/2.000000/10.000000:n/0/5.000000/14.000000/11.000000/16.000000:d/0/5.000000/6.000000/11.000000/10.000000:w/0/6.000000/14.000000/10.000000/16.000000:e/0/6.000000/14.000000/10.000000/16.000000:s/0/5.000000/14.000000/11.000000/16.000000:u/0/5.000000/10.000000/11.000000/6.000000:R/90/270/0 +[1.19-]modellist:id=%mangrove_button,state=facing:east/face:wall/powered:true,box=5.000000/0.000000/6.000000:11.000000/1.000000/10.000000:n/0/5.000000/14.000000/11.000000/15.000000:d/0/5.000000/6.000000/11.000000/10.000000:w/0/6.000000/14.000000/10.000000/15.000000:e/0/6.000000/14.000000/10.000000/15.000000:s/0/5.000000/14.000000/11.000000/15.000000:u/0/5.000000/10.000000/11.000000/6.000000:R/90/90/0 +[1.19-]modellist:id=%mangrove_button,state=facing:east/face:wall/powered:false,box=5.000000/0.000000/6.000000:11.000000/2.000000/10.000000:n/0/5.000000/14.000000/11.000000/16.000000:d/0/5.000000/6.000000/11.000000/10.000000:w/0/6.000000/14.000000/10.000000/16.000000:e/0/6.000000/14.000000/10.000000/16.000000:s/0/5.000000/14.000000/11.000000/16.000000:u/0/5.000000/10.000000/11.000000/6.000000:R/90/90/0 +[1.19-]modellist:id=%mangrove_button,state=facing:north/face:ceiling/powered:true,box=5.000000/0.000000/6.000000:11.000000/1.000000/10.000000:n/0/5.000000/14.000000/11.000000/15.000000:d/0/5.000000/6.000000/11.000000/10.000000:w/0/6.000000/14.000000/10.000000/15.000000:e/0/6.000000/14.000000/10.000000/15.000000:s/0/5.000000/14.000000/11.000000/15.000000:u/0/5.000000/10.000000/11.000000/6.000000:R/180/180/0 +[1.19-]modellist:id=%mangrove_button,state=facing:north/face:ceiling/powered:false,box=5.000000/0.000000/6.000000:11.000000/2.000000/10.000000:n/0/5.000000/14.000000/11.000000/16.000000:d/0/5.000000/6.000000/11.000000/10.000000:w/0/6.000000/14.000000/10.000000/16.000000:e/0/6.000000/14.000000/10.000000/16.000000:s/0/5.000000/14.000000/11.000000/16.000000:u/0/5.000000/10.000000/11.000000/6.000000:R/180/180/0 +[1.19-]modellist:id=%mangrove_button,state=facing:south/face:ceiling/powered:true,box=5.000000/0.000000/6.000000:11.000000/1.000000/10.000000:n/0/5.000000/14.000000/11.000000/15.000000:d/0/5.000000/6.000000/11.000000/10.000000:w/0/6.000000/14.000000/10.000000/15.000000:e/0/6.000000/14.000000/10.000000/15.000000:s/0/5.000000/14.000000/11.000000/15.000000:u/0/5.000000/10.000000/11.000000/6.000000:R/180/0/0 +[1.19-]modellist:id=%mangrove_button,state=facing:south/face:ceiling/powered:false,box=5.000000/0.000000/6.000000:11.000000/2.000000/10.000000:n/0/5.000000/14.000000/11.000000/16.000000:d/0/5.000000/6.000000/11.000000/10.000000:w/0/6.000000/14.000000/10.000000/16.000000:e/0/6.000000/14.000000/10.000000/16.000000:s/0/5.000000/14.000000/11.000000/16.000000:u/0/5.000000/10.000000/11.000000/6.000000:R/180/0/0 +[1.19-]modellist:id=%mangrove_button,state=facing:west/face:ceiling/powered:true,box=5.000000/0.000000/6.000000:11.000000/1.000000/10.000000:n/0/5.000000/14.000000/11.000000/15.000000:d/0/5.000000/6.000000/11.000000/10.000000:w/0/6.000000/14.000000/10.000000/15.000000:e/0/6.000000/14.000000/10.000000/15.000000:s/0/5.000000/14.000000/11.000000/15.000000:u/0/5.000000/10.000000/11.000000/6.000000:R/180/90/0 +[1.19-]modellist:id=%mangrove_button,state=facing:west/face:ceiling/powered:false,box=5.000000/0.000000/6.000000:11.000000/2.000000/10.000000:n/0/5.000000/14.000000/11.000000/16.000000:d/0/5.000000/6.000000/11.000000/10.000000:w/0/6.000000/14.000000/10.000000/16.000000:e/0/6.000000/14.000000/10.000000/16.000000:s/0/5.000000/14.000000/11.000000/16.000000:u/0/5.000000/10.000000/11.000000/6.000000:R/180/90/0 +[1.19-]modellist:id=%mangrove_button,state=facing:east/face:ceiling/powered:true,box=5.000000/0.000000/6.000000:11.000000/1.000000/10.000000:n/0/5.000000/14.000000/11.000000/15.000000:d/0/5.000000/6.000000/11.000000/10.000000:w/0/6.000000/14.000000/10.000000/15.000000:e/0/6.000000/14.000000/10.000000/15.000000:s/0/5.000000/14.000000/11.000000/15.000000:u/0/5.000000/10.000000/11.000000/6.000000:R/180/270/0 +[1.19-]modellist:id=%mangrove_button,state=facing:east/face:ceiling/powered:false,box=5.000000/0.000000/6.000000:11.000000/2.000000/10.000000:n/0/5.000000/14.000000/11.000000/16.000000:d/0/5.000000/6.000000/11.000000/10.000000:w/0/6.000000/14.000000/10.000000/16.000000:e/0/6.000000/14.000000/10.000000/16.000000:s/0/5.000000/14.000000/11.000000/16.000000:u/0/5.000000/10.000000/11.000000/6.000000:R/180/270/0 +[1.19-]modellist:id=%mangrove_stairs,state=facing:north/half:top/shape:straight,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/0/0.000000/0.000000/16.000000/16.000000:R/180/270/0,box=8.000000/8.000000/0.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/8.000000/8.000000:w/0/0.000000/0.000000/16.000000/8.000000:e/0/0.000000/0.000000/16.000000/8.000000:s/0/8.000000/0.000000/16.000000/8.000000:u/0/8.000000/0.000000/16.000000/16.000000:R/180/270/0 +[1.19-]modellist:id=%mangrove_stairs,state=facing:north/half:top/shape:inner_left,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/0/0.000000/0.000000/16.000000/16.000000:R/180/270/0,box=8.000000/8.000000/0.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/8.000000/8.000000:w/0/0.000000/0.000000/16.000000/8.000000:e/0/0.000000/0.000000/16.000000/8.000000:s/0/8.000000/0.000000/16.000000/8.000000:u/0/8.000000/0.000000/16.000000/16.000000:R/180/270/0,box=0.000000/8.000000/8.000000:8.000000/16.000000/16.000000:n/0/8.000000/0.000000/16.000000/8.000000:w/0/8.000000/0.000000/16.000000/8.000000:s/0/0.000000/0.000000/8.000000/8.000000:u/0/0.000000/8.000000/8.000000/16.000000:R/180/270/0 +[1.19-]modellist:id=%mangrove_stairs,state=facing:north/half:top/shape:inner_right,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/0/0.000000/0.000000/16.000000/16.000000:R/180/0/0,box=8.000000/8.000000/0.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/8.000000/8.000000:w/0/0.000000/0.000000/16.000000/8.000000:e/0/0.000000/0.000000/16.000000/8.000000:s/0/8.000000/0.000000/16.000000/8.000000:u/0/8.000000/0.000000/16.000000/16.000000:R/180/0/0,box=0.000000/8.000000/8.000000:8.000000/16.000000/16.000000:n/0/8.000000/0.000000/16.000000/8.000000:w/0/8.000000/0.000000/16.000000/8.000000:s/0/0.000000/0.000000/8.000000/8.000000:u/0/0.000000/8.000000/8.000000/16.000000:R/180/0/0 +[1.19-]modellist:id=%mangrove_stairs,state=facing:north/half:top/shape:outer_left,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/0/0.000000/0.000000/16.000000/16.000000:R/180/270/0,box=8.000000/8.000000/8.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/8.000000/8.000000:w/0/8.000000/0.000000/16.000000/8.000000:e/0/0.000000/0.000000/8.000000/8.000000:s/0/8.000000/0.000000/16.000000/8.000000:u/0/8.000000/8.000000/16.000000/16.000000:R/180/270/0 +[1.19-]modellist:id=%mangrove_stairs,state=facing:north/half:top/shape:outer_right,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/0/0.000000/0.000000/16.000000/16.000000:R/180/0/0,box=8.000000/8.000000/8.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/8.000000/8.000000:w/0/8.000000/0.000000/16.000000/8.000000:e/0/0.000000/0.000000/8.000000/8.000000:s/0/8.000000/0.000000/16.000000/8.000000:u/0/8.000000/8.000000/16.000000/16.000000:R/180/0/0 +[1.19-]modellist:id=%mangrove_stairs,state=facing:north/half:bottom/shape:straight,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/0/0.000000/0.000000/16.000000/16.000000:R/0/270/0,box=8.000000/8.000000/0.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/8.000000/8.000000:w/0/0.000000/0.000000/16.000000/8.000000:e/0/0.000000/0.000000/16.000000/8.000000:s/0/8.000000/0.000000/16.000000/8.000000:u/0/8.000000/0.000000/16.000000/16.000000:R/0/270/0 +[1.19-]modellist:id=%mangrove_stairs,state=facing:north/half:bottom/shape:inner_left,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/0/0.000000/0.000000/16.000000/16.000000:R/0/180/0,box=8.000000/8.000000/0.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/8.000000/8.000000:w/0/0.000000/0.000000/16.000000/8.000000:e/0/0.000000/0.000000/16.000000/8.000000:s/0/8.000000/0.000000/16.000000/8.000000:u/0/8.000000/0.000000/16.000000/16.000000:R/0/180/0,box=0.000000/8.000000/8.000000:8.000000/16.000000/16.000000:n/0/8.000000/0.000000/16.000000/8.000000:w/0/8.000000/0.000000/16.000000/8.000000:s/0/0.000000/0.000000/8.000000/8.000000:u/0/0.000000/8.000000/8.000000/16.000000:R/0/180/0 +[1.19-]modellist:id=%mangrove_stairs,state=facing:north/half:bottom/shape:inner_right,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/0/0.000000/0.000000/16.000000/16.000000:R/0/270/0,box=8.000000/8.000000/0.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/8.000000/8.000000:w/0/0.000000/0.000000/16.000000/8.000000:e/0/0.000000/0.000000/16.000000/8.000000:s/0/8.000000/0.000000/16.000000/8.000000:u/0/8.000000/0.000000/16.000000/16.000000:R/0/270/0,box=0.000000/8.000000/8.000000:8.000000/16.000000/16.000000:n/0/8.000000/0.000000/16.000000/8.000000:w/0/8.000000/0.000000/16.000000/8.000000:s/0/0.000000/0.000000/8.000000/8.000000:u/0/0.000000/8.000000/8.000000/16.000000:R/0/270/0 +[1.19-]modellist:id=%mangrove_stairs,state=facing:north/half:bottom/shape:outer_left,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/0/0.000000/0.000000/16.000000/16.000000:R/0/180/0,box=8.000000/8.000000/8.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/8.000000/8.000000:w/0/8.000000/0.000000/16.000000/8.000000:e/0/0.000000/0.000000/8.000000/8.000000:s/0/8.000000/0.000000/16.000000/8.000000:u/0/8.000000/8.000000/16.000000/16.000000:R/0/180/0 +[1.19-]modellist:id=%mangrove_stairs,state=facing:north/half:bottom/shape:outer_right,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/0/0.000000/0.000000/16.000000/16.000000:R/0/270/0,box=8.000000/8.000000/8.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/8.000000/8.000000:w/0/8.000000/0.000000/16.000000/8.000000:e/0/0.000000/0.000000/8.000000/8.000000:s/0/8.000000/0.000000/16.000000/8.000000:u/0/8.000000/8.000000/16.000000/16.000000:R/0/270/0 +[1.19-]modellist:id=%mangrove_stairs,state=facing:south/half:top/shape:straight,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/0/0.000000/0.000000/16.000000/16.000000:R/180/90/0,box=8.000000/8.000000/0.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/8.000000/8.000000:w/0/0.000000/0.000000/16.000000/8.000000:e/0/0.000000/0.000000/16.000000/8.000000:s/0/8.000000/0.000000/16.000000/8.000000:u/0/8.000000/0.000000/16.000000/16.000000:R/180/90/0 +[1.19-]modellist:id=%mangrove_stairs,state=facing:south/half:top/shape:inner_left,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/0/0.000000/0.000000/16.000000/16.000000:R/180/90/0,box=8.000000/8.000000/0.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/8.000000/8.000000:w/0/0.000000/0.000000/16.000000/8.000000:e/0/0.000000/0.000000/16.000000/8.000000:s/0/8.000000/0.000000/16.000000/8.000000:u/0/8.000000/0.000000/16.000000/16.000000:R/180/90/0,box=0.000000/8.000000/8.000000:8.000000/16.000000/16.000000:n/0/8.000000/0.000000/16.000000/8.000000:w/0/8.000000/0.000000/16.000000/8.000000:s/0/0.000000/0.000000/8.000000/8.000000:u/0/0.000000/8.000000/8.000000/16.000000:R/180/90/0 +[1.19-]modellist:id=%mangrove_stairs,state=facing:south/half:top/shape:inner_right,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/0/0.000000/0.000000/16.000000/16.000000:R/180/180/0,box=8.000000/8.000000/0.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/8.000000/8.000000:w/0/0.000000/0.000000/16.000000/8.000000:e/0/0.000000/0.000000/16.000000/8.000000:s/0/8.000000/0.000000/16.000000/8.000000:u/0/8.000000/0.000000/16.000000/16.000000:R/180/180/0,box=0.000000/8.000000/8.000000:8.000000/16.000000/16.000000:n/0/8.000000/0.000000/16.000000/8.000000:w/0/8.000000/0.000000/16.000000/8.000000:s/0/0.000000/0.000000/8.000000/8.000000:u/0/0.000000/8.000000/8.000000/16.000000:R/180/180/0 +[1.19-]modellist:id=%mangrove_stairs,state=facing:south/half:top/shape:outer_left,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/0/0.000000/0.000000/16.000000/16.000000:R/180/90/0,box=8.000000/8.000000/8.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/8.000000/8.000000:w/0/8.000000/0.000000/16.000000/8.000000:e/0/0.000000/0.000000/8.000000/8.000000:s/0/8.000000/0.000000/16.000000/8.000000:u/0/8.000000/8.000000/16.000000/16.000000:R/180/90/0 +[1.19-]modellist:id=%mangrove_stairs,state=facing:south/half:top/shape:outer_right,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/0/0.000000/0.000000/16.000000/16.000000:R/180/180/0,box=8.000000/8.000000/8.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/8.000000/8.000000:w/0/8.000000/0.000000/16.000000/8.000000:e/0/0.000000/0.000000/8.000000/8.000000:s/0/8.000000/0.000000/16.000000/8.000000:u/0/8.000000/8.000000/16.000000/16.000000:R/180/180/0 +[1.19-]modellist:id=%mangrove_stairs,state=facing:south/half:bottom/shape:straight,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/0/0.000000/0.000000/16.000000/16.000000:R/0/90/0,box=8.000000/8.000000/0.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/8.000000/8.000000:w/0/0.000000/0.000000/16.000000/8.000000:e/0/0.000000/0.000000/16.000000/8.000000:s/0/8.000000/0.000000/16.000000/8.000000:u/0/8.000000/0.000000/16.000000/16.000000:R/0/90/0 +[1.19-]modellist:id=%mangrove_stairs,state=facing:south/half:bottom/shape:inner_left,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/0/0.000000/0.000000/16.000000/16.000000,box=8.000000/8.000000/0.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/8.000000/8.000000:w/0/0.000000/0.000000/16.000000/8.000000:e/0/0.000000/0.000000/16.000000/8.000000:s/0/8.000000/0.000000/16.000000/8.000000:u/0/8.000000/0.000000/16.000000/16.000000,box=0.000000/8.000000/8.000000:8.000000/16.000000/16.000000:n/0/8.000000/0.000000/16.000000/8.000000:w/0/8.000000/0.000000/16.000000/8.000000:s/0/0.000000/0.000000/8.000000/8.000000:u/0/0.000000/8.000000/8.000000/16.000000 +[1.19-]modellist:id=%mangrove_stairs,state=facing:south/half:bottom/shape:inner_right,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/0/0.000000/0.000000/16.000000/16.000000:R/0/90/0,box=8.000000/8.000000/0.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/8.000000/8.000000:w/0/0.000000/0.000000/16.000000/8.000000:e/0/0.000000/0.000000/16.000000/8.000000:s/0/8.000000/0.000000/16.000000/8.000000:u/0/8.000000/0.000000/16.000000/16.000000:R/0/90/0,box=0.000000/8.000000/8.000000:8.000000/16.000000/16.000000:n/0/8.000000/0.000000/16.000000/8.000000:w/0/8.000000/0.000000/16.000000/8.000000:s/0/0.000000/0.000000/8.000000/8.000000:u/0/0.000000/8.000000/8.000000/16.000000:R/0/90/0 +[1.19-]modellist:id=%mangrove_stairs,state=facing:south/half:bottom/shape:outer_left,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/0/0.000000/0.000000/16.000000/16.000000,box=8.000000/8.000000/8.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/8.000000/8.000000:w/0/8.000000/0.000000/16.000000/8.000000:e/0/0.000000/0.000000/8.000000/8.000000:s/0/8.000000/0.000000/16.000000/8.000000:u/0/8.000000/8.000000/16.000000/16.000000 +[1.19-]modellist:id=%mangrove_stairs,state=facing:south/half:bottom/shape:outer_right,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/0/0.000000/0.000000/16.000000/16.000000:R/0/90/0,box=8.000000/8.000000/8.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/8.000000/8.000000:w/0/8.000000/0.000000/16.000000/8.000000:e/0/0.000000/0.000000/8.000000/8.000000:s/0/8.000000/0.000000/16.000000/8.000000:u/0/8.000000/8.000000/16.000000/16.000000:R/0/90/0 +[1.19-]modellist:id=%mangrove_stairs,state=facing:west/half:top/shape:straight,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/0/0.000000/0.000000/16.000000/16.000000:R/180/180/0,box=8.000000/8.000000/0.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/8.000000/8.000000:w/0/0.000000/0.000000/16.000000/8.000000:e/0/0.000000/0.000000/16.000000/8.000000:s/0/8.000000/0.000000/16.000000/8.000000:u/0/8.000000/0.000000/16.000000/16.000000:R/180/180/0 +[1.19-]modellist:id=%mangrove_stairs,state=facing:west/half:top/shape:inner_left,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/0/0.000000/0.000000/16.000000/16.000000:R/180/180/0,box=8.000000/8.000000/0.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/8.000000/8.000000:w/0/0.000000/0.000000/16.000000/8.000000:e/0/0.000000/0.000000/16.000000/8.000000:s/0/8.000000/0.000000/16.000000/8.000000:u/0/8.000000/0.000000/16.000000/16.000000:R/180/180/0,box=0.000000/8.000000/8.000000:8.000000/16.000000/16.000000:n/0/8.000000/0.000000/16.000000/8.000000:w/0/8.000000/0.000000/16.000000/8.000000:s/0/0.000000/0.000000/8.000000/8.000000:u/0/0.000000/8.000000/8.000000/16.000000:R/180/180/0 +[1.19-]modellist:id=%mangrove_stairs,state=facing:west/half:top/shape:inner_right,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/0/0.000000/0.000000/16.000000/16.000000:R/180/270/0,box=8.000000/8.000000/0.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/8.000000/8.000000:w/0/0.000000/0.000000/16.000000/8.000000:e/0/0.000000/0.000000/16.000000/8.000000:s/0/8.000000/0.000000/16.000000/8.000000:u/0/8.000000/0.000000/16.000000/16.000000:R/180/270/0,box=0.000000/8.000000/8.000000:8.000000/16.000000/16.000000:n/0/8.000000/0.000000/16.000000/8.000000:w/0/8.000000/0.000000/16.000000/8.000000:s/0/0.000000/0.000000/8.000000/8.000000:u/0/0.000000/8.000000/8.000000/16.000000:R/180/270/0 +[1.19-]modellist:id=%mangrove_stairs,state=facing:west/half:top/shape:outer_left,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/0/0.000000/0.000000/16.000000/16.000000:R/180/180/0,box=8.000000/8.000000/8.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/8.000000/8.000000:w/0/8.000000/0.000000/16.000000/8.000000:e/0/0.000000/0.000000/8.000000/8.000000:s/0/8.000000/0.000000/16.000000/8.000000:u/0/8.000000/8.000000/16.000000/16.000000:R/180/180/0 +[1.19-]modellist:id=%mangrove_stairs,state=facing:west/half:top/shape:outer_right,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/0/0.000000/0.000000/16.000000/16.000000:R/180/270/0,box=8.000000/8.000000/8.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/8.000000/8.000000:w/0/8.000000/0.000000/16.000000/8.000000:e/0/0.000000/0.000000/8.000000/8.000000:s/0/8.000000/0.000000/16.000000/8.000000:u/0/8.000000/8.000000/16.000000/16.000000:R/180/270/0 +[1.19-]modellist:id=%mangrove_stairs,state=facing:west/half:bottom/shape:straight,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/0/0.000000/0.000000/16.000000/16.000000:R/0/180/0,box=8.000000/8.000000/0.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/8.000000/8.000000:w/0/0.000000/0.000000/16.000000/8.000000:e/0/0.000000/0.000000/16.000000/8.000000:s/0/8.000000/0.000000/16.000000/8.000000:u/0/8.000000/0.000000/16.000000/16.000000:R/0/180/0 +[1.19-]modellist:id=%mangrove_stairs,state=facing:west/half:bottom/shape:inner_left,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/0/0.000000/0.000000/16.000000/16.000000:R/0/90/0,box=8.000000/8.000000/0.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/8.000000/8.000000:w/0/0.000000/0.000000/16.000000/8.000000:e/0/0.000000/0.000000/16.000000/8.000000:s/0/8.000000/0.000000/16.000000/8.000000:u/0/8.000000/0.000000/16.000000/16.000000:R/0/90/0,box=0.000000/8.000000/8.000000:8.000000/16.000000/16.000000:n/0/8.000000/0.000000/16.000000/8.000000:w/0/8.000000/0.000000/16.000000/8.000000:s/0/0.000000/0.000000/8.000000/8.000000:u/0/0.000000/8.000000/8.000000/16.000000:R/0/90/0 +[1.19-]modellist:id=%mangrove_stairs,state=facing:west/half:bottom/shape:inner_right,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/0/0.000000/0.000000/16.000000/16.000000:R/0/180/0,box=8.000000/8.000000/0.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/8.000000/8.000000:w/0/0.000000/0.000000/16.000000/8.000000:e/0/0.000000/0.000000/16.000000/8.000000:s/0/8.000000/0.000000/16.000000/8.000000:u/0/8.000000/0.000000/16.000000/16.000000:R/0/180/0,box=0.000000/8.000000/8.000000:8.000000/16.000000/16.000000:n/0/8.000000/0.000000/16.000000/8.000000:w/0/8.000000/0.000000/16.000000/8.000000:s/0/0.000000/0.000000/8.000000/8.000000:u/0/0.000000/8.000000/8.000000/16.000000:R/0/180/0 +[1.19-]modellist:id=%mangrove_stairs,state=facing:west/half:bottom/shape:outer_left,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/0/0.000000/0.000000/16.000000/16.000000:R/0/90/0,box=8.000000/8.000000/8.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/8.000000/8.000000:w/0/8.000000/0.000000/16.000000/8.000000:e/0/0.000000/0.000000/8.000000/8.000000:s/0/8.000000/0.000000/16.000000/8.000000:u/0/8.000000/8.000000/16.000000/16.000000:R/0/90/0 +[1.19-]modellist:id=%mangrove_stairs,state=facing:west/half:bottom/shape:outer_right,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/0/0.000000/0.000000/16.000000/16.000000:R/0/180/0,box=8.000000/8.000000/8.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/8.000000/8.000000:w/0/8.000000/0.000000/16.000000/8.000000:e/0/0.000000/0.000000/8.000000/8.000000:s/0/8.000000/0.000000/16.000000/8.000000:u/0/8.000000/8.000000/16.000000/16.000000:R/0/180/0 +[1.19-]modellist:id=%mangrove_stairs,state=facing:east/half:top/shape:straight,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/0/0.000000/0.000000/16.000000/16.000000:R/180/0/0,box=8.000000/8.000000/0.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/8.000000/8.000000:w/0/0.000000/0.000000/16.000000/8.000000:e/0/0.000000/0.000000/16.000000/8.000000:s/0/8.000000/0.000000/16.000000/8.000000:u/0/8.000000/0.000000/16.000000/16.000000:R/180/0/0 +[1.19-]modellist:id=%mangrove_stairs,state=facing:east/half:top/shape:inner_left,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/0/0.000000/0.000000/16.000000/16.000000:R/180/0/0,box=8.000000/8.000000/0.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/8.000000/8.000000:w/0/0.000000/0.000000/16.000000/8.000000:e/0/0.000000/0.000000/16.000000/8.000000:s/0/8.000000/0.000000/16.000000/8.000000:u/0/8.000000/0.000000/16.000000/16.000000:R/180/0/0,box=0.000000/8.000000/8.000000:8.000000/16.000000/16.000000:n/0/8.000000/0.000000/16.000000/8.000000:w/0/8.000000/0.000000/16.000000/8.000000:s/0/0.000000/0.000000/8.000000/8.000000:u/0/0.000000/8.000000/8.000000/16.000000:R/180/0/0 +[1.19-]modellist:id=%mangrove_stairs,state=facing:east/half:top/shape:inner_right,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/0/0.000000/0.000000/16.000000/16.000000:R/180/90/0,box=8.000000/8.000000/0.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/8.000000/8.000000:w/0/0.000000/0.000000/16.000000/8.000000:e/0/0.000000/0.000000/16.000000/8.000000:s/0/8.000000/0.000000/16.000000/8.000000:u/0/8.000000/0.000000/16.000000/16.000000:R/180/90/0,box=0.000000/8.000000/8.000000:8.000000/16.000000/16.000000:n/0/8.000000/0.000000/16.000000/8.000000:w/0/8.000000/0.000000/16.000000/8.000000:s/0/0.000000/0.000000/8.000000/8.000000:u/0/0.000000/8.000000/8.000000/16.000000:R/180/90/0 +[1.19-]modellist:id=%mangrove_stairs,state=facing:east/half:top/shape:outer_left,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/0/0.000000/0.000000/16.000000/16.000000:R/180/0/0,box=8.000000/8.000000/8.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/8.000000/8.000000:w/0/8.000000/0.000000/16.000000/8.000000:e/0/0.000000/0.000000/8.000000/8.000000:s/0/8.000000/0.000000/16.000000/8.000000:u/0/8.000000/8.000000/16.000000/16.000000:R/180/0/0 +[1.19-]modellist:id=%mangrove_stairs,state=facing:east/half:top/shape:outer_right,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/0/0.000000/0.000000/16.000000/16.000000:R/180/90/0,box=8.000000/8.000000/8.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/8.000000/8.000000:w/0/8.000000/0.000000/16.000000/8.000000:e/0/0.000000/0.000000/8.000000/8.000000:s/0/8.000000/0.000000/16.000000/8.000000:u/0/8.000000/8.000000/16.000000/16.000000:R/180/90/0 +[1.19-]modellist:id=%mangrove_stairs,state=facing:east/half:bottom/shape:straight,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/0/0.000000/0.000000/16.000000/16.000000,box=8.000000/8.000000/0.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/8.000000/8.000000:w/0/0.000000/0.000000/16.000000/8.000000:e/0/0.000000/0.000000/16.000000/8.000000:s/0/8.000000/0.000000/16.000000/8.000000:u/0/8.000000/0.000000/16.000000/16.000000 +[1.19-]modellist:id=%mangrove_stairs,state=facing:east/half:bottom/shape:inner_left,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/0/0.000000/0.000000/16.000000/16.000000:R/0/270/0,box=8.000000/8.000000/0.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/8.000000/8.000000:w/0/0.000000/0.000000/16.000000/8.000000:e/0/0.000000/0.000000/16.000000/8.000000:s/0/8.000000/0.000000/16.000000/8.000000:u/0/8.000000/0.000000/16.000000/16.000000:R/0/270/0,box=0.000000/8.000000/8.000000:8.000000/16.000000/16.000000:n/0/8.000000/0.000000/16.000000/8.000000:w/0/8.000000/0.000000/16.000000/8.000000:s/0/0.000000/0.000000/8.000000/8.000000:u/0/0.000000/8.000000/8.000000/16.000000:R/0/270/0 +[1.19-]modellist:id=%mangrove_stairs,state=facing:east/half:bottom/shape:inner_right,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/0/0.000000/0.000000/16.000000/16.000000,box=8.000000/8.000000/0.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/8.000000/8.000000:w/0/0.000000/0.000000/16.000000/8.000000:e/0/0.000000/0.000000/16.000000/8.000000:s/0/8.000000/0.000000/16.000000/8.000000:u/0/8.000000/0.000000/16.000000/16.000000,box=0.000000/8.000000/8.000000:8.000000/16.000000/16.000000:n/0/8.000000/0.000000/16.000000/8.000000:w/0/8.000000/0.000000/16.000000/8.000000:s/0/0.000000/0.000000/8.000000/8.000000:u/0/0.000000/8.000000/8.000000/16.000000 +[1.19-]modellist:id=%mangrove_stairs,state=facing:east/half:bottom/shape:outer_left,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/0/0.000000/0.000000/16.000000/16.000000:R/0/270/0,box=8.000000/8.000000/8.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/8.000000/8.000000:w/0/8.000000/0.000000/16.000000/8.000000:e/0/0.000000/0.000000/8.000000/8.000000:s/0/8.000000/0.000000/16.000000/8.000000:u/0/8.000000/8.000000/16.000000/16.000000:R/0/270/0 +[1.19-]modellist:id=%mangrove_stairs,state=facing:east/half:bottom/shape:outer_right,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/0/0.000000/0.000000/16.000000/16.000000,box=8.000000/8.000000/8.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/8.000000/8.000000:w/0/8.000000/0.000000/16.000000/8.000000:e/0/0.000000/0.000000/8.000000/8.000000:s/0/8.000000/0.000000/16.000000/8.000000:u/0/8.000000/8.000000/16.000000/16.000000 +[1.19-]modellist:id=%mangrove_slab,state=type:top,box=0.000000/8.000000/0.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/16.000000/8.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/0.000000/16.000000/8.000000:e/0/0.000000/0.000000/16.000000/8.000000:s/0/0.000000/0.000000/16.000000/8.000000:u/0/0.000000/0.000000/16.000000/16.000000 +[1.19-]modellist:id=%mangrove_slab,state=type:bottom,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/0/0.000000/0.000000/16.000000/16.000000 +[1.19-]modellist:id=%mangrove_fence_gate,state=facing:north/in_wall:true/open:true,box=0.000000/2.000000/7.000000:2.000000/13.000000/9.000000:n/0/0.000000/0.000000/2.000000/11.000000:d/0/0.000000/7.000000/2.000000/9.000000:w/0/7.000000/0.000000/9.000000/11.000000:e/0/7.000000/0.000000/9.000000/11.000000:s/0/0.000000/0.000000/2.000000/11.000000:u/0/0.000000/7.000000/2.000000/9.000000:R/0/180/0,box=14.000000/2.000000/7.000000:16.000000/13.000000/9.000000:n/0/14.000000/0.000000/16.000000/11.000000:d/0/14.000000/7.000000/16.000000/9.000000:w/0/7.000000/0.000000/9.000000/11.000000:e/0/7.000000/0.000000/9.000000/11.000000:s/0/14.000000/0.000000/16.000000/11.000000:u/0/14.000000/7.000000/16.000000/9.000000:R/0/180/0,box=0.000000/3.000000/13.000000:2.000000/12.000000/15.000000:n/0/0.000000/1.000000/2.000000/10.000000:d/0/0.000000/13.000000/2.000000/15.000000:w/0/13.000000/1.000000/15.000000/10.000000:e/0/13.000000/1.000000/15.000000/10.000000:s/0/0.000000/1.000000/2.000000/10.000000:u/0/0.000000/13.000000/2.000000/15.000000:R/0/180/0,box=14.000000/3.000000/13.000000:16.000000/12.000000/15.000000:n/0/14.000000/1.000000/16.000000/10.000000:d/0/14.000000/13.000000/16.000000/15.000000:w/0/13.000000/1.000000/15.000000/10.000000:e/0/13.000000/1.000000/15.000000/10.000000:s/0/14.000000/1.000000/16.000000/10.000000:u/0/14.000000/13.000000/16.000000/15.000000:R/0/180/0,box=0.000000/3.000000/9.000000:2.000000/6.000000/13.000000:d/0/0.000000/9.000000/2.000000/13.000000:w/0/13.000000/7.000000/15.000000/10.000000:e/0/13.000000/7.000000/15.000000/10.000000:u/0/0.000000/9.000000/2.000000/13.000000:R/0/180/0,box=0.000000/9.000000/9.000000:2.000000/12.000000/13.000000:d/0/0.000000/9.000000/2.000000/13.000000:w/0/13.000000/1.000000/15.000000/4.000000:e/0/13.000000/1.000000/15.000000/4.000000:u/0/0.000000/9.000000/2.000000/13.000000:R/0/180/0,box=14.000000/3.000000/9.000000:16.000000/6.000000/13.000000:d/0/14.000000/9.000000/16.000000/13.000000:w/0/13.000000/7.000000/15.000000/10.000000:e/0/13.000000/7.000000/15.000000/10.000000:u/0/14.000000/9.000000/16.000000/13.000000:R/0/180/0,box=14.000000/9.000000/9.000000:16.000000/12.000000/13.000000:d/0/14.000000/9.000000/16.000000/13.000000:w/0/13.000000/1.000000/15.000000/4.000000:e/0/13.000000/1.000000/15.000000/4.000000:u/0/14.000000/9.000000/16.000000/13.000000:R/0/180/0 +[1.19-]modellist:id=%mangrove_fence_gate,state=facing:north/in_wall:true/open:false,box=0.000000/2.000000/7.000000:2.000000/13.000000/9.000000:n/0/0.000000/0.000000/2.000000/11.000000:d/0/0.000000/7.000000/2.000000/9.000000:w/0/7.000000/0.000000/9.000000/11.000000:e/0/7.000000/0.000000/9.000000/11.000000:s/0/0.000000/0.000000/2.000000/11.000000:u/0/0.000000/7.000000/2.000000/9.000000:R/0/180/0,box=14.000000/2.000000/7.000000:16.000000/13.000000/9.000000:n/0/14.000000/0.000000/16.000000/11.000000:d/0/14.000000/7.000000/16.000000/9.000000:w/0/7.000000/0.000000/9.000000/11.000000:e/0/7.000000/0.000000/9.000000/11.000000:s/0/14.000000/0.000000/16.000000/11.000000:u/0/14.000000/7.000000/16.000000/9.000000:R/0/180/0,box=6.000000/3.000000/7.000000:8.000000/12.000000/9.000000:n/0/6.000000/1.000000/8.000000/10.000000:d/0/6.000000/7.000000/8.000000/9.000000:w/0/7.000000/1.000000/9.000000/10.000000:e/0/7.000000/1.000000/9.000000/10.000000:s/0/6.000000/1.000000/8.000000/10.000000:u/0/6.000000/7.000000/8.000000/9.000000:R/0/180/0,box=8.000000/3.000000/7.000000:10.000000/12.000000/9.000000:n/0/8.000000/1.000000/10.000000/10.000000:d/0/8.000000/7.000000/10.000000/9.000000:w/0/7.000000/1.000000/9.000000/10.000000:e/0/7.000000/1.000000/9.000000/10.000000:s/0/8.000000/1.000000/10.000000/10.000000:u/0/8.000000/7.000000/10.000000/9.000000:R/0/180/0,box=2.000000/3.000000/7.000000:6.000000/6.000000/9.000000:n/0/2.000000/7.000000/6.000000/10.000000:d/0/2.000000/7.000000/6.000000/9.000000:s/0/2.000000/7.000000/6.000000/10.000000:u/0/2.000000/7.000000/6.000000/9.000000:R/0/180/0,box=2.000000/9.000000/7.000000:6.000000/12.000000/9.000000:n/0/2.000000/1.000000/6.000000/4.000000:d/0/2.000000/7.000000/6.000000/9.000000:s/0/2.000000/1.000000/6.000000/4.000000:u/0/2.000000/7.000000/6.000000/9.000000:R/0/180/0,box=10.000000/3.000000/7.000000:14.000000/6.000000/9.000000:n/0/10.000000/7.000000/14.000000/10.000000:d/0/10.000000/7.000000/14.000000/9.000000:s/0/10.000000/7.000000/14.000000/10.000000:u/0/10.000000/7.000000/14.000000/9.000000:R/0/180/0,box=10.000000/9.000000/7.000000:14.000000/12.000000/9.000000:n/0/10.000000/1.000000/14.000000/4.000000:d/0/10.000000/7.000000/14.000000/9.000000:s/0/10.000000/1.000000/14.000000/4.000000:u/0/10.000000/7.000000/14.000000/9.000000:R/0/180/0 +[1.19-]modellist:id=%mangrove_fence_gate,state=facing:north/in_wall:false/open:true,box=0.000000/5.000000/7.000000:2.000000/16.000000/9.000000:n/0/0.000000/0.000000/2.000000/11.000000:d/0/0.000000/7.000000/2.000000/9.000000:w/0/7.000000/0.000000/9.000000/11.000000:e/0/7.000000/0.000000/9.000000/11.000000:s/0/0.000000/0.000000/2.000000/11.000000:u/0/0.000000/7.000000/2.000000/9.000000:R/0/180/0,box=14.000000/5.000000/7.000000:16.000000/16.000000/9.000000:n/0/14.000000/0.000000/16.000000/11.000000:d/0/14.000000/7.000000/16.000000/9.000000:w/0/7.000000/0.000000/9.000000/11.000000:e/0/7.000000/0.000000/9.000000/11.000000:s/0/14.000000/0.000000/16.000000/11.000000:u/0/14.000000/7.000000/16.000000/9.000000:R/0/180/0,box=0.000000/6.000000/13.000000:2.000000/15.000000/15.000000:n/0/0.000000/1.000000/2.000000/10.000000:d/0/0.000000/13.000000/2.000000/15.000000:w/0/13.000000/1.000000/15.000000/10.000000:e/0/13.000000/1.000000/15.000000/10.000000:s/0/0.000000/1.000000/2.000000/10.000000:u/0/0.000000/13.000000/2.000000/15.000000:R/0/180/0,box=14.000000/6.000000/13.000000:16.000000/15.000000/15.000000:n/0/14.000000/1.000000/16.000000/10.000000:d/0/14.000000/13.000000/16.000000/15.000000:w/0/13.000000/1.000000/15.000000/10.000000:e/0/13.000000/1.000000/15.000000/10.000000:s/0/14.000000/1.000000/16.000000/10.000000:u/0/14.000000/13.000000/16.000000/15.000000:R/0/180/0,box=0.000000/6.000000/9.000000:2.000000/9.000000/13.000000:d/0/0.000000/9.000000/2.000000/13.000000:w/0/13.000000/7.000000/15.000000/10.000000:e/0/13.000000/7.000000/15.000000/10.000000:u/0/0.000000/9.000000/2.000000/13.000000:R/0/180/0,box=0.000000/12.000000/9.000000:2.000000/15.000000/13.000000:d/0/0.000000/9.000000/2.000000/13.000000:w/0/13.000000/1.000000/15.000000/4.000000:e/0/13.000000/1.000000/15.000000/4.000000:u/0/0.000000/9.000000/2.000000/13.000000:R/0/180/0,box=14.000000/6.000000/9.000000:16.000000/9.000000/13.000000:d/0/14.000000/9.000000/16.000000/13.000000:w/0/13.000000/7.000000/15.000000/10.000000:e/0/13.000000/7.000000/15.000000/10.000000:u/0/14.000000/9.000000/16.000000/13.000000:R/0/180/0,box=14.000000/12.000000/9.000000:16.000000/15.000000/13.000000:d/0/14.000000/9.000000/16.000000/13.000000:w/0/13.000000/1.000000/15.000000/4.000000:e/0/13.000000/1.000000/15.000000/4.000000:u/0/14.000000/9.000000/16.000000/13.000000:R/0/180/0 +[1.19-]modellist:id=%mangrove_fence_gate,state=facing:north/in_wall:false/open:false,box=0.000000/5.000000/7.000000:2.000000/16.000000/9.000000:n/0/0.000000/0.000000/2.000000/11.000000:d/0/0.000000/7.000000/2.000000/9.000000:w/0/7.000000/0.000000/9.000000/11.000000:e/0/7.000000/0.000000/9.000000/11.000000:s/0/0.000000/0.000000/2.000000/11.000000:u/0/0.000000/7.000000/2.000000/9.000000:R/0/180/0,box=14.000000/5.000000/7.000000:16.000000/16.000000/9.000000:n/0/14.000000/0.000000/16.000000/11.000000:d/0/14.000000/7.000000/16.000000/9.000000:w/0/7.000000/0.000000/9.000000/11.000000:e/0/7.000000/0.000000/9.000000/11.000000:s/0/14.000000/0.000000/16.000000/11.000000:u/0/14.000000/7.000000/16.000000/9.000000:R/0/180/0,box=6.000000/6.000000/7.000000:8.000000/15.000000/9.000000:n/0/6.000000/1.000000/8.000000/10.000000:d/0/6.000000/7.000000/8.000000/9.000000:w/0/7.000000/1.000000/9.000000/10.000000:e/0/7.000000/1.000000/9.000000/10.000000:s/0/6.000000/1.000000/8.000000/10.000000:u/0/6.000000/7.000000/8.000000/9.000000:R/0/180/0,box=8.000000/6.000000/7.000000:10.000000/15.000000/9.000000:n/0/8.000000/1.000000/10.000000/10.000000:d/0/8.000000/7.000000/10.000000/9.000000:w/0/7.000000/1.000000/9.000000/10.000000:e/0/7.000000/1.000000/9.000000/10.000000:s/0/8.000000/1.000000/10.000000/10.000000:u/0/8.000000/7.000000/10.000000/9.000000:R/0/180/0,box=2.000000/6.000000/7.000000:6.000000/9.000000/9.000000:n/0/2.000000/7.000000/6.000000/10.000000:d/0/2.000000/7.000000/6.000000/9.000000:s/0/2.000000/7.000000/6.000000/10.000000:u/0/2.000000/7.000000/6.000000/9.000000:R/0/180/0,box=2.000000/12.000000/7.000000:6.000000/15.000000/9.000000:n/0/2.000000/1.000000/6.000000/4.000000:d/0/2.000000/7.000000/6.000000/9.000000:s/0/2.000000/1.000000/6.000000/4.000000:u/0/2.000000/7.000000/6.000000/9.000000:R/0/180/0,box=10.000000/6.000000/7.000000:14.000000/9.000000/9.000000:n/0/10.000000/7.000000/14.000000/10.000000:d/0/10.000000/7.000000/14.000000/9.000000:s/0/10.000000/7.000000/14.000000/10.000000:u/0/10.000000/7.000000/14.000000/9.000000:R/0/180/0,box=10.000000/12.000000/7.000000:14.000000/15.000000/9.000000:n/0/10.000000/1.000000/14.000000/4.000000:d/0/10.000000/7.000000/14.000000/9.000000:s/0/10.000000/1.000000/14.000000/4.000000:u/0/10.000000/7.000000/14.000000/9.000000:R/0/180/0 +[1.19-]modellist:id=%mangrove_fence_gate,state=facing:south/in_wall:true/open:true,box=0.000000/2.000000/7.000000:2.000000/13.000000/9.000000:n/0/0.000000/0.000000/2.000000/11.000000:d/0/0.000000/7.000000/2.000000/9.000000:w/0/7.000000/0.000000/9.000000/11.000000:e/0/7.000000/0.000000/9.000000/11.000000:s/0/0.000000/0.000000/2.000000/11.000000:u/0/0.000000/7.000000/2.000000/9.000000,box=14.000000/2.000000/7.000000:16.000000/13.000000/9.000000:n/0/14.000000/0.000000/16.000000/11.000000:d/0/14.000000/7.000000/16.000000/9.000000:w/0/7.000000/0.000000/9.000000/11.000000:e/0/7.000000/0.000000/9.000000/11.000000:s/0/14.000000/0.000000/16.000000/11.000000:u/0/14.000000/7.000000/16.000000/9.000000,box=0.000000/3.000000/13.000000:2.000000/12.000000/15.000000:n/0/0.000000/1.000000/2.000000/10.000000:d/0/0.000000/13.000000/2.000000/15.000000:w/0/13.000000/1.000000/15.000000/10.000000:e/0/13.000000/1.000000/15.000000/10.000000:s/0/0.000000/1.000000/2.000000/10.000000:u/0/0.000000/13.000000/2.000000/15.000000,box=14.000000/3.000000/13.000000:16.000000/12.000000/15.000000:n/0/14.000000/1.000000/16.000000/10.000000:d/0/14.000000/13.000000/16.000000/15.000000:w/0/13.000000/1.000000/15.000000/10.000000:e/0/13.000000/1.000000/15.000000/10.000000:s/0/14.000000/1.000000/16.000000/10.000000:u/0/14.000000/13.000000/16.000000/15.000000,box=0.000000/3.000000/9.000000:2.000000/6.000000/13.000000:d/0/0.000000/9.000000/2.000000/13.000000:w/0/13.000000/7.000000/15.000000/10.000000:e/0/13.000000/7.000000/15.000000/10.000000:u/0/0.000000/9.000000/2.000000/13.000000,box=0.000000/9.000000/9.000000:2.000000/12.000000/13.000000:d/0/0.000000/9.000000/2.000000/13.000000:w/0/13.000000/1.000000/15.000000/4.000000:e/0/13.000000/1.000000/15.000000/4.000000:u/0/0.000000/9.000000/2.000000/13.000000,box=14.000000/3.000000/9.000000:16.000000/6.000000/13.000000:d/0/14.000000/9.000000/16.000000/13.000000:w/0/13.000000/7.000000/15.000000/10.000000:e/0/13.000000/7.000000/15.000000/10.000000:u/0/14.000000/9.000000/16.000000/13.000000,box=14.000000/9.000000/9.000000:16.000000/12.000000/13.000000:d/0/14.000000/9.000000/16.000000/13.000000:w/0/13.000000/1.000000/15.000000/4.000000:e/0/13.000000/1.000000/15.000000/4.000000:u/0/14.000000/9.000000/16.000000/13.000000 +[1.19-]modellist:id=%mangrove_fence_gate,state=facing:south/in_wall:true/open:false,box=0.000000/2.000000/7.000000:2.000000/13.000000/9.000000:n/0/0.000000/0.000000/2.000000/11.000000:d/0/0.000000/7.000000/2.000000/9.000000:w/0/7.000000/0.000000/9.000000/11.000000:e/0/7.000000/0.000000/9.000000/11.000000:s/0/0.000000/0.000000/2.000000/11.000000:u/0/0.000000/7.000000/2.000000/9.000000,box=14.000000/2.000000/7.000000:16.000000/13.000000/9.000000:n/0/14.000000/0.000000/16.000000/11.000000:d/0/14.000000/7.000000/16.000000/9.000000:w/0/7.000000/0.000000/9.000000/11.000000:e/0/7.000000/0.000000/9.000000/11.000000:s/0/14.000000/0.000000/16.000000/11.000000:u/0/14.000000/7.000000/16.000000/9.000000,box=6.000000/3.000000/7.000000:8.000000/12.000000/9.000000:n/0/6.000000/1.000000/8.000000/10.000000:d/0/6.000000/7.000000/8.000000/9.000000:w/0/7.000000/1.000000/9.000000/10.000000:e/0/7.000000/1.000000/9.000000/10.000000:s/0/6.000000/1.000000/8.000000/10.000000:u/0/6.000000/7.000000/8.000000/9.000000,box=8.000000/3.000000/7.000000:10.000000/12.000000/9.000000:n/0/8.000000/1.000000/10.000000/10.000000:d/0/8.000000/7.000000/10.000000/9.000000:w/0/7.000000/1.000000/9.000000/10.000000:e/0/7.000000/1.000000/9.000000/10.000000:s/0/8.000000/1.000000/10.000000/10.000000:u/0/8.000000/7.000000/10.000000/9.000000,box=2.000000/3.000000/7.000000:6.000000/6.000000/9.000000:n/0/2.000000/7.000000/6.000000/10.000000:d/0/2.000000/7.000000/6.000000/9.000000:s/0/2.000000/7.000000/6.000000/10.000000:u/0/2.000000/7.000000/6.000000/9.000000,box=2.000000/9.000000/7.000000:6.000000/12.000000/9.000000:n/0/2.000000/1.000000/6.000000/4.000000:d/0/2.000000/7.000000/6.000000/9.000000:s/0/2.000000/1.000000/6.000000/4.000000:u/0/2.000000/7.000000/6.000000/9.000000,box=10.000000/3.000000/7.000000:14.000000/6.000000/9.000000:n/0/10.000000/7.000000/14.000000/10.000000:d/0/10.000000/7.000000/14.000000/9.000000:s/0/10.000000/7.000000/14.000000/10.000000:u/0/10.000000/7.000000/14.000000/9.000000,box=10.000000/9.000000/7.000000:14.000000/12.000000/9.000000:n/0/10.000000/1.000000/14.000000/4.000000:d/0/10.000000/7.000000/14.000000/9.000000:s/0/10.000000/1.000000/14.000000/4.000000:u/0/10.000000/7.000000/14.000000/9.000000 +[1.19-]modellist:id=%mangrove_fence_gate,state=facing:south/in_wall:false/open:true,box=0.000000/5.000000/7.000000:2.000000/16.000000/9.000000:n/0/0.000000/0.000000/2.000000/11.000000:d/0/0.000000/7.000000/2.000000/9.000000:w/0/7.000000/0.000000/9.000000/11.000000:e/0/7.000000/0.000000/9.000000/11.000000:s/0/0.000000/0.000000/2.000000/11.000000:u/0/0.000000/7.000000/2.000000/9.000000,box=14.000000/5.000000/7.000000:16.000000/16.000000/9.000000:n/0/14.000000/0.000000/16.000000/11.000000:d/0/14.000000/7.000000/16.000000/9.000000:w/0/7.000000/0.000000/9.000000/11.000000:e/0/7.000000/0.000000/9.000000/11.000000:s/0/14.000000/0.000000/16.000000/11.000000:u/0/14.000000/7.000000/16.000000/9.000000,box=0.000000/6.000000/13.000000:2.000000/15.000000/15.000000:n/0/0.000000/1.000000/2.000000/10.000000:d/0/0.000000/13.000000/2.000000/15.000000:w/0/13.000000/1.000000/15.000000/10.000000:e/0/13.000000/1.000000/15.000000/10.000000:s/0/0.000000/1.000000/2.000000/10.000000:u/0/0.000000/13.000000/2.000000/15.000000,box=14.000000/6.000000/13.000000:16.000000/15.000000/15.000000:n/0/14.000000/1.000000/16.000000/10.000000:d/0/14.000000/13.000000/16.000000/15.000000:w/0/13.000000/1.000000/15.000000/10.000000:e/0/13.000000/1.000000/15.000000/10.000000:s/0/14.000000/1.000000/16.000000/10.000000:u/0/14.000000/13.000000/16.000000/15.000000,box=0.000000/6.000000/9.000000:2.000000/9.000000/13.000000:d/0/0.000000/9.000000/2.000000/13.000000:w/0/13.000000/7.000000/15.000000/10.000000:e/0/13.000000/7.000000/15.000000/10.000000:u/0/0.000000/9.000000/2.000000/13.000000,box=0.000000/12.000000/9.000000:2.000000/15.000000/13.000000:d/0/0.000000/9.000000/2.000000/13.000000:w/0/13.000000/1.000000/15.000000/4.000000:e/0/13.000000/1.000000/15.000000/4.000000:u/0/0.000000/9.000000/2.000000/13.000000,box=14.000000/6.000000/9.000000:16.000000/9.000000/13.000000:d/0/14.000000/9.000000/16.000000/13.000000:w/0/13.000000/7.000000/15.000000/10.000000:e/0/13.000000/7.000000/15.000000/10.000000:u/0/14.000000/9.000000/16.000000/13.000000,box=14.000000/12.000000/9.000000:16.000000/15.000000/13.000000:d/0/14.000000/9.000000/16.000000/13.000000:w/0/13.000000/1.000000/15.000000/4.000000:e/0/13.000000/1.000000/15.000000/4.000000:u/0/14.000000/9.000000/16.000000/13.000000 +[1.19-]modellist:id=%mangrove_fence_gate,state=facing:south/in_wall:false/open:false,box=0.000000/5.000000/7.000000:2.000000/16.000000/9.000000:n/0/0.000000/0.000000/2.000000/11.000000:d/0/0.000000/7.000000/2.000000/9.000000:w/0/7.000000/0.000000/9.000000/11.000000:e/0/7.000000/0.000000/9.000000/11.000000:s/0/0.000000/0.000000/2.000000/11.000000:u/0/0.000000/7.000000/2.000000/9.000000,box=14.000000/5.000000/7.000000:16.000000/16.000000/9.000000:n/0/14.000000/0.000000/16.000000/11.000000:d/0/14.000000/7.000000/16.000000/9.000000:w/0/7.000000/0.000000/9.000000/11.000000:e/0/7.000000/0.000000/9.000000/11.000000:s/0/14.000000/0.000000/16.000000/11.000000:u/0/14.000000/7.000000/16.000000/9.000000,box=6.000000/6.000000/7.000000:8.000000/15.000000/9.000000:n/0/6.000000/1.000000/8.000000/10.000000:d/0/6.000000/7.000000/8.000000/9.000000:w/0/7.000000/1.000000/9.000000/10.000000:e/0/7.000000/1.000000/9.000000/10.000000:s/0/6.000000/1.000000/8.000000/10.000000:u/0/6.000000/7.000000/8.000000/9.000000,box=8.000000/6.000000/7.000000:10.000000/15.000000/9.000000:n/0/8.000000/1.000000/10.000000/10.000000:d/0/8.000000/7.000000/10.000000/9.000000:w/0/7.000000/1.000000/9.000000/10.000000:e/0/7.000000/1.000000/9.000000/10.000000:s/0/8.000000/1.000000/10.000000/10.000000:u/0/8.000000/7.000000/10.000000/9.000000,box=2.000000/6.000000/7.000000:6.000000/9.000000/9.000000:n/0/2.000000/7.000000/6.000000/10.000000:d/0/2.000000/7.000000/6.000000/9.000000:s/0/2.000000/7.000000/6.000000/10.000000:u/0/2.000000/7.000000/6.000000/9.000000,box=2.000000/12.000000/7.000000:6.000000/15.000000/9.000000:n/0/2.000000/1.000000/6.000000/4.000000:d/0/2.000000/7.000000/6.000000/9.000000:s/0/2.000000/1.000000/6.000000/4.000000:u/0/2.000000/7.000000/6.000000/9.000000,box=10.000000/6.000000/7.000000:14.000000/9.000000/9.000000:n/0/10.000000/7.000000/14.000000/10.000000:d/0/10.000000/7.000000/14.000000/9.000000:s/0/10.000000/7.000000/14.000000/10.000000:u/0/10.000000/7.000000/14.000000/9.000000,box=10.000000/12.000000/7.000000:14.000000/15.000000/9.000000:n/0/10.000000/1.000000/14.000000/4.000000:d/0/10.000000/7.000000/14.000000/9.000000:s/0/10.000000/1.000000/14.000000/4.000000:u/0/10.000000/7.000000/14.000000/9.000000 +[1.19-]modellist:id=%mangrove_fence_gate,state=facing:west/in_wall:true/open:true,box=0.000000/2.000000/7.000000:2.000000/13.000000/9.000000:n/0/0.000000/0.000000/2.000000/11.000000:d/0/0.000000/7.000000/2.000000/9.000000:w/0/7.000000/0.000000/9.000000/11.000000:e/0/7.000000/0.000000/9.000000/11.000000:s/0/0.000000/0.000000/2.000000/11.000000:u/0/0.000000/7.000000/2.000000/9.000000:R/0/90/0,box=14.000000/2.000000/7.000000:16.000000/13.000000/9.000000:n/0/14.000000/0.000000/16.000000/11.000000:d/0/14.000000/7.000000/16.000000/9.000000:w/0/7.000000/0.000000/9.000000/11.000000:e/0/7.000000/0.000000/9.000000/11.000000:s/0/14.000000/0.000000/16.000000/11.000000:u/0/14.000000/7.000000/16.000000/9.000000:R/0/90/0,box=0.000000/3.000000/13.000000:2.000000/12.000000/15.000000:n/0/0.000000/1.000000/2.000000/10.000000:d/0/0.000000/13.000000/2.000000/15.000000:w/0/13.000000/1.000000/15.000000/10.000000:e/0/13.000000/1.000000/15.000000/10.000000:s/0/0.000000/1.000000/2.000000/10.000000:u/0/0.000000/13.000000/2.000000/15.000000:R/0/90/0,box=14.000000/3.000000/13.000000:16.000000/12.000000/15.000000:n/0/14.000000/1.000000/16.000000/10.000000:d/0/14.000000/13.000000/16.000000/15.000000:w/0/13.000000/1.000000/15.000000/10.000000:e/0/13.000000/1.000000/15.000000/10.000000:s/0/14.000000/1.000000/16.000000/10.000000:u/0/14.000000/13.000000/16.000000/15.000000:R/0/90/0,box=0.000000/3.000000/9.000000:2.000000/6.000000/13.000000:d/0/0.000000/9.000000/2.000000/13.000000:w/0/13.000000/7.000000/15.000000/10.000000:e/0/13.000000/7.000000/15.000000/10.000000:u/0/0.000000/9.000000/2.000000/13.000000:R/0/90/0,box=0.000000/9.000000/9.000000:2.000000/12.000000/13.000000:d/0/0.000000/9.000000/2.000000/13.000000:w/0/13.000000/1.000000/15.000000/4.000000:e/0/13.000000/1.000000/15.000000/4.000000:u/0/0.000000/9.000000/2.000000/13.000000:R/0/90/0,box=14.000000/3.000000/9.000000:16.000000/6.000000/13.000000:d/0/14.000000/9.000000/16.000000/13.000000:w/0/13.000000/7.000000/15.000000/10.000000:e/0/13.000000/7.000000/15.000000/10.000000:u/0/14.000000/9.000000/16.000000/13.000000:R/0/90/0,box=14.000000/9.000000/9.000000:16.000000/12.000000/13.000000:d/0/14.000000/9.000000/16.000000/13.000000:w/0/13.000000/1.000000/15.000000/4.000000:e/0/13.000000/1.000000/15.000000/4.000000:u/0/14.000000/9.000000/16.000000/13.000000:R/0/90/0 +[1.19-]modellist:id=%mangrove_fence_gate,state=facing:west/in_wall:true/open:false,box=0.000000/2.000000/7.000000:2.000000/13.000000/9.000000:n/0/0.000000/0.000000/2.000000/11.000000:d/0/0.000000/7.000000/2.000000/9.000000:w/0/7.000000/0.000000/9.000000/11.000000:e/0/7.000000/0.000000/9.000000/11.000000:s/0/0.000000/0.000000/2.000000/11.000000:u/0/0.000000/7.000000/2.000000/9.000000:R/0/90/0,box=14.000000/2.000000/7.000000:16.000000/13.000000/9.000000:n/0/14.000000/0.000000/16.000000/11.000000:d/0/14.000000/7.000000/16.000000/9.000000:w/0/7.000000/0.000000/9.000000/11.000000:e/0/7.000000/0.000000/9.000000/11.000000:s/0/14.000000/0.000000/16.000000/11.000000:u/0/14.000000/7.000000/16.000000/9.000000:R/0/90/0,box=6.000000/3.000000/7.000000:8.000000/12.000000/9.000000:n/0/6.000000/1.000000/8.000000/10.000000:d/0/6.000000/7.000000/8.000000/9.000000:w/0/7.000000/1.000000/9.000000/10.000000:e/0/7.000000/1.000000/9.000000/10.000000:s/0/6.000000/1.000000/8.000000/10.000000:u/0/6.000000/7.000000/8.000000/9.000000:R/0/90/0,box=8.000000/3.000000/7.000000:10.000000/12.000000/9.000000:n/0/8.000000/1.000000/10.000000/10.000000:d/0/8.000000/7.000000/10.000000/9.000000:w/0/7.000000/1.000000/9.000000/10.000000:e/0/7.000000/1.000000/9.000000/10.000000:s/0/8.000000/1.000000/10.000000/10.000000:u/0/8.000000/7.000000/10.000000/9.000000:R/0/90/0,box=2.000000/3.000000/7.000000:6.000000/6.000000/9.000000:n/0/2.000000/7.000000/6.000000/10.000000:d/0/2.000000/7.000000/6.000000/9.000000:s/0/2.000000/7.000000/6.000000/10.000000:u/0/2.000000/7.000000/6.000000/9.000000:R/0/90/0,box=2.000000/9.000000/7.000000:6.000000/12.000000/9.000000:n/0/2.000000/1.000000/6.000000/4.000000:d/0/2.000000/7.000000/6.000000/9.000000:s/0/2.000000/1.000000/6.000000/4.000000:u/0/2.000000/7.000000/6.000000/9.000000:R/0/90/0,box=10.000000/3.000000/7.000000:14.000000/6.000000/9.000000:n/0/10.000000/7.000000/14.000000/10.000000:d/0/10.000000/7.000000/14.000000/9.000000:s/0/10.000000/7.000000/14.000000/10.000000:u/0/10.000000/7.000000/14.000000/9.000000:R/0/90/0,box=10.000000/9.000000/7.000000:14.000000/12.000000/9.000000:n/0/10.000000/1.000000/14.000000/4.000000:d/0/10.000000/7.000000/14.000000/9.000000:s/0/10.000000/1.000000/14.000000/4.000000:u/0/10.000000/7.000000/14.000000/9.000000:R/0/90/0 +[1.19-]modellist:id=%mangrove_fence_gate,state=facing:west/in_wall:false/open:true,box=0.000000/5.000000/7.000000:2.000000/16.000000/9.000000:n/0/0.000000/0.000000/2.000000/11.000000:d/0/0.000000/7.000000/2.000000/9.000000:w/0/7.000000/0.000000/9.000000/11.000000:e/0/7.000000/0.000000/9.000000/11.000000:s/0/0.000000/0.000000/2.000000/11.000000:u/0/0.000000/7.000000/2.000000/9.000000:R/0/90/0,box=14.000000/5.000000/7.000000:16.000000/16.000000/9.000000:n/0/14.000000/0.000000/16.000000/11.000000:d/0/14.000000/7.000000/16.000000/9.000000:w/0/7.000000/0.000000/9.000000/11.000000:e/0/7.000000/0.000000/9.000000/11.000000:s/0/14.000000/0.000000/16.000000/11.000000:u/0/14.000000/7.000000/16.000000/9.000000:R/0/90/0,box=0.000000/6.000000/13.000000:2.000000/15.000000/15.000000:n/0/0.000000/1.000000/2.000000/10.000000:d/0/0.000000/13.000000/2.000000/15.000000:w/0/13.000000/1.000000/15.000000/10.000000:e/0/13.000000/1.000000/15.000000/10.000000:s/0/0.000000/1.000000/2.000000/10.000000:u/0/0.000000/13.000000/2.000000/15.000000:R/0/90/0,box=14.000000/6.000000/13.000000:16.000000/15.000000/15.000000:n/0/14.000000/1.000000/16.000000/10.000000:d/0/14.000000/13.000000/16.000000/15.000000:w/0/13.000000/1.000000/15.000000/10.000000:e/0/13.000000/1.000000/15.000000/10.000000:s/0/14.000000/1.000000/16.000000/10.000000:u/0/14.000000/13.000000/16.000000/15.000000:R/0/90/0,box=0.000000/6.000000/9.000000:2.000000/9.000000/13.000000:d/0/0.000000/9.000000/2.000000/13.000000:w/0/13.000000/7.000000/15.000000/10.000000:e/0/13.000000/7.000000/15.000000/10.000000:u/0/0.000000/9.000000/2.000000/13.000000:R/0/90/0,box=0.000000/12.000000/9.000000:2.000000/15.000000/13.000000:d/0/0.000000/9.000000/2.000000/13.000000:w/0/13.000000/1.000000/15.000000/4.000000:e/0/13.000000/1.000000/15.000000/4.000000:u/0/0.000000/9.000000/2.000000/13.000000:R/0/90/0,box=14.000000/6.000000/9.000000:16.000000/9.000000/13.000000:d/0/14.000000/9.000000/16.000000/13.000000:w/0/13.000000/7.000000/15.000000/10.000000:e/0/13.000000/7.000000/15.000000/10.000000:u/0/14.000000/9.000000/16.000000/13.000000:R/0/90/0,box=14.000000/12.000000/9.000000:16.000000/15.000000/13.000000:d/0/14.000000/9.000000/16.000000/13.000000:w/0/13.000000/1.000000/15.000000/4.000000:e/0/13.000000/1.000000/15.000000/4.000000:u/0/14.000000/9.000000/16.000000/13.000000:R/0/90/0 +[1.19-]modellist:id=%mangrove_fence_gate,state=facing:west/in_wall:false/open:false,box=0.000000/5.000000/7.000000:2.000000/16.000000/9.000000:n/0/0.000000/0.000000/2.000000/11.000000:d/0/0.000000/7.000000/2.000000/9.000000:w/0/7.000000/0.000000/9.000000/11.000000:e/0/7.000000/0.000000/9.000000/11.000000:s/0/0.000000/0.000000/2.000000/11.000000:u/0/0.000000/7.000000/2.000000/9.000000:R/0/90/0,box=14.000000/5.000000/7.000000:16.000000/16.000000/9.000000:n/0/14.000000/0.000000/16.000000/11.000000:d/0/14.000000/7.000000/16.000000/9.000000:w/0/7.000000/0.000000/9.000000/11.000000:e/0/7.000000/0.000000/9.000000/11.000000:s/0/14.000000/0.000000/16.000000/11.000000:u/0/14.000000/7.000000/16.000000/9.000000:R/0/90/0,box=6.000000/6.000000/7.000000:8.000000/15.000000/9.000000:n/0/6.000000/1.000000/8.000000/10.000000:d/0/6.000000/7.000000/8.000000/9.000000:w/0/7.000000/1.000000/9.000000/10.000000:e/0/7.000000/1.000000/9.000000/10.000000:s/0/6.000000/1.000000/8.000000/10.000000:u/0/6.000000/7.000000/8.000000/9.000000:R/0/90/0,box=8.000000/6.000000/7.000000:10.000000/15.000000/9.000000:n/0/8.000000/1.000000/10.000000/10.000000:d/0/8.000000/7.000000/10.000000/9.000000:w/0/7.000000/1.000000/9.000000/10.000000:e/0/7.000000/1.000000/9.000000/10.000000:s/0/8.000000/1.000000/10.000000/10.000000:u/0/8.000000/7.000000/10.000000/9.000000:R/0/90/0,box=2.000000/6.000000/7.000000:6.000000/9.000000/9.000000:n/0/2.000000/7.000000/6.000000/10.000000:d/0/2.000000/7.000000/6.000000/9.000000:s/0/2.000000/7.000000/6.000000/10.000000:u/0/2.000000/7.000000/6.000000/9.000000:R/0/90/0,box=2.000000/12.000000/7.000000:6.000000/15.000000/9.000000:n/0/2.000000/1.000000/6.000000/4.000000:d/0/2.000000/7.000000/6.000000/9.000000:s/0/2.000000/1.000000/6.000000/4.000000:u/0/2.000000/7.000000/6.000000/9.000000:R/0/90/0,box=10.000000/6.000000/7.000000:14.000000/9.000000/9.000000:n/0/10.000000/7.000000/14.000000/10.000000:d/0/10.000000/7.000000/14.000000/9.000000:s/0/10.000000/7.000000/14.000000/10.000000:u/0/10.000000/7.000000/14.000000/9.000000:R/0/90/0,box=10.000000/12.000000/7.000000:14.000000/15.000000/9.000000:n/0/10.000000/1.000000/14.000000/4.000000:d/0/10.000000/7.000000/14.000000/9.000000:s/0/10.000000/1.000000/14.000000/4.000000:u/0/10.000000/7.000000/14.000000/9.000000:R/0/90/0 +[1.19-]modellist:id=%mangrove_fence_gate,state=facing:east/in_wall:true/open:true,box=0.000000/2.000000/7.000000:2.000000/13.000000/9.000000:n/0/0.000000/0.000000/2.000000/11.000000:d/0/0.000000/7.000000/2.000000/9.000000:w/0/7.000000/0.000000/9.000000/11.000000:e/0/7.000000/0.000000/9.000000/11.000000:s/0/0.000000/0.000000/2.000000/11.000000:u/0/0.000000/7.000000/2.000000/9.000000:R/0/270/0,box=14.000000/2.000000/7.000000:16.000000/13.000000/9.000000:n/0/14.000000/0.000000/16.000000/11.000000:d/0/14.000000/7.000000/16.000000/9.000000:w/0/7.000000/0.000000/9.000000/11.000000:e/0/7.000000/0.000000/9.000000/11.000000:s/0/14.000000/0.000000/16.000000/11.000000:u/0/14.000000/7.000000/16.000000/9.000000:R/0/270/0,box=0.000000/3.000000/13.000000:2.000000/12.000000/15.000000:n/0/0.000000/1.000000/2.000000/10.000000:d/0/0.000000/13.000000/2.000000/15.000000:w/0/13.000000/1.000000/15.000000/10.000000:e/0/13.000000/1.000000/15.000000/10.000000:s/0/0.000000/1.000000/2.000000/10.000000:u/0/0.000000/13.000000/2.000000/15.000000:R/0/270/0,box=14.000000/3.000000/13.000000:16.000000/12.000000/15.000000:n/0/14.000000/1.000000/16.000000/10.000000:d/0/14.000000/13.000000/16.000000/15.000000:w/0/13.000000/1.000000/15.000000/10.000000:e/0/13.000000/1.000000/15.000000/10.000000:s/0/14.000000/1.000000/16.000000/10.000000:u/0/14.000000/13.000000/16.000000/15.000000:R/0/270/0,box=0.000000/3.000000/9.000000:2.000000/6.000000/13.000000:d/0/0.000000/9.000000/2.000000/13.000000:w/0/13.000000/7.000000/15.000000/10.000000:e/0/13.000000/7.000000/15.000000/10.000000:u/0/0.000000/9.000000/2.000000/13.000000:R/0/270/0,box=0.000000/9.000000/9.000000:2.000000/12.000000/13.000000:d/0/0.000000/9.000000/2.000000/13.000000:w/0/13.000000/1.000000/15.000000/4.000000:e/0/13.000000/1.000000/15.000000/4.000000:u/0/0.000000/9.000000/2.000000/13.000000:R/0/270/0,box=14.000000/3.000000/9.000000:16.000000/6.000000/13.000000:d/0/14.000000/9.000000/16.000000/13.000000:w/0/13.000000/7.000000/15.000000/10.000000:e/0/13.000000/7.000000/15.000000/10.000000:u/0/14.000000/9.000000/16.000000/13.000000:R/0/270/0,box=14.000000/9.000000/9.000000:16.000000/12.000000/13.000000:d/0/14.000000/9.000000/16.000000/13.000000:w/0/13.000000/1.000000/15.000000/4.000000:e/0/13.000000/1.000000/15.000000/4.000000:u/0/14.000000/9.000000/16.000000/13.000000:R/0/270/0 +[1.19-]modellist:id=%mangrove_fence_gate,state=facing:east/in_wall:true/open:false,box=0.000000/2.000000/7.000000:2.000000/13.000000/9.000000:n/0/0.000000/0.000000/2.000000/11.000000:d/0/0.000000/7.000000/2.000000/9.000000:w/0/7.000000/0.000000/9.000000/11.000000:e/0/7.000000/0.000000/9.000000/11.000000:s/0/0.000000/0.000000/2.000000/11.000000:u/0/0.000000/7.000000/2.000000/9.000000:R/0/270/0,box=14.000000/2.000000/7.000000:16.000000/13.000000/9.000000:n/0/14.000000/0.000000/16.000000/11.000000:d/0/14.000000/7.000000/16.000000/9.000000:w/0/7.000000/0.000000/9.000000/11.000000:e/0/7.000000/0.000000/9.000000/11.000000:s/0/14.000000/0.000000/16.000000/11.000000:u/0/14.000000/7.000000/16.000000/9.000000:R/0/270/0,box=6.000000/3.000000/7.000000:8.000000/12.000000/9.000000:n/0/6.000000/1.000000/8.000000/10.000000:d/0/6.000000/7.000000/8.000000/9.000000:w/0/7.000000/1.000000/9.000000/10.000000:e/0/7.000000/1.000000/9.000000/10.000000:s/0/6.000000/1.000000/8.000000/10.000000:u/0/6.000000/7.000000/8.000000/9.000000:R/0/270/0,box=8.000000/3.000000/7.000000:10.000000/12.000000/9.000000:n/0/8.000000/1.000000/10.000000/10.000000:d/0/8.000000/7.000000/10.000000/9.000000:w/0/7.000000/1.000000/9.000000/10.000000:e/0/7.000000/1.000000/9.000000/10.000000:s/0/8.000000/1.000000/10.000000/10.000000:u/0/8.000000/7.000000/10.000000/9.000000:R/0/270/0,box=2.000000/3.000000/7.000000:6.000000/6.000000/9.000000:n/0/2.000000/7.000000/6.000000/10.000000:d/0/2.000000/7.000000/6.000000/9.000000:s/0/2.000000/7.000000/6.000000/10.000000:u/0/2.000000/7.000000/6.000000/9.000000:R/0/270/0,box=2.000000/9.000000/7.000000:6.000000/12.000000/9.000000:n/0/2.000000/1.000000/6.000000/4.000000:d/0/2.000000/7.000000/6.000000/9.000000:s/0/2.000000/1.000000/6.000000/4.000000:u/0/2.000000/7.000000/6.000000/9.000000:R/0/270/0,box=10.000000/3.000000/7.000000:14.000000/6.000000/9.000000:n/0/10.000000/7.000000/14.000000/10.000000:d/0/10.000000/7.000000/14.000000/9.000000:s/0/10.000000/7.000000/14.000000/10.000000:u/0/10.000000/7.000000/14.000000/9.000000:R/0/270/0,box=10.000000/9.000000/7.000000:14.000000/12.000000/9.000000:n/0/10.000000/1.000000/14.000000/4.000000:d/0/10.000000/7.000000/14.000000/9.000000:s/0/10.000000/1.000000/14.000000/4.000000:u/0/10.000000/7.000000/14.000000/9.000000:R/0/270/0 +[1.19-]modellist:id=%mangrove_fence_gate,state=facing:east/in_wall:false/open:true,box=0.000000/5.000000/7.000000:2.000000/16.000000/9.000000:n/0/0.000000/0.000000/2.000000/11.000000:d/0/0.000000/7.000000/2.000000/9.000000:w/0/7.000000/0.000000/9.000000/11.000000:e/0/7.000000/0.000000/9.000000/11.000000:s/0/0.000000/0.000000/2.000000/11.000000:u/0/0.000000/7.000000/2.000000/9.000000:R/0/270/0,box=14.000000/5.000000/7.000000:16.000000/16.000000/9.000000:n/0/14.000000/0.000000/16.000000/11.000000:d/0/14.000000/7.000000/16.000000/9.000000:w/0/7.000000/0.000000/9.000000/11.000000:e/0/7.000000/0.000000/9.000000/11.000000:s/0/14.000000/0.000000/16.000000/11.000000:u/0/14.000000/7.000000/16.000000/9.000000:R/0/270/0,box=0.000000/6.000000/13.000000:2.000000/15.000000/15.000000:n/0/0.000000/1.000000/2.000000/10.000000:d/0/0.000000/13.000000/2.000000/15.000000:w/0/13.000000/1.000000/15.000000/10.000000:e/0/13.000000/1.000000/15.000000/10.000000:s/0/0.000000/1.000000/2.000000/10.000000:u/0/0.000000/13.000000/2.000000/15.000000:R/0/270/0,box=14.000000/6.000000/13.000000:16.000000/15.000000/15.000000:n/0/14.000000/1.000000/16.000000/10.000000:d/0/14.000000/13.000000/16.000000/15.000000:w/0/13.000000/1.000000/15.000000/10.000000:e/0/13.000000/1.000000/15.000000/10.000000:s/0/14.000000/1.000000/16.000000/10.000000:u/0/14.000000/13.000000/16.000000/15.000000:R/0/270/0,box=0.000000/6.000000/9.000000:2.000000/9.000000/13.000000:d/0/0.000000/9.000000/2.000000/13.000000:w/0/13.000000/7.000000/15.000000/10.000000:e/0/13.000000/7.000000/15.000000/10.000000:u/0/0.000000/9.000000/2.000000/13.000000:R/0/270/0,box=0.000000/12.000000/9.000000:2.000000/15.000000/13.000000:d/0/0.000000/9.000000/2.000000/13.000000:w/0/13.000000/1.000000/15.000000/4.000000:e/0/13.000000/1.000000/15.000000/4.000000:u/0/0.000000/9.000000/2.000000/13.000000:R/0/270/0,box=14.000000/6.000000/9.000000:16.000000/9.000000/13.000000:d/0/14.000000/9.000000/16.000000/13.000000:w/0/13.000000/7.000000/15.000000/10.000000:e/0/13.000000/7.000000/15.000000/10.000000:u/0/14.000000/9.000000/16.000000/13.000000:R/0/270/0,box=14.000000/12.000000/9.000000:16.000000/15.000000/13.000000:d/0/14.000000/9.000000/16.000000/13.000000:w/0/13.000000/1.000000/15.000000/4.000000:e/0/13.000000/1.000000/15.000000/4.000000:u/0/14.000000/9.000000/16.000000/13.000000:R/0/270/0 +[1.19-]modellist:id=%mangrove_fence_gate,state=facing:east/in_wall:false/open:false,box=0.000000/5.000000/7.000000:2.000000/16.000000/9.000000:n/0/0.000000/0.000000/2.000000/11.000000:d/0/0.000000/7.000000/2.000000/9.000000:w/0/7.000000/0.000000/9.000000/11.000000:e/0/7.000000/0.000000/9.000000/11.000000:s/0/0.000000/0.000000/2.000000/11.000000:u/0/0.000000/7.000000/2.000000/9.000000:R/0/270/0,box=14.000000/5.000000/7.000000:16.000000/16.000000/9.000000:n/0/14.000000/0.000000/16.000000/11.000000:d/0/14.000000/7.000000/16.000000/9.000000:w/0/7.000000/0.000000/9.000000/11.000000:e/0/7.000000/0.000000/9.000000/11.000000:s/0/14.000000/0.000000/16.000000/11.000000:u/0/14.000000/7.000000/16.000000/9.000000:R/0/270/0,box=6.000000/6.000000/7.000000:8.000000/15.000000/9.000000:n/0/6.000000/1.000000/8.000000/10.000000:d/0/6.000000/7.000000/8.000000/9.000000:w/0/7.000000/1.000000/9.000000/10.000000:e/0/7.000000/1.000000/9.000000/10.000000:s/0/6.000000/1.000000/8.000000/10.000000:u/0/6.000000/7.000000/8.000000/9.000000:R/0/270/0,box=8.000000/6.000000/7.000000:10.000000/15.000000/9.000000:n/0/8.000000/1.000000/10.000000/10.000000:d/0/8.000000/7.000000/10.000000/9.000000:w/0/7.000000/1.000000/9.000000/10.000000:e/0/7.000000/1.000000/9.000000/10.000000:s/0/8.000000/1.000000/10.000000/10.000000:u/0/8.000000/7.000000/10.000000/9.000000:R/0/270/0,box=2.000000/6.000000/7.000000:6.000000/9.000000/9.000000:n/0/2.000000/7.000000/6.000000/10.000000:d/0/2.000000/7.000000/6.000000/9.000000:s/0/2.000000/7.000000/6.000000/10.000000:u/0/2.000000/7.000000/6.000000/9.000000:R/0/270/0,box=2.000000/12.000000/7.000000:6.000000/15.000000/9.000000:n/0/2.000000/1.000000/6.000000/4.000000:d/0/2.000000/7.000000/6.000000/9.000000:s/0/2.000000/1.000000/6.000000/4.000000:u/0/2.000000/7.000000/6.000000/9.000000:R/0/270/0,box=10.000000/6.000000/7.000000:14.000000/9.000000/9.000000:n/0/10.000000/7.000000/14.000000/10.000000:d/0/10.000000/7.000000/14.000000/9.000000:s/0/10.000000/7.000000/14.000000/10.000000:u/0/10.000000/7.000000/14.000000/9.000000:R/0/270/0,box=10.000000/12.000000/7.000000:14.000000/15.000000/9.000000:n/0/10.000000/1.000000/14.000000/4.000000:d/0/10.000000/7.000000/14.000000/9.000000:s/0/10.000000/1.000000/14.000000/4.000000:u/0/10.000000/7.000000/14.000000/9.000000:R/0/270/0 +[1.19-]modellist:id=%mangrove_fence,state=west:true/east:true/south:true/north:true,box=6.000000/0.000000/6.000000:10.000000/16.000000/10.000000:n/0/6.000000/0.000000/10.000000/16.000000:d/0/6.000000/6.000000/10.000000/10.000000:w/0/6.000000/0.000000/10.000000/16.000000:e/0/6.000000/0.000000/10.000000/16.000000:s/0/6.000000/0.000000/10.000000/16.000000:u/0/6.000000/6.000000/10.000000/10.000000,box=7.000000/12.000000/0.000000:9.000000/15.000000/9.000000:n/0/7.000000/1.000000/9.000000/4.000000:d/0/7.000000/0.000000/9.000000/9.000000:w/0/0.000000/1.000000/9.000000/4.000000:e/0/0.000000/1.000000/9.000000/4.000000:u/0/7.000000/0.000000/9.000000/9.000000,box=7.000000/6.000000/0.000000:9.000000/9.000000/9.000000:n/0/7.000000/7.000000/9.000000/10.000000:d/0/7.000000/0.000000/9.000000/9.000000:w/0/0.000000/7.000000/9.000000/10.000000:e/0/0.000000/7.000000/9.000000/10.000000:u/0/7.000000/0.000000/9.000000/9.000000,box=7.000000/12.000000/0.000000:9.000000/15.000000/9.000000:n/0/7.000000/1.000000/9.000000/4.000000:d/0/7.000000/0.000000/9.000000/9.000000:w/0/0.000000/1.000000/9.000000/4.000000:e/0/0.000000/1.000000/9.000000/4.000000:u/0/7.000000/0.000000/9.000000/9.000000:R/0/90/0,box=7.000000/6.000000/0.000000:9.000000/9.000000/9.000000:n/0/7.000000/7.000000/9.000000/10.000000:d/0/7.000000/0.000000/9.000000/9.000000:w/0/0.000000/7.000000/9.000000/10.000000:e/0/0.000000/7.000000/9.000000/10.000000:u/0/7.000000/0.000000/9.000000/9.000000:R/0/90/0,box=7.000000/12.000000/0.000000:9.000000/15.000000/9.000000:n/0/7.000000/1.000000/9.000000/4.000000:d/0/7.000000/0.000000/9.000000/9.000000:w/0/0.000000/1.000000/9.000000/4.000000:e/0/0.000000/1.000000/9.000000/4.000000:u/0/7.000000/0.000000/9.000000/9.000000:R/0/180/0,box=7.000000/6.000000/0.000000:9.000000/9.000000/9.000000:n/0/7.000000/7.000000/9.000000/10.000000:d/0/7.000000/0.000000/9.000000/9.000000:w/0/0.000000/7.000000/9.000000/10.000000:e/0/0.000000/7.000000/9.000000/10.000000:u/0/7.000000/0.000000/9.000000/9.000000:R/0/180/0,box=7.000000/12.000000/0.000000:9.000000/15.000000/9.000000:n/0/7.000000/1.000000/9.000000/4.000000:d/0/7.000000/0.000000/9.000000/9.000000:w/0/0.000000/1.000000/9.000000/4.000000:e/0/0.000000/1.000000/9.000000/4.000000:u/0/7.000000/0.000000/9.000000/9.000000:R/0/270/0,box=7.000000/6.000000/0.000000:9.000000/9.000000/9.000000:n/0/7.000000/7.000000/9.000000/10.000000:d/0/7.000000/0.000000/9.000000/9.000000:w/0/0.000000/7.000000/9.000000/10.000000:e/0/0.000000/7.000000/9.000000/10.000000:u/0/7.000000/0.000000/9.000000/9.000000:R/0/270/0 +[1.19-]modellist:id=%mangrove_fence,state=west:false/east:true/south:true/north:true,box=6.000000/0.000000/6.000000:10.000000/16.000000/10.000000:n/0/6.000000/0.000000/10.000000/16.000000:d/0/6.000000/6.000000/10.000000/10.000000:w/0/6.000000/0.000000/10.000000/16.000000:e/0/6.000000/0.000000/10.000000/16.000000:s/0/6.000000/0.000000/10.000000/16.000000:u/0/6.000000/6.000000/10.000000/10.000000,box=7.000000/12.000000/0.000000:9.000000/15.000000/9.000000:n/0/7.000000/1.000000/9.000000/4.000000:d/0/7.000000/0.000000/9.000000/9.000000:w/0/0.000000/1.000000/9.000000/4.000000:e/0/0.000000/1.000000/9.000000/4.000000:u/0/7.000000/0.000000/9.000000/9.000000,box=7.000000/6.000000/0.000000:9.000000/9.000000/9.000000:n/0/7.000000/7.000000/9.000000/10.000000:d/0/7.000000/0.000000/9.000000/9.000000:w/0/0.000000/7.000000/9.000000/10.000000:e/0/0.000000/7.000000/9.000000/10.000000:u/0/7.000000/0.000000/9.000000/9.000000,box=7.000000/12.000000/0.000000:9.000000/15.000000/9.000000:n/0/7.000000/1.000000/9.000000/4.000000:d/0/7.000000/0.000000/9.000000/9.000000:w/0/0.000000/1.000000/9.000000/4.000000:e/0/0.000000/1.000000/9.000000/4.000000:u/0/7.000000/0.000000/9.000000/9.000000:R/0/90/0,box=7.000000/6.000000/0.000000:9.000000/9.000000/9.000000:n/0/7.000000/7.000000/9.000000/10.000000:d/0/7.000000/0.000000/9.000000/9.000000:w/0/0.000000/7.000000/9.000000/10.000000:e/0/0.000000/7.000000/9.000000/10.000000:u/0/7.000000/0.000000/9.000000/9.000000:R/0/90/0,box=7.000000/12.000000/0.000000:9.000000/15.000000/9.000000:n/0/7.000000/1.000000/9.000000/4.000000:d/0/7.000000/0.000000/9.000000/9.000000:w/0/0.000000/1.000000/9.000000/4.000000:e/0/0.000000/1.000000/9.000000/4.000000:u/0/7.000000/0.000000/9.000000/9.000000:R/0/180/0,box=7.000000/6.000000/0.000000:9.000000/9.000000/9.000000:n/0/7.000000/7.000000/9.000000/10.000000:d/0/7.000000/0.000000/9.000000/9.000000:w/0/0.000000/7.000000/9.000000/10.000000:e/0/0.000000/7.000000/9.000000/10.000000:u/0/7.000000/0.000000/9.000000/9.000000:R/0/180/0 +[1.19-]modellist:id=%mangrove_fence,state=west:true/east:true/south:false/north:true,box=6.000000/0.000000/6.000000:10.000000/16.000000/10.000000:n/0/6.000000/0.000000/10.000000/16.000000:d/0/6.000000/6.000000/10.000000/10.000000:w/0/6.000000/0.000000/10.000000/16.000000:e/0/6.000000/0.000000/10.000000/16.000000:s/0/6.000000/0.000000/10.000000/16.000000:u/0/6.000000/6.000000/10.000000/10.000000,box=7.000000/12.000000/0.000000:9.000000/15.000000/9.000000:n/0/7.000000/1.000000/9.000000/4.000000:d/0/7.000000/0.000000/9.000000/9.000000:w/0/0.000000/1.000000/9.000000/4.000000:e/0/0.000000/1.000000/9.000000/4.000000:u/0/7.000000/0.000000/9.000000/9.000000,box=7.000000/6.000000/0.000000:9.000000/9.000000/9.000000:n/0/7.000000/7.000000/9.000000/10.000000:d/0/7.000000/0.000000/9.000000/9.000000:w/0/0.000000/7.000000/9.000000/10.000000:e/0/0.000000/7.000000/9.000000/10.000000:u/0/7.000000/0.000000/9.000000/9.000000,box=7.000000/12.000000/0.000000:9.000000/15.000000/9.000000:n/0/7.000000/1.000000/9.000000/4.000000:d/0/7.000000/0.000000/9.000000/9.000000:w/0/0.000000/1.000000/9.000000/4.000000:e/0/0.000000/1.000000/9.000000/4.000000:u/0/7.000000/0.000000/9.000000/9.000000:R/0/90/0,box=7.000000/6.000000/0.000000:9.000000/9.000000/9.000000:n/0/7.000000/7.000000/9.000000/10.000000:d/0/7.000000/0.000000/9.000000/9.000000:w/0/0.000000/7.000000/9.000000/10.000000:e/0/0.000000/7.000000/9.000000/10.000000:u/0/7.000000/0.000000/9.000000/9.000000:R/0/90/0,box=7.000000/12.000000/0.000000:9.000000/15.000000/9.000000:n/0/7.000000/1.000000/9.000000/4.000000:d/0/7.000000/0.000000/9.000000/9.000000:w/0/0.000000/1.000000/9.000000/4.000000:e/0/0.000000/1.000000/9.000000/4.000000:u/0/7.000000/0.000000/9.000000/9.000000:R/0/270/0,box=7.000000/6.000000/0.000000:9.000000/9.000000/9.000000:n/0/7.000000/7.000000/9.000000/10.000000:d/0/7.000000/0.000000/9.000000/9.000000:w/0/0.000000/7.000000/9.000000/10.000000:e/0/0.000000/7.000000/9.000000/10.000000:u/0/7.000000/0.000000/9.000000/9.000000:R/0/270/0 +[1.19-]modellist:id=%mangrove_fence,state=west:false/east:true/south:false/north:true,box=6.000000/0.000000/6.000000:10.000000/16.000000/10.000000:n/0/6.000000/0.000000/10.000000/16.000000:d/0/6.000000/6.000000/10.000000/10.000000:w/0/6.000000/0.000000/10.000000/16.000000:e/0/6.000000/0.000000/10.000000/16.000000:s/0/6.000000/0.000000/10.000000/16.000000:u/0/6.000000/6.000000/10.000000/10.000000,box=7.000000/12.000000/0.000000:9.000000/15.000000/9.000000:n/0/7.000000/1.000000/9.000000/4.000000:d/0/7.000000/0.000000/9.000000/9.000000:w/0/0.000000/1.000000/9.000000/4.000000:e/0/0.000000/1.000000/9.000000/4.000000:u/0/7.000000/0.000000/9.000000/9.000000,box=7.000000/6.000000/0.000000:9.000000/9.000000/9.000000:n/0/7.000000/7.000000/9.000000/10.000000:d/0/7.000000/0.000000/9.000000/9.000000:w/0/0.000000/7.000000/9.000000/10.000000:e/0/0.000000/7.000000/9.000000/10.000000:u/0/7.000000/0.000000/9.000000/9.000000,box=7.000000/12.000000/0.000000:9.000000/15.000000/9.000000:n/0/7.000000/1.000000/9.000000/4.000000:d/0/7.000000/0.000000/9.000000/9.000000:w/0/0.000000/1.000000/9.000000/4.000000:e/0/0.000000/1.000000/9.000000/4.000000:u/0/7.000000/0.000000/9.000000/9.000000:R/0/90/0,box=7.000000/6.000000/0.000000:9.000000/9.000000/9.000000:n/0/7.000000/7.000000/9.000000/10.000000:d/0/7.000000/0.000000/9.000000/9.000000:w/0/0.000000/7.000000/9.000000/10.000000:e/0/0.000000/7.000000/9.000000/10.000000:u/0/7.000000/0.000000/9.000000/9.000000:R/0/90/0 +[1.19-]modellist:id=%mangrove_fence,state=west:true/east:true/south:true/north:false,box=6.000000/0.000000/6.000000:10.000000/16.000000/10.000000:n/0/6.000000/0.000000/10.000000/16.000000:d/0/6.000000/6.000000/10.000000/10.000000:w/0/6.000000/0.000000/10.000000/16.000000:e/0/6.000000/0.000000/10.000000/16.000000:s/0/6.000000/0.000000/10.000000/16.000000:u/0/6.000000/6.000000/10.000000/10.000000,box=7.000000/12.000000/0.000000:9.000000/15.000000/9.000000:n/0/7.000000/1.000000/9.000000/4.000000:d/0/7.000000/0.000000/9.000000/9.000000:w/0/0.000000/1.000000/9.000000/4.000000:e/0/0.000000/1.000000/9.000000/4.000000:u/0/7.000000/0.000000/9.000000/9.000000:R/0/90/0,box=7.000000/6.000000/0.000000:9.000000/9.000000/9.000000:n/0/7.000000/7.000000/9.000000/10.000000:d/0/7.000000/0.000000/9.000000/9.000000:w/0/0.000000/7.000000/9.000000/10.000000:e/0/0.000000/7.000000/9.000000/10.000000:u/0/7.000000/0.000000/9.000000/9.000000:R/0/90/0,box=7.000000/12.000000/0.000000:9.000000/15.000000/9.000000:n/0/7.000000/1.000000/9.000000/4.000000:d/0/7.000000/0.000000/9.000000/9.000000:w/0/0.000000/1.000000/9.000000/4.000000:e/0/0.000000/1.000000/9.000000/4.000000:u/0/7.000000/0.000000/9.000000/9.000000:R/0/180/0,box=7.000000/6.000000/0.000000:9.000000/9.000000/9.000000:n/0/7.000000/7.000000/9.000000/10.000000:d/0/7.000000/0.000000/9.000000/9.000000:w/0/0.000000/7.000000/9.000000/10.000000:e/0/0.000000/7.000000/9.000000/10.000000:u/0/7.000000/0.000000/9.000000/9.000000:R/0/180/0,box=7.000000/12.000000/0.000000:9.000000/15.000000/9.000000:n/0/7.000000/1.000000/9.000000/4.000000:d/0/7.000000/0.000000/9.000000/9.000000:w/0/0.000000/1.000000/9.000000/4.000000:e/0/0.000000/1.000000/9.000000/4.000000:u/0/7.000000/0.000000/9.000000/9.000000:R/0/270/0,box=7.000000/6.000000/0.000000:9.000000/9.000000/9.000000:n/0/7.000000/7.000000/9.000000/10.000000:d/0/7.000000/0.000000/9.000000/9.000000:w/0/0.000000/7.000000/9.000000/10.000000:e/0/0.000000/7.000000/9.000000/10.000000:u/0/7.000000/0.000000/9.000000/9.000000:R/0/270/0 +[1.19-]modellist:id=%mangrove_fence,state=west:false/east:true/south:true/north:false,box=6.000000/0.000000/6.000000:10.000000/16.000000/10.000000:n/0/6.000000/0.000000/10.000000/16.000000:d/0/6.000000/6.000000/10.000000/10.000000:w/0/6.000000/0.000000/10.000000/16.000000:e/0/6.000000/0.000000/10.000000/16.000000:s/0/6.000000/0.000000/10.000000/16.000000:u/0/6.000000/6.000000/10.000000/10.000000,box=7.000000/12.000000/0.000000:9.000000/15.000000/9.000000:n/0/7.000000/1.000000/9.000000/4.000000:d/0/7.000000/0.000000/9.000000/9.000000:w/0/0.000000/1.000000/9.000000/4.000000:e/0/0.000000/1.000000/9.000000/4.000000:u/0/7.000000/0.000000/9.000000/9.000000:R/0/90/0,box=7.000000/6.000000/0.000000:9.000000/9.000000/9.000000:n/0/7.000000/7.000000/9.000000/10.000000:d/0/7.000000/0.000000/9.000000/9.000000:w/0/0.000000/7.000000/9.000000/10.000000:e/0/0.000000/7.000000/9.000000/10.000000:u/0/7.000000/0.000000/9.000000/9.000000:R/0/90/0,box=7.000000/12.000000/0.000000:9.000000/15.000000/9.000000:n/0/7.000000/1.000000/9.000000/4.000000:d/0/7.000000/0.000000/9.000000/9.000000:w/0/0.000000/1.000000/9.000000/4.000000:e/0/0.000000/1.000000/9.000000/4.000000:u/0/7.000000/0.000000/9.000000/9.000000:R/0/180/0,box=7.000000/6.000000/0.000000:9.000000/9.000000/9.000000:n/0/7.000000/7.000000/9.000000/10.000000:d/0/7.000000/0.000000/9.000000/9.000000:w/0/0.000000/7.000000/9.000000/10.000000:e/0/0.000000/7.000000/9.000000/10.000000:u/0/7.000000/0.000000/9.000000/9.000000:R/0/180/0 +[1.19-]modellist:id=%mangrove_fence,state=west:true/east:true/south:false/north:false,box=6.000000/0.000000/6.000000:10.000000/16.000000/10.000000:n/0/6.000000/0.000000/10.000000/16.000000:d/0/6.000000/6.000000/10.000000/10.000000:w/0/6.000000/0.000000/10.000000/16.000000:e/0/6.000000/0.000000/10.000000/16.000000:s/0/6.000000/0.000000/10.000000/16.000000:u/0/6.000000/6.000000/10.000000/10.000000,box=7.000000/12.000000/0.000000:9.000000/15.000000/9.000000:n/0/7.000000/1.000000/9.000000/4.000000:d/0/7.000000/0.000000/9.000000/9.000000:w/0/0.000000/1.000000/9.000000/4.000000:e/0/0.000000/1.000000/9.000000/4.000000:u/0/7.000000/0.000000/9.000000/9.000000:R/0/90/0,box=7.000000/6.000000/0.000000:9.000000/9.000000/9.000000:n/0/7.000000/7.000000/9.000000/10.000000:d/0/7.000000/0.000000/9.000000/9.000000:w/0/0.000000/7.000000/9.000000/10.000000:e/0/0.000000/7.000000/9.000000/10.000000:u/0/7.000000/0.000000/9.000000/9.000000:R/0/90/0,box=7.000000/12.000000/0.000000:9.000000/15.000000/9.000000:n/0/7.000000/1.000000/9.000000/4.000000:d/0/7.000000/0.000000/9.000000/9.000000:w/0/0.000000/1.000000/9.000000/4.000000:e/0/0.000000/1.000000/9.000000/4.000000:u/0/7.000000/0.000000/9.000000/9.000000:R/0/270/0,box=7.000000/6.000000/0.000000:9.000000/9.000000/9.000000:n/0/7.000000/7.000000/9.000000/10.000000:d/0/7.000000/0.000000/9.000000/9.000000:w/0/0.000000/7.000000/9.000000/10.000000:e/0/0.000000/7.000000/9.000000/10.000000:u/0/7.000000/0.000000/9.000000/9.000000:R/0/270/0 +[1.19-]modellist:id=%mangrove_fence,state=west:false/east:true/south:false/north:false,box=6.000000/0.000000/6.000000:10.000000/16.000000/10.000000:n/0/6.000000/0.000000/10.000000/16.000000:d/0/6.000000/6.000000/10.000000/10.000000:w/0/6.000000/0.000000/10.000000/16.000000:e/0/6.000000/0.000000/10.000000/16.000000:s/0/6.000000/0.000000/10.000000/16.000000:u/0/6.000000/6.000000/10.000000/10.000000,box=7.000000/12.000000/0.000000:9.000000/15.000000/9.000000:n/0/7.000000/1.000000/9.000000/4.000000:d/0/7.000000/0.000000/9.000000/9.000000:w/0/0.000000/1.000000/9.000000/4.000000:e/0/0.000000/1.000000/9.000000/4.000000:u/0/7.000000/0.000000/9.000000/9.000000:R/0/90/0,box=7.000000/6.000000/0.000000:9.000000/9.000000/9.000000:n/0/7.000000/7.000000/9.000000/10.000000:d/0/7.000000/0.000000/9.000000/9.000000:w/0/0.000000/7.000000/9.000000/10.000000:e/0/0.000000/7.000000/9.000000/10.000000:u/0/7.000000/0.000000/9.000000/9.000000:R/0/90/0 +[1.19-]modellist:id=%mangrove_fence,state=west:true/east:false/south:true/north:true,box=6.000000/0.000000/6.000000:10.000000/16.000000/10.000000:n/0/6.000000/0.000000/10.000000/16.000000:d/0/6.000000/6.000000/10.000000/10.000000:w/0/6.000000/0.000000/10.000000/16.000000:e/0/6.000000/0.000000/10.000000/16.000000:s/0/6.000000/0.000000/10.000000/16.000000:u/0/6.000000/6.000000/10.000000/10.000000,box=7.000000/12.000000/0.000000:9.000000/15.000000/9.000000:n/0/7.000000/1.000000/9.000000/4.000000:d/0/7.000000/0.000000/9.000000/9.000000:w/0/0.000000/1.000000/9.000000/4.000000:e/0/0.000000/1.000000/9.000000/4.000000:u/0/7.000000/0.000000/9.000000/9.000000,box=7.000000/6.000000/0.000000:9.000000/9.000000/9.000000:n/0/7.000000/7.000000/9.000000/10.000000:d/0/7.000000/0.000000/9.000000/9.000000:w/0/0.000000/7.000000/9.000000/10.000000:e/0/0.000000/7.000000/9.000000/10.000000:u/0/7.000000/0.000000/9.000000/9.000000,box=7.000000/12.000000/0.000000:9.000000/15.000000/9.000000:n/0/7.000000/1.000000/9.000000/4.000000:d/0/7.000000/0.000000/9.000000/9.000000:w/0/0.000000/1.000000/9.000000/4.000000:e/0/0.000000/1.000000/9.000000/4.000000:u/0/7.000000/0.000000/9.000000/9.000000:R/0/180/0,box=7.000000/6.000000/0.000000:9.000000/9.000000/9.000000:n/0/7.000000/7.000000/9.000000/10.000000:d/0/7.000000/0.000000/9.000000/9.000000:w/0/0.000000/7.000000/9.000000/10.000000:e/0/0.000000/7.000000/9.000000/10.000000:u/0/7.000000/0.000000/9.000000/9.000000:R/0/180/0,box=7.000000/12.000000/0.000000:9.000000/15.000000/9.000000:n/0/7.000000/1.000000/9.000000/4.000000:d/0/7.000000/0.000000/9.000000/9.000000:w/0/0.000000/1.000000/9.000000/4.000000:e/0/0.000000/1.000000/9.000000/4.000000:u/0/7.000000/0.000000/9.000000/9.000000:R/0/270/0,box=7.000000/6.000000/0.000000:9.000000/9.000000/9.000000:n/0/7.000000/7.000000/9.000000/10.000000:d/0/7.000000/0.000000/9.000000/9.000000:w/0/0.000000/7.000000/9.000000/10.000000:e/0/0.000000/7.000000/9.000000/10.000000:u/0/7.000000/0.000000/9.000000/9.000000:R/0/270/0 +[1.19-]modellist:id=%mangrove_fence,state=west:false/east:false/south:true/north:true,box=6.000000/0.000000/6.000000:10.000000/16.000000/10.000000:n/0/6.000000/0.000000/10.000000/16.000000:d/0/6.000000/6.000000/10.000000/10.000000:w/0/6.000000/0.000000/10.000000/16.000000:e/0/6.000000/0.000000/10.000000/16.000000:s/0/6.000000/0.000000/10.000000/16.000000:u/0/6.000000/6.000000/10.000000/10.000000,box=7.000000/12.000000/0.000000:9.000000/15.000000/9.000000:n/0/7.000000/1.000000/9.000000/4.000000:d/0/7.000000/0.000000/9.000000/9.000000:w/0/0.000000/1.000000/9.000000/4.000000:e/0/0.000000/1.000000/9.000000/4.000000:u/0/7.000000/0.000000/9.000000/9.000000,box=7.000000/6.000000/0.000000:9.000000/9.000000/9.000000:n/0/7.000000/7.000000/9.000000/10.000000:d/0/7.000000/0.000000/9.000000/9.000000:w/0/0.000000/7.000000/9.000000/10.000000:e/0/0.000000/7.000000/9.000000/10.000000:u/0/7.000000/0.000000/9.000000/9.000000,box=7.000000/12.000000/0.000000:9.000000/15.000000/9.000000:n/0/7.000000/1.000000/9.000000/4.000000:d/0/7.000000/0.000000/9.000000/9.000000:w/0/0.000000/1.000000/9.000000/4.000000:e/0/0.000000/1.000000/9.000000/4.000000:u/0/7.000000/0.000000/9.000000/9.000000:R/0/180/0,box=7.000000/6.000000/0.000000:9.000000/9.000000/9.000000:n/0/7.000000/7.000000/9.000000/10.000000:d/0/7.000000/0.000000/9.000000/9.000000:w/0/0.000000/7.000000/9.000000/10.000000:e/0/0.000000/7.000000/9.000000/10.000000:u/0/7.000000/0.000000/9.000000/9.000000:R/0/180/0 +[1.19-]modellist:id=%mangrove_fence,state=west:true/east:false/south:false/north:true,box=6.000000/0.000000/6.000000:10.000000/16.000000/10.000000:n/0/6.000000/0.000000/10.000000/16.000000:d/0/6.000000/6.000000/10.000000/10.000000:w/0/6.000000/0.000000/10.000000/16.000000:e/0/6.000000/0.000000/10.000000/16.000000:s/0/6.000000/0.000000/10.000000/16.000000:u/0/6.000000/6.000000/10.000000/10.000000,box=7.000000/12.000000/0.000000:9.000000/15.000000/9.000000:n/0/7.000000/1.000000/9.000000/4.000000:d/0/7.000000/0.000000/9.000000/9.000000:w/0/0.000000/1.000000/9.000000/4.000000:e/0/0.000000/1.000000/9.000000/4.000000:u/0/7.000000/0.000000/9.000000/9.000000,box=7.000000/6.000000/0.000000:9.000000/9.000000/9.000000:n/0/7.000000/7.000000/9.000000/10.000000:d/0/7.000000/0.000000/9.000000/9.000000:w/0/0.000000/7.000000/9.000000/10.000000:e/0/0.000000/7.000000/9.000000/10.000000:u/0/7.000000/0.000000/9.000000/9.000000,box=7.000000/12.000000/0.000000:9.000000/15.000000/9.000000:n/0/7.000000/1.000000/9.000000/4.000000:d/0/7.000000/0.000000/9.000000/9.000000:w/0/0.000000/1.000000/9.000000/4.000000:e/0/0.000000/1.000000/9.000000/4.000000:u/0/7.000000/0.000000/9.000000/9.000000:R/0/270/0,box=7.000000/6.000000/0.000000:9.000000/9.000000/9.000000:n/0/7.000000/7.000000/9.000000/10.000000:d/0/7.000000/0.000000/9.000000/9.000000:w/0/0.000000/7.000000/9.000000/10.000000:e/0/0.000000/7.000000/9.000000/10.000000:u/0/7.000000/0.000000/9.000000/9.000000:R/0/270/0 +[1.19-]modellist:id=%mangrove_fence,state=west:false/east:false/south:false/north:true,box=6.000000/0.000000/6.000000:10.000000/16.000000/10.000000:n/0/6.000000/0.000000/10.000000/16.000000:d/0/6.000000/6.000000/10.000000/10.000000:w/0/6.000000/0.000000/10.000000/16.000000:e/0/6.000000/0.000000/10.000000/16.000000:s/0/6.000000/0.000000/10.000000/16.000000:u/0/6.000000/6.000000/10.000000/10.000000,box=7.000000/12.000000/0.000000:9.000000/15.000000/9.000000:n/0/7.000000/1.000000/9.000000/4.000000:d/0/7.000000/0.000000/9.000000/9.000000:w/0/0.000000/1.000000/9.000000/4.000000:e/0/0.000000/1.000000/9.000000/4.000000:u/0/7.000000/0.000000/9.000000/9.000000,box=7.000000/6.000000/0.000000:9.000000/9.000000/9.000000:n/0/7.000000/7.000000/9.000000/10.000000:d/0/7.000000/0.000000/9.000000/9.000000:w/0/0.000000/7.000000/9.000000/10.000000:e/0/0.000000/7.000000/9.000000/10.000000:u/0/7.000000/0.000000/9.000000/9.000000 +[1.19-]modellist:id=%mangrove_fence,state=west:true/east:false/south:true/north:false,box=6.000000/0.000000/6.000000:10.000000/16.000000/10.000000:n/0/6.000000/0.000000/10.000000/16.000000:d/0/6.000000/6.000000/10.000000/10.000000:w/0/6.000000/0.000000/10.000000/16.000000:e/0/6.000000/0.000000/10.000000/16.000000:s/0/6.000000/0.000000/10.000000/16.000000:u/0/6.000000/6.000000/10.000000/10.000000,box=7.000000/12.000000/0.000000:9.000000/15.000000/9.000000:n/0/7.000000/1.000000/9.000000/4.000000:d/0/7.000000/0.000000/9.000000/9.000000:w/0/0.000000/1.000000/9.000000/4.000000:e/0/0.000000/1.000000/9.000000/4.000000:u/0/7.000000/0.000000/9.000000/9.000000:R/0/180/0,box=7.000000/6.000000/0.000000:9.000000/9.000000/9.000000:n/0/7.000000/7.000000/9.000000/10.000000:d/0/7.000000/0.000000/9.000000/9.000000:w/0/0.000000/7.000000/9.000000/10.000000:e/0/0.000000/7.000000/9.000000/10.000000:u/0/7.000000/0.000000/9.000000/9.000000:R/0/180/0,box=7.000000/12.000000/0.000000:9.000000/15.000000/9.000000:n/0/7.000000/1.000000/9.000000/4.000000:d/0/7.000000/0.000000/9.000000/9.000000:w/0/0.000000/1.000000/9.000000/4.000000:e/0/0.000000/1.000000/9.000000/4.000000:u/0/7.000000/0.000000/9.000000/9.000000:R/0/270/0,box=7.000000/6.000000/0.000000:9.000000/9.000000/9.000000:n/0/7.000000/7.000000/9.000000/10.000000:d/0/7.000000/0.000000/9.000000/9.000000:w/0/0.000000/7.000000/9.000000/10.000000:e/0/0.000000/7.000000/9.000000/10.000000:u/0/7.000000/0.000000/9.000000/9.000000:R/0/270/0 +[1.19-]modellist:id=%mangrove_fence,state=west:false/east:false/south:true/north:false,box=6.000000/0.000000/6.000000:10.000000/16.000000/10.000000:n/0/6.000000/0.000000/10.000000/16.000000:d/0/6.000000/6.000000/10.000000/10.000000:w/0/6.000000/0.000000/10.000000/16.000000:e/0/6.000000/0.000000/10.000000/16.000000:s/0/6.000000/0.000000/10.000000/16.000000:u/0/6.000000/6.000000/10.000000/10.000000,box=7.000000/12.000000/0.000000:9.000000/15.000000/9.000000:n/0/7.000000/1.000000/9.000000/4.000000:d/0/7.000000/0.000000/9.000000/9.000000:w/0/0.000000/1.000000/9.000000/4.000000:e/0/0.000000/1.000000/9.000000/4.000000:u/0/7.000000/0.000000/9.000000/9.000000:R/0/180/0,box=7.000000/6.000000/0.000000:9.000000/9.000000/9.000000:n/0/7.000000/7.000000/9.000000/10.000000:d/0/7.000000/0.000000/9.000000/9.000000:w/0/0.000000/7.000000/9.000000/10.000000:e/0/0.000000/7.000000/9.000000/10.000000:u/0/7.000000/0.000000/9.000000/9.000000:R/0/180/0 +[1.19-]modellist:id=%mangrove_fence,state=west:true/east:false/south:false/north:false,box=6.000000/0.000000/6.000000:10.000000/16.000000/10.000000:n/0/6.000000/0.000000/10.000000/16.000000:d/0/6.000000/6.000000/10.000000/10.000000:w/0/6.000000/0.000000/10.000000/16.000000:e/0/6.000000/0.000000/10.000000/16.000000:s/0/6.000000/0.000000/10.000000/16.000000:u/0/6.000000/6.000000/10.000000/10.000000,box=7.000000/12.000000/0.000000:9.000000/15.000000/9.000000:n/0/7.000000/1.000000/9.000000/4.000000:d/0/7.000000/0.000000/9.000000/9.000000:w/0/0.000000/1.000000/9.000000/4.000000:e/0/0.000000/1.000000/9.000000/4.000000:u/0/7.000000/0.000000/9.000000/9.000000:R/0/270/0,box=7.000000/6.000000/0.000000:9.000000/9.000000/9.000000:n/0/7.000000/7.000000/9.000000/10.000000:d/0/7.000000/0.000000/9.000000/9.000000:w/0/0.000000/7.000000/9.000000/10.000000:e/0/0.000000/7.000000/9.000000/10.000000:u/0/7.000000/0.000000/9.000000/9.000000:R/0/270/0 +[1.19-]modellist:id=%mangrove_fence,state=west:false/east:false/south:false/north:false,box=6.000000/0.000000/6.000000:10.000000/16.000000/10.000000:n/0/6.000000/0.000000/10.000000/16.000000:d/0/6.000000/6.000000/10.000000/10.000000:w/0/6.000000/0.000000/10.000000/16.000000:e/0/6.000000/0.000000/10.000000/16.000000:s/0/6.000000/0.000000/10.000000/16.000000:u/0/6.000000/6.000000/10.000000/10.000000 +[1.19-]modellist:id=%mangrove_door,state=facing:north/hinge:left/half:upper/open:true,box=0.000000/0.000000/0.000000:3.000000/16.000000/16.000000:n/0/0.000000/0.000000/3.000000/16.000000:w/0/16.000000/0.000000/0.000000/16.000000:e/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/3.000000/16.000000:u270/0/0.000000/3.000000/16.000000/0.000000 +[1.19-]modellist:id=%mangrove_door,state=facing:north/hinge:left/half:upper/open:false,box=0.000000/0.000000/0.000000:3.000000/16.000000/16.000000:n/0/3.000000/0.000000/0.000000/16.000000:w/0/0.000000/0.000000/16.000000/16.000000:e/0/16.000000/0.000000/0.000000/16.000000:s/0/0.000000/0.000000/3.000000/16.000000:u90/0/0.000000/3.000000/16.000000/0.000000:R/0/270/0 +[1.19-]modellist:id=%mangrove_door,state=facing:north/hinge:right/half:upper/open:true,box=0.000000/0.000000/0.000000:3.000000/16.000000/16.000000:n/0/3.000000/0.000000/0.000000/16.000000:w/0/0.000000/0.000000/16.000000/16.000000:e/0/16.000000/0.000000/0.000000/16.000000:s/0/3.000000/0.000000/0.000000/16.000000:u90/0/0.000000/0.000000/16.000000/3.000000:R/0/180/0 +[1.19-]modellist:id=%mangrove_door,state=facing:north/hinge:right/half:upper/open:false,box=0.000000/0.000000/0.000000:3.000000/16.000000/16.000000:n/0/3.000000/0.000000/0.000000/16.000000:w/0/16.000000/0.000000/0.000000/16.000000:e/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/3.000000/16.000000:u270/0/0.000000/0.000000/16.000000/3.000000:R/0/270/0 +[1.19-]modellist:id=%mangrove_door,state=facing:north/hinge:left/half:lower/open:true,box=0.000000/0.000000/0.000000:3.000000/16.000000/16.000000:n/0/0.000000/0.000000/3.000000/16.000000:d90/0/0.000000/16.000000/16.000000/13.000000:w/0/16.000000/0.000000/0.000000/16.000000:e/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/3.000000/16.000000 +[1.19-]modellist:id=%mangrove_door,state=facing:north/hinge:left/half:lower/open:false,box=0.000000/0.000000/0.000000:3.000000/16.000000/16.000000:n/0/3.000000/0.000000/0.000000/16.000000:d90/0/16.000000/13.000000/0.000000/16.000000:w/0/0.000000/0.000000/16.000000/16.000000:e/0/16.000000/0.000000/0.000000/16.000000:s/0/0.000000/0.000000/3.000000/16.000000:R/0/270/0 +[1.19-]modellist:id=%mangrove_door,state=facing:north/hinge:right/half:lower/open:true,box=0.000000/0.000000/0.000000:3.000000/16.000000/16.000000:n/0/3.000000/0.000000/0.000000/16.000000:d90/0/16.000000/16.000000/0.000000/13.000000:w/0/0.000000/0.000000/16.000000/16.000000:e/0/16.000000/0.000000/0.000000/16.000000:s/0/3.000000/0.000000/0.000000/16.000000:R/0/180/0 +[1.19-]modellist:id=%mangrove_door,state=facing:north/hinge:right/half:lower/open:false,box=0.000000/0.000000/0.000000:3.000000/16.000000/16.000000:n/0/3.000000/0.000000/0.000000/16.000000:d90/0/0.000000/13.000000/16.000000/16.000000:w/0/16.000000/0.000000/0.000000/16.000000:e/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/3.000000/16.000000:R/0/270/0 +[1.19-]modellist:id=%mangrove_door,state=facing:south/hinge:left/half:upper/open:true,box=0.000000/0.000000/0.000000:3.000000/16.000000/16.000000:n/0/0.000000/0.000000/3.000000/16.000000:w/0/16.000000/0.000000/0.000000/16.000000:e/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/3.000000/16.000000:u270/0/0.000000/3.000000/16.000000/0.000000:R/0/180/0 +[1.19-]modellist:id=%mangrove_door,state=facing:south/hinge:left/half:upper/open:false,box=0.000000/0.000000/0.000000:3.000000/16.000000/16.000000:n/0/3.000000/0.000000/0.000000/16.000000:w/0/0.000000/0.000000/16.000000/16.000000:e/0/16.000000/0.000000/0.000000/16.000000:s/0/0.000000/0.000000/3.000000/16.000000:u90/0/0.000000/3.000000/16.000000/0.000000:R/0/90/0 +[1.19-]modellist:id=%mangrove_door,state=facing:south/hinge:right/half:upper/open:true,box=0.000000/0.000000/0.000000:3.000000/16.000000/16.000000:n/0/3.000000/0.000000/0.000000/16.000000:w/0/0.000000/0.000000/16.000000/16.000000:e/0/16.000000/0.000000/0.000000/16.000000:s/0/3.000000/0.000000/0.000000/16.000000:u90/0/0.000000/0.000000/16.000000/3.000000 +[1.19-]modellist:id=%mangrove_door,state=facing:south/hinge:right/half:upper/open:false,box=0.000000/0.000000/0.000000:3.000000/16.000000/16.000000:n/0/3.000000/0.000000/0.000000/16.000000:w/0/16.000000/0.000000/0.000000/16.000000:e/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/3.000000/16.000000:u270/0/0.000000/0.000000/16.000000/3.000000:R/0/90/0 +[1.19-]modellist:id=%mangrove_door,state=facing:south/hinge:left/half:lower/open:true,box=0.000000/0.000000/0.000000:3.000000/16.000000/16.000000:n/0/0.000000/0.000000/3.000000/16.000000:d90/0/0.000000/16.000000/16.000000/13.000000:w/0/16.000000/0.000000/0.000000/16.000000:e/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/3.000000/16.000000:R/0/180/0 +[1.19-]modellist:id=%mangrove_door,state=facing:south/hinge:left/half:lower/open:false,box=0.000000/0.000000/0.000000:3.000000/16.000000/16.000000:n/0/3.000000/0.000000/0.000000/16.000000:d90/0/16.000000/13.000000/0.000000/16.000000:w/0/0.000000/0.000000/16.000000/16.000000:e/0/16.000000/0.000000/0.000000/16.000000:s/0/0.000000/0.000000/3.000000/16.000000:R/0/90/0 +[1.19-]modellist:id=%mangrove_door,state=facing:south/hinge:right/half:lower/open:true,box=0.000000/0.000000/0.000000:3.000000/16.000000/16.000000:n/0/3.000000/0.000000/0.000000/16.000000:d90/0/16.000000/16.000000/0.000000/13.000000:w/0/0.000000/0.000000/16.000000/16.000000:e/0/16.000000/0.000000/0.000000/16.000000:s/0/3.000000/0.000000/0.000000/16.000000 +[1.19-]modellist:id=%mangrove_door,state=facing:south/hinge:right/half:lower/open:false,box=0.000000/0.000000/0.000000:3.000000/16.000000/16.000000:n/0/3.000000/0.000000/0.000000/16.000000:d90/0/0.000000/13.000000/16.000000/16.000000:w/0/16.000000/0.000000/0.000000/16.000000:e/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/3.000000/16.000000:R/0/90/0 +[1.19-]modellist:id=%mangrove_door,state=facing:west/hinge:left/half:upper/open:true,box=0.000000/0.000000/0.000000:3.000000/16.000000/16.000000:n/0/0.000000/0.000000/3.000000/16.000000:w/0/16.000000/0.000000/0.000000/16.000000:e/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/3.000000/16.000000:u270/0/0.000000/3.000000/16.000000/0.000000:R/0/270/0 +[1.19-]modellist:id=%mangrove_door,state=facing:west/hinge:left/half:upper/open:false,box=0.000000/0.000000/0.000000:3.000000/16.000000/16.000000:n/0/3.000000/0.000000/0.000000/16.000000:w/0/0.000000/0.000000/16.000000/16.000000:e/0/16.000000/0.000000/0.000000/16.000000:s/0/0.000000/0.000000/3.000000/16.000000:u90/0/0.000000/3.000000/16.000000/0.000000:R/0/180/0 +[1.19-]modellist:id=%mangrove_door,state=facing:west/hinge:right/half:upper/open:true,box=0.000000/0.000000/0.000000:3.000000/16.000000/16.000000:n/0/3.000000/0.000000/0.000000/16.000000:w/0/0.000000/0.000000/16.000000/16.000000:e/0/16.000000/0.000000/0.000000/16.000000:s/0/3.000000/0.000000/0.000000/16.000000:u90/0/0.000000/0.000000/16.000000/3.000000:R/0/90/0 +[1.19-]modellist:id=%mangrove_door,state=facing:west/hinge:right/half:upper/open:false,box=0.000000/0.000000/0.000000:3.000000/16.000000/16.000000:n/0/3.000000/0.000000/0.000000/16.000000:w/0/16.000000/0.000000/0.000000/16.000000:e/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/3.000000/16.000000:u270/0/0.000000/0.000000/16.000000/3.000000:R/0/180/0 +[1.19-]modellist:id=%mangrove_door,state=facing:west/hinge:left/half:lower/open:true,box=0.000000/0.000000/0.000000:3.000000/16.000000/16.000000:n/0/0.000000/0.000000/3.000000/16.000000:d90/0/0.000000/16.000000/16.000000/13.000000:w/0/16.000000/0.000000/0.000000/16.000000:e/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/3.000000/16.000000:R/0/270/0 +[1.19-]modellist:id=%mangrove_door,state=facing:west/hinge:left/half:lower/open:false,box=0.000000/0.000000/0.000000:3.000000/16.000000/16.000000:n/0/3.000000/0.000000/0.000000/16.000000:d90/0/16.000000/13.000000/0.000000/16.000000:w/0/0.000000/0.000000/16.000000/16.000000:e/0/16.000000/0.000000/0.000000/16.000000:s/0/0.000000/0.000000/3.000000/16.000000:R/0/180/0 +[1.19-]modellist:id=%mangrove_door,state=facing:west/hinge:right/half:lower/open:true,box=0.000000/0.000000/0.000000:3.000000/16.000000/16.000000:n/0/3.000000/0.000000/0.000000/16.000000:d90/0/16.000000/16.000000/0.000000/13.000000:w/0/0.000000/0.000000/16.000000/16.000000:e/0/16.000000/0.000000/0.000000/16.000000:s/0/3.000000/0.000000/0.000000/16.000000:R/0/90/0 +[1.19-]modellist:id=%mangrove_door,state=facing:west/hinge:right/half:lower/open:false,box=0.000000/0.000000/0.000000:3.000000/16.000000/16.000000:n/0/3.000000/0.000000/0.000000/16.000000:d90/0/0.000000/13.000000/16.000000/16.000000:w/0/16.000000/0.000000/0.000000/16.000000:e/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/3.000000/16.000000:R/0/180/0 +[1.19-]modellist:id=%mangrove_door,state=facing:east/hinge:left/half:upper/open:true,box=0.000000/0.000000/0.000000:3.000000/16.000000/16.000000:n/0/0.000000/0.000000/3.000000/16.000000:w/0/16.000000/0.000000/0.000000/16.000000:e/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/3.000000/16.000000:u270/0/0.000000/3.000000/16.000000/0.000000:R/0/90/0 +[1.19-]modellist:id=%mangrove_door,state=facing:east/hinge:left/half:upper/open:false,box=0.000000/0.000000/0.000000:3.000000/16.000000/16.000000:n/0/3.000000/0.000000/0.000000/16.000000:w/0/0.000000/0.000000/16.000000/16.000000:e/0/16.000000/0.000000/0.000000/16.000000:s/0/0.000000/0.000000/3.000000/16.000000:u90/0/0.000000/3.000000/16.000000/0.000000 +[1.19-]modellist:id=%mangrove_door,state=facing:east/hinge:right/half:upper/open:true,box=0.000000/0.000000/0.000000:3.000000/16.000000/16.000000:n/0/3.000000/0.000000/0.000000/16.000000:w/0/0.000000/0.000000/16.000000/16.000000:e/0/16.000000/0.000000/0.000000/16.000000:s/0/3.000000/0.000000/0.000000/16.000000:u90/0/0.000000/0.000000/16.000000/3.000000:R/0/270/0 +[1.19-]modellist:id=%mangrove_door,state=facing:east/hinge:right/half:upper/open:false,box=0.000000/0.000000/0.000000:3.000000/16.000000/16.000000:n/0/3.000000/0.000000/0.000000/16.000000:w/0/16.000000/0.000000/0.000000/16.000000:e/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/3.000000/16.000000:u270/0/0.000000/0.000000/16.000000/3.000000 +[1.19-]modellist:id=%mangrove_door,state=facing:east/hinge:left/half:lower/open:true,box=0.000000/0.000000/0.000000:3.000000/16.000000/16.000000:n/0/0.000000/0.000000/3.000000/16.000000:d90/0/0.000000/16.000000/16.000000/13.000000:w/0/16.000000/0.000000/0.000000/16.000000:e/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/3.000000/16.000000:R/0/90/0 +[1.19-]modellist:id=%mangrove_door,state=facing:east/hinge:left/half:lower/open:false,box=0.000000/0.000000/0.000000:3.000000/16.000000/16.000000:n/0/3.000000/0.000000/0.000000/16.000000:d90/0/16.000000/13.000000/0.000000/16.000000:w/0/0.000000/0.000000/16.000000/16.000000:e/0/16.000000/0.000000/0.000000/16.000000:s/0/0.000000/0.000000/3.000000/16.000000 +[1.19-]modellist:id=%mangrove_door,state=facing:east/hinge:right/half:lower/open:true,box=0.000000/0.000000/0.000000:3.000000/16.000000/16.000000:n/0/3.000000/0.000000/0.000000/16.000000:d90/0/16.000000/16.000000/0.000000/13.000000:w/0/0.000000/0.000000/16.000000/16.000000:e/0/16.000000/0.000000/0.000000/16.000000:s/0/3.000000/0.000000/0.000000/16.000000:R/0/270/0 +[1.19-]modellist:id=%mangrove_door,state=facing:east/hinge:right/half:lower/open:false,box=0.000000/0.000000/0.000000:3.000000/16.000000/16.000000:n/0/3.000000/0.000000/0.000000/16.000000:d90/0/0.000000/13.000000/16.000000/16.000000:w/0/16.000000/0.000000/0.000000/16.000000:e/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/3.000000/16.000000 +[1.19-]modellist:id=%stripped_mangrove_wood,state=axis:x,box=0.000000/0.000000/0.000000:16.000000/16.000000/16.000000:n/0:d/0:w/0:e/0:s/0:u/0:R/90/90/0 +[1.19-]modellist:id=%stripped_mangrove_wood,state=axis:z,box=0.000000/0.000000/0.000000:16.000000/16.000000/16.000000:n/0:d/0:w/0:e/0:s/0:u/0:R/90/0/0 +[1.19-]modellist:id=%mud_brick_stairs,state=facing:north/half:top/shape:straight,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/0/0.000000/0.000000/16.000000/16.000000:R/180/270/0,box=8.000000/8.000000/0.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/8.000000/8.000000:w/0/0.000000/0.000000/16.000000/8.000000:e/0/0.000000/0.000000/16.000000/8.000000:s/0/8.000000/0.000000/16.000000/8.000000:u/0/8.000000/0.000000/16.000000/16.000000:R/180/270/0 +[1.19-]modellist:id=%mud_brick_stairs,state=facing:north/half:top/shape:inner_left,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/0/0.000000/0.000000/16.000000/16.000000:R/180/270/0,box=8.000000/8.000000/0.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/8.000000/8.000000:w/0/0.000000/0.000000/16.000000/8.000000:e/0/0.000000/0.000000/16.000000/8.000000:s/0/8.000000/0.000000/16.000000/8.000000:u/0/8.000000/0.000000/16.000000/16.000000:R/180/270/0,box=0.000000/8.000000/8.000000:8.000000/16.000000/16.000000:n/0/8.000000/0.000000/16.000000/8.000000:w/0/8.000000/0.000000/16.000000/8.000000:s/0/0.000000/0.000000/8.000000/8.000000:u/0/0.000000/8.000000/8.000000/16.000000:R/180/270/0 +[1.19-]modellist:id=%mud_brick_stairs,state=facing:north/half:top/shape:inner_right,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/0/0.000000/0.000000/16.000000/16.000000:R/180/0/0,box=8.000000/8.000000/0.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/8.000000/8.000000:w/0/0.000000/0.000000/16.000000/8.000000:e/0/0.000000/0.000000/16.000000/8.000000:s/0/8.000000/0.000000/16.000000/8.000000:u/0/8.000000/0.000000/16.000000/16.000000:R/180/0/0,box=0.000000/8.000000/8.000000:8.000000/16.000000/16.000000:n/0/8.000000/0.000000/16.000000/8.000000:w/0/8.000000/0.000000/16.000000/8.000000:s/0/0.000000/0.000000/8.000000/8.000000:u/0/0.000000/8.000000/8.000000/16.000000:R/180/0/0 +[1.19-]modellist:id=%mud_brick_stairs,state=facing:north/half:top/shape:outer_left,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/0/0.000000/0.000000/16.000000/16.000000:R/180/270/0,box=8.000000/8.000000/8.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/8.000000/8.000000:w/0/8.000000/0.000000/16.000000/8.000000:e/0/0.000000/0.000000/8.000000/8.000000:s/0/8.000000/0.000000/16.000000/8.000000:u/0/8.000000/8.000000/16.000000/16.000000:R/180/270/0 +[1.19-]modellist:id=%mud_brick_stairs,state=facing:north/half:top/shape:outer_right,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/0/0.000000/0.000000/16.000000/16.000000:R/180/0/0,box=8.000000/8.000000/8.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/8.000000/8.000000:w/0/8.000000/0.000000/16.000000/8.000000:e/0/0.000000/0.000000/8.000000/8.000000:s/0/8.000000/0.000000/16.000000/8.000000:u/0/8.000000/8.000000/16.000000/16.000000:R/180/0/0 +[1.19-]modellist:id=%mud_brick_stairs,state=facing:north/half:bottom/shape:straight,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/0/0.000000/0.000000/16.000000/16.000000:R/0/270/0,box=8.000000/8.000000/0.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/8.000000/8.000000:w/0/0.000000/0.000000/16.000000/8.000000:e/0/0.000000/0.000000/16.000000/8.000000:s/0/8.000000/0.000000/16.000000/8.000000:u/0/8.000000/0.000000/16.000000/16.000000:R/0/270/0 +[1.19-]modellist:id=%mud_brick_stairs,state=facing:north/half:bottom/shape:inner_left,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/0/0.000000/0.000000/16.000000/16.000000:R/0/180/0,box=8.000000/8.000000/0.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/8.000000/8.000000:w/0/0.000000/0.000000/16.000000/8.000000:e/0/0.000000/0.000000/16.000000/8.000000:s/0/8.000000/0.000000/16.000000/8.000000:u/0/8.000000/0.000000/16.000000/16.000000:R/0/180/0,box=0.000000/8.000000/8.000000:8.000000/16.000000/16.000000:n/0/8.000000/0.000000/16.000000/8.000000:w/0/8.000000/0.000000/16.000000/8.000000:s/0/0.000000/0.000000/8.000000/8.000000:u/0/0.000000/8.000000/8.000000/16.000000:R/0/180/0 +[1.19-]modellist:id=%mud_brick_stairs,state=facing:north/half:bottom/shape:inner_right,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/0/0.000000/0.000000/16.000000/16.000000:R/0/270/0,box=8.000000/8.000000/0.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/8.000000/8.000000:w/0/0.000000/0.000000/16.000000/8.000000:e/0/0.000000/0.000000/16.000000/8.000000:s/0/8.000000/0.000000/16.000000/8.000000:u/0/8.000000/0.000000/16.000000/16.000000:R/0/270/0,box=0.000000/8.000000/8.000000:8.000000/16.000000/16.000000:n/0/8.000000/0.000000/16.000000/8.000000:w/0/8.000000/0.000000/16.000000/8.000000:s/0/0.000000/0.000000/8.000000/8.000000:u/0/0.000000/8.000000/8.000000/16.000000:R/0/270/0 +[1.19-]modellist:id=%mud_brick_stairs,state=facing:north/half:bottom/shape:outer_left,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/0/0.000000/0.000000/16.000000/16.000000:R/0/180/0,box=8.000000/8.000000/8.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/8.000000/8.000000:w/0/8.000000/0.000000/16.000000/8.000000:e/0/0.000000/0.000000/8.000000/8.000000:s/0/8.000000/0.000000/16.000000/8.000000:u/0/8.000000/8.000000/16.000000/16.000000:R/0/180/0 +[1.19-]modellist:id=%mud_brick_stairs,state=facing:north/half:bottom/shape:outer_right,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/0/0.000000/0.000000/16.000000/16.000000:R/0/270/0,box=8.000000/8.000000/8.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/8.000000/8.000000:w/0/8.000000/0.000000/16.000000/8.000000:e/0/0.000000/0.000000/8.000000/8.000000:s/0/8.000000/0.000000/16.000000/8.000000:u/0/8.000000/8.000000/16.000000/16.000000:R/0/270/0 +[1.19-]modellist:id=%mud_brick_stairs,state=facing:south/half:top/shape:straight,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/0/0.000000/0.000000/16.000000/16.000000:R/180/90/0,box=8.000000/8.000000/0.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/8.000000/8.000000:w/0/0.000000/0.000000/16.000000/8.000000:e/0/0.000000/0.000000/16.000000/8.000000:s/0/8.000000/0.000000/16.000000/8.000000:u/0/8.000000/0.000000/16.000000/16.000000:R/180/90/0 +[1.19-]modellist:id=%mud_brick_stairs,state=facing:south/half:top/shape:inner_left,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/0/0.000000/0.000000/16.000000/16.000000:R/180/90/0,box=8.000000/8.000000/0.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/8.000000/8.000000:w/0/0.000000/0.000000/16.000000/8.000000:e/0/0.000000/0.000000/16.000000/8.000000:s/0/8.000000/0.000000/16.000000/8.000000:u/0/8.000000/0.000000/16.000000/16.000000:R/180/90/0,box=0.000000/8.000000/8.000000:8.000000/16.000000/16.000000:n/0/8.000000/0.000000/16.000000/8.000000:w/0/8.000000/0.000000/16.000000/8.000000:s/0/0.000000/0.000000/8.000000/8.000000:u/0/0.000000/8.000000/8.000000/16.000000:R/180/90/0 +[1.19-]modellist:id=%mud_brick_stairs,state=facing:south/half:top/shape:inner_right,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/0/0.000000/0.000000/16.000000/16.000000:R/180/180/0,box=8.000000/8.000000/0.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/8.000000/8.000000:w/0/0.000000/0.000000/16.000000/8.000000:e/0/0.000000/0.000000/16.000000/8.000000:s/0/8.000000/0.000000/16.000000/8.000000:u/0/8.000000/0.000000/16.000000/16.000000:R/180/180/0,box=0.000000/8.000000/8.000000:8.000000/16.000000/16.000000:n/0/8.000000/0.000000/16.000000/8.000000:w/0/8.000000/0.000000/16.000000/8.000000:s/0/0.000000/0.000000/8.000000/8.000000:u/0/0.000000/8.000000/8.000000/16.000000:R/180/180/0 +[1.19-]modellist:id=%mud_brick_stairs,state=facing:south/half:top/shape:outer_left,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/0/0.000000/0.000000/16.000000/16.000000:R/180/90/0,box=8.000000/8.000000/8.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/8.000000/8.000000:w/0/8.000000/0.000000/16.000000/8.000000:e/0/0.000000/0.000000/8.000000/8.000000:s/0/8.000000/0.000000/16.000000/8.000000:u/0/8.000000/8.000000/16.000000/16.000000:R/180/90/0 +[1.19-]modellist:id=%mud_brick_stairs,state=facing:south/half:top/shape:outer_right,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/0/0.000000/0.000000/16.000000/16.000000:R/180/180/0,box=8.000000/8.000000/8.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/8.000000/8.000000:w/0/8.000000/0.000000/16.000000/8.000000:e/0/0.000000/0.000000/8.000000/8.000000:s/0/8.000000/0.000000/16.000000/8.000000:u/0/8.000000/8.000000/16.000000/16.000000:R/180/180/0 +[1.19-]modellist:id=%mud_brick_stairs,state=facing:south/half:bottom/shape:straight,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/0/0.000000/0.000000/16.000000/16.000000:R/0/90/0,box=8.000000/8.000000/0.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/8.000000/8.000000:w/0/0.000000/0.000000/16.000000/8.000000:e/0/0.000000/0.000000/16.000000/8.000000:s/0/8.000000/0.000000/16.000000/8.000000:u/0/8.000000/0.000000/16.000000/16.000000:R/0/90/0 +[1.19-]modellist:id=%mud_brick_stairs,state=facing:south/half:bottom/shape:inner_left,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/0/0.000000/0.000000/16.000000/16.000000,box=8.000000/8.000000/0.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/8.000000/8.000000:w/0/0.000000/0.000000/16.000000/8.000000:e/0/0.000000/0.000000/16.000000/8.000000:s/0/8.000000/0.000000/16.000000/8.000000:u/0/8.000000/0.000000/16.000000/16.000000,box=0.000000/8.000000/8.000000:8.000000/16.000000/16.000000:n/0/8.000000/0.000000/16.000000/8.000000:w/0/8.000000/0.000000/16.000000/8.000000:s/0/0.000000/0.000000/8.000000/8.000000:u/0/0.000000/8.000000/8.000000/16.000000 +[1.19-]modellist:id=%mud_brick_stairs,state=facing:south/half:bottom/shape:inner_right,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/0/0.000000/0.000000/16.000000/16.000000:R/0/90/0,box=8.000000/8.000000/0.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/8.000000/8.000000:w/0/0.000000/0.000000/16.000000/8.000000:e/0/0.000000/0.000000/16.000000/8.000000:s/0/8.000000/0.000000/16.000000/8.000000:u/0/8.000000/0.000000/16.000000/16.000000:R/0/90/0,box=0.000000/8.000000/8.000000:8.000000/16.000000/16.000000:n/0/8.000000/0.000000/16.000000/8.000000:w/0/8.000000/0.000000/16.000000/8.000000:s/0/0.000000/0.000000/8.000000/8.000000:u/0/0.000000/8.000000/8.000000/16.000000:R/0/90/0 +[1.19-]modellist:id=%mud_brick_stairs,state=facing:south/half:bottom/shape:outer_left,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/0/0.000000/0.000000/16.000000/16.000000,box=8.000000/8.000000/8.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/8.000000/8.000000:w/0/8.000000/0.000000/16.000000/8.000000:e/0/0.000000/0.000000/8.000000/8.000000:s/0/8.000000/0.000000/16.000000/8.000000:u/0/8.000000/8.000000/16.000000/16.000000 +[1.19-]modellist:id=%mud_brick_stairs,state=facing:south/half:bottom/shape:outer_right,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/0/0.000000/0.000000/16.000000/16.000000:R/0/90/0,box=8.000000/8.000000/8.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/8.000000/8.000000:w/0/8.000000/0.000000/16.000000/8.000000:e/0/0.000000/0.000000/8.000000/8.000000:s/0/8.000000/0.000000/16.000000/8.000000:u/0/8.000000/8.000000/16.000000/16.000000:R/0/90/0 +[1.19-]modellist:id=%mud_brick_stairs,state=facing:west/half:top/shape:straight,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/0/0.000000/0.000000/16.000000/16.000000:R/180/180/0,box=8.000000/8.000000/0.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/8.000000/8.000000:w/0/0.000000/0.000000/16.000000/8.000000:e/0/0.000000/0.000000/16.000000/8.000000:s/0/8.000000/0.000000/16.000000/8.000000:u/0/8.000000/0.000000/16.000000/16.000000:R/180/180/0 +[1.19-]modellist:id=%mud_brick_stairs,state=facing:west/half:top/shape:inner_left,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/0/0.000000/0.000000/16.000000/16.000000:R/180/180/0,box=8.000000/8.000000/0.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/8.000000/8.000000:w/0/0.000000/0.000000/16.000000/8.000000:e/0/0.000000/0.000000/16.000000/8.000000:s/0/8.000000/0.000000/16.000000/8.000000:u/0/8.000000/0.000000/16.000000/16.000000:R/180/180/0,box=0.000000/8.000000/8.000000:8.000000/16.000000/16.000000:n/0/8.000000/0.000000/16.000000/8.000000:w/0/8.000000/0.000000/16.000000/8.000000:s/0/0.000000/0.000000/8.000000/8.000000:u/0/0.000000/8.000000/8.000000/16.000000:R/180/180/0 +[1.19-]modellist:id=%mud_brick_stairs,state=facing:west/half:top/shape:inner_right,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/0/0.000000/0.000000/16.000000/16.000000:R/180/270/0,box=8.000000/8.000000/0.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/8.000000/8.000000:w/0/0.000000/0.000000/16.000000/8.000000:e/0/0.000000/0.000000/16.000000/8.000000:s/0/8.000000/0.000000/16.000000/8.000000:u/0/8.000000/0.000000/16.000000/16.000000:R/180/270/0,box=0.000000/8.000000/8.000000:8.000000/16.000000/16.000000:n/0/8.000000/0.000000/16.000000/8.000000:w/0/8.000000/0.000000/16.000000/8.000000:s/0/0.000000/0.000000/8.000000/8.000000:u/0/0.000000/8.000000/8.000000/16.000000:R/180/270/0 +[1.19-]modellist:id=%mud_brick_stairs,state=facing:west/half:top/shape:outer_left,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/0/0.000000/0.000000/16.000000/16.000000:R/180/180/0,box=8.000000/8.000000/8.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/8.000000/8.000000:w/0/8.000000/0.000000/16.000000/8.000000:e/0/0.000000/0.000000/8.000000/8.000000:s/0/8.000000/0.000000/16.000000/8.000000:u/0/8.000000/8.000000/16.000000/16.000000:R/180/180/0 +[1.19-]modellist:id=%mud_brick_stairs,state=facing:west/half:top/shape:outer_right,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/0/0.000000/0.000000/16.000000/16.000000:R/180/270/0,box=8.000000/8.000000/8.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/8.000000/8.000000:w/0/8.000000/0.000000/16.000000/8.000000:e/0/0.000000/0.000000/8.000000/8.000000:s/0/8.000000/0.000000/16.000000/8.000000:u/0/8.000000/8.000000/16.000000/16.000000:R/180/270/0 +[1.19-]modellist:id=%mud_brick_stairs,state=facing:west/half:bottom/shape:straight,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/0/0.000000/0.000000/16.000000/16.000000:R/0/180/0,box=8.000000/8.000000/0.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/8.000000/8.000000:w/0/0.000000/0.000000/16.000000/8.000000:e/0/0.000000/0.000000/16.000000/8.000000:s/0/8.000000/0.000000/16.000000/8.000000:u/0/8.000000/0.000000/16.000000/16.000000:R/0/180/0 +[1.19-]modellist:id=%mud_brick_stairs,state=facing:west/half:bottom/shape:inner_left,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/0/0.000000/0.000000/16.000000/16.000000:R/0/90/0,box=8.000000/8.000000/0.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/8.000000/8.000000:w/0/0.000000/0.000000/16.000000/8.000000:e/0/0.000000/0.000000/16.000000/8.000000:s/0/8.000000/0.000000/16.000000/8.000000:u/0/8.000000/0.000000/16.000000/16.000000:R/0/90/0,box=0.000000/8.000000/8.000000:8.000000/16.000000/16.000000:n/0/8.000000/0.000000/16.000000/8.000000:w/0/8.000000/0.000000/16.000000/8.000000:s/0/0.000000/0.000000/8.000000/8.000000:u/0/0.000000/8.000000/8.000000/16.000000:R/0/90/0 +[1.19-]modellist:id=%mud_brick_stairs,state=facing:west/half:bottom/shape:inner_right,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/0/0.000000/0.000000/16.000000/16.000000:R/0/180/0,box=8.000000/8.000000/0.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/8.000000/8.000000:w/0/0.000000/0.000000/16.000000/8.000000:e/0/0.000000/0.000000/16.000000/8.000000:s/0/8.000000/0.000000/16.000000/8.000000:u/0/8.000000/0.000000/16.000000/16.000000:R/0/180/0,box=0.000000/8.000000/8.000000:8.000000/16.000000/16.000000:n/0/8.000000/0.000000/16.000000/8.000000:w/0/8.000000/0.000000/16.000000/8.000000:s/0/0.000000/0.000000/8.000000/8.000000:u/0/0.000000/8.000000/8.000000/16.000000:R/0/180/0 +[1.19-]modellist:id=%mud_brick_stairs,state=facing:west/half:bottom/shape:outer_left,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/0/0.000000/0.000000/16.000000/16.000000:R/0/90/0,box=8.000000/8.000000/8.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/8.000000/8.000000:w/0/8.000000/0.000000/16.000000/8.000000:e/0/0.000000/0.000000/8.000000/8.000000:s/0/8.000000/0.000000/16.000000/8.000000:u/0/8.000000/8.000000/16.000000/16.000000:R/0/90/0 +[1.19-]modellist:id=%mud_brick_stairs,state=facing:west/half:bottom/shape:outer_right,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/0/0.000000/0.000000/16.000000/16.000000:R/0/180/0,box=8.000000/8.000000/8.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/8.000000/8.000000:w/0/8.000000/0.000000/16.000000/8.000000:e/0/0.000000/0.000000/8.000000/8.000000:s/0/8.000000/0.000000/16.000000/8.000000:u/0/8.000000/8.000000/16.000000/16.000000:R/0/180/0 +[1.19-]modellist:id=%mud_brick_stairs,state=facing:east/half:top/shape:straight,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/0/0.000000/0.000000/16.000000/16.000000:R/180/0/0,box=8.000000/8.000000/0.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/8.000000/8.000000:w/0/0.000000/0.000000/16.000000/8.000000:e/0/0.000000/0.000000/16.000000/8.000000:s/0/8.000000/0.000000/16.000000/8.000000:u/0/8.000000/0.000000/16.000000/16.000000:R/180/0/0 +[1.19-]modellist:id=%mud_brick_stairs,state=facing:east/half:top/shape:inner_left,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/0/0.000000/0.000000/16.000000/16.000000:R/180/0/0,box=8.000000/8.000000/0.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/8.000000/8.000000:w/0/0.000000/0.000000/16.000000/8.000000:e/0/0.000000/0.000000/16.000000/8.000000:s/0/8.000000/0.000000/16.000000/8.000000:u/0/8.000000/0.000000/16.000000/16.000000:R/180/0/0,box=0.000000/8.000000/8.000000:8.000000/16.000000/16.000000:n/0/8.000000/0.000000/16.000000/8.000000:w/0/8.000000/0.000000/16.000000/8.000000:s/0/0.000000/0.000000/8.000000/8.000000:u/0/0.000000/8.000000/8.000000/16.000000:R/180/0/0 +[1.19-]modellist:id=%mud_brick_stairs,state=facing:east/half:top/shape:inner_right,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/0/0.000000/0.000000/16.000000/16.000000:R/180/90/0,box=8.000000/8.000000/0.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/8.000000/8.000000:w/0/0.000000/0.000000/16.000000/8.000000:e/0/0.000000/0.000000/16.000000/8.000000:s/0/8.000000/0.000000/16.000000/8.000000:u/0/8.000000/0.000000/16.000000/16.000000:R/180/90/0,box=0.000000/8.000000/8.000000:8.000000/16.000000/16.000000:n/0/8.000000/0.000000/16.000000/8.000000:w/0/8.000000/0.000000/16.000000/8.000000:s/0/0.000000/0.000000/8.000000/8.000000:u/0/0.000000/8.000000/8.000000/16.000000:R/180/90/0 +[1.19-]modellist:id=%mud_brick_stairs,state=facing:east/half:top/shape:outer_left,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/0/0.000000/0.000000/16.000000/16.000000:R/180/0/0,box=8.000000/8.000000/8.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/8.000000/8.000000:w/0/8.000000/0.000000/16.000000/8.000000:e/0/0.000000/0.000000/8.000000/8.000000:s/0/8.000000/0.000000/16.000000/8.000000:u/0/8.000000/8.000000/16.000000/16.000000:R/180/0/0 +[1.19-]modellist:id=%mud_brick_stairs,state=facing:east/half:top/shape:outer_right,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/0/0.000000/0.000000/16.000000/16.000000:R/180/90/0,box=8.000000/8.000000/8.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/8.000000/8.000000:w/0/8.000000/0.000000/16.000000/8.000000:e/0/0.000000/0.000000/8.000000/8.000000:s/0/8.000000/0.000000/16.000000/8.000000:u/0/8.000000/8.000000/16.000000/16.000000:R/180/90/0 +[1.19-]modellist:id=%mud_brick_stairs,state=facing:east/half:bottom/shape:straight,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/0/0.000000/0.000000/16.000000/16.000000,box=8.000000/8.000000/0.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/8.000000/8.000000:w/0/0.000000/0.000000/16.000000/8.000000:e/0/0.000000/0.000000/16.000000/8.000000:s/0/8.000000/0.000000/16.000000/8.000000:u/0/8.000000/0.000000/16.000000/16.000000 +[1.19-]modellist:id=%mud_brick_stairs,state=facing:east/half:bottom/shape:inner_left,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/0/0.000000/0.000000/16.000000/16.000000:R/0/270/0,box=8.000000/8.000000/0.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/8.000000/8.000000:w/0/0.000000/0.000000/16.000000/8.000000:e/0/0.000000/0.000000/16.000000/8.000000:s/0/8.000000/0.000000/16.000000/8.000000:u/0/8.000000/0.000000/16.000000/16.000000:R/0/270/0,box=0.000000/8.000000/8.000000:8.000000/16.000000/16.000000:n/0/8.000000/0.000000/16.000000/8.000000:w/0/8.000000/0.000000/16.000000/8.000000:s/0/0.000000/0.000000/8.000000/8.000000:u/0/0.000000/8.000000/8.000000/16.000000:R/0/270/0 +[1.19-]modellist:id=%mud_brick_stairs,state=facing:east/half:bottom/shape:inner_right,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/0/0.000000/0.000000/16.000000/16.000000,box=8.000000/8.000000/0.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/8.000000/8.000000:w/0/0.000000/0.000000/16.000000/8.000000:e/0/0.000000/0.000000/16.000000/8.000000:s/0/8.000000/0.000000/16.000000/8.000000:u/0/8.000000/0.000000/16.000000/16.000000,box=0.000000/8.000000/8.000000:8.000000/16.000000/16.000000:n/0/8.000000/0.000000/16.000000/8.000000:w/0/8.000000/0.000000/16.000000/8.000000:s/0/0.000000/0.000000/8.000000/8.000000:u/0/0.000000/8.000000/8.000000/16.000000 +[1.19-]modellist:id=%mud_brick_stairs,state=facing:east/half:bottom/shape:outer_left,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/0/0.000000/0.000000/16.000000/16.000000:R/0/270/0,box=8.000000/8.000000/8.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/8.000000/8.000000:w/0/8.000000/0.000000/16.000000/8.000000:e/0/0.000000/0.000000/8.000000/8.000000:s/0/8.000000/0.000000/16.000000/8.000000:u/0/8.000000/8.000000/16.000000/16.000000:R/0/270/0 +[1.19-]modellist:id=%mud_brick_stairs,state=facing:east/half:bottom/shape:outer_right,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/0/0.000000/0.000000/16.000000/16.000000,box=8.000000/8.000000/8.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/8.000000/8.000000:w/0/8.000000/0.000000/16.000000/8.000000:e/0/0.000000/0.000000/8.000000/8.000000:s/0/8.000000/0.000000/16.000000/8.000000:u/0/8.000000/8.000000/16.000000/16.000000 +[1.19-]modellist:id=%mud_brick_slab,state=type:top,box=0.000000/8.000000/0.000000:16.000000/16.000000/16.000000:n/0/0.000000/0.000000/16.000000/8.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/0.000000/16.000000/8.000000:e/0/0.000000/0.000000/16.000000/8.000000:s/0/0.000000/0.000000/16.000000/8.000000:u/0/0.000000/0.000000/16.000000/16.000000 +[1.19-]modellist:id=%mud_brick_slab,state=type:bottom,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/0/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/0/0.000000/0.000000/16.000000/16.000000 +[1.19-]modellist:id=%mud_brick_wall,state=west:none/east:none/up:true/south:none/north:none,box=4.000000/0.000000/4.000000:12.000000/16.000000/12.000000:n/0:d/0:w/0:e/0:s/0:u/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:low/east:none/up:true/south:none/north:none,box=4.000000/0.000000/4.000000:12.000000/16.000000/12.000000:n/0:d/0:w/0:e/0:s/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:tall/east:none/up:true/south:none/north:none,box=4.000000/0.000000/4.000000:12.000000/16.000000/12.000000:n/0:d/0:w/0:e/0:s/0:u/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:none/east:none/up:false/south:none/north:none +[1.19-]modellist:id=%mud_brick_wall,state=west:low/east:none/up:false/south:none/north:none,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:tall/east:none/up:false/south:none/north:none,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:none/east:none/up:true/south:low/north:none,box=4.000000/0.000000/4.000000:12.000000/16.000000/12.000000:n/0:d/0:w/0:e/0:s/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:low/east:none/up:true/south:low/north:none,box=4.000000/0.000000/4.000000:12.000000/16.000000/12.000000:n/0:d/0:w/0:e/0:s/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:tall/east:none/up:true/south:low/north:none,box=4.000000/0.000000/4.000000:12.000000/16.000000/12.000000:n/0:d/0:w/0:e/0:s/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:none/east:none/up:false/south:low/north:none,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:low/east:none/up:false/south:low/north:none,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:tall/east:none/up:false/south:low/north:none,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:none/east:none/up:true/south:tall/north:none,box=4.000000/0.000000/4.000000:12.000000/16.000000/12.000000:n/0:d/0:w/0:e/0:s/0:u/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:low/east:none/up:true/south:tall/north:none,box=4.000000/0.000000/4.000000:12.000000/16.000000/12.000000:n/0:d/0:w/0:e/0:s/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:tall/east:none/up:true/south:tall/north:none,box=4.000000/0.000000/4.000000:12.000000/16.000000/12.000000:n/0:d/0:w/0:e/0:s/0:u/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:none/east:none/up:false/south:tall/north:none,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:low/east:none/up:false/south:tall/north:none,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:tall/east:none/up:false/south:tall/north:none,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:none/east:none/up:true/south:none/north:low,box=4.000000/0.000000/4.000000:12.000000/16.000000/12.000000:n/0:d/0:w/0:e/0:s/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:low/east:none/up:true/south:none/north:low,box=4.000000/0.000000/4.000000:12.000000/16.000000/12.000000:n/0:d/0:w/0:e/0:s/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:tall/east:none/up:true/south:none/north:low,box=4.000000/0.000000/4.000000:12.000000/16.000000/12.000000:n/0:d/0:w/0:e/0:s/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:none/east:none/up:false/south:none/north:low,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:low/east:none/up:false/south:none/north:low,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:tall/east:none/up:false/south:none/north:low,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:none/east:none/up:true/south:low/north:low,box=4.000000/0.000000/4.000000:12.000000/16.000000/12.000000:n/0:d/0:w/0:e/0:s/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:low/east:none/up:true/south:low/north:low,box=4.000000/0.000000/4.000000:12.000000/16.000000/12.000000:n/0:d/0:w/0:e/0:s/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:tall/east:none/up:true/south:low/north:low,box=4.000000/0.000000/4.000000:12.000000/16.000000/12.000000:n/0:d/0:w/0:e/0:s/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:none/east:none/up:false/south:low/north:low,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:low/east:none/up:false/south:low/north:low,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:tall/east:none/up:false/south:low/north:low,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:none/east:none/up:true/south:tall/north:low,box=4.000000/0.000000/4.000000:12.000000/16.000000/12.000000:n/0:d/0:w/0:e/0:s/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:low/east:none/up:true/south:tall/north:low,box=4.000000/0.000000/4.000000:12.000000/16.000000/12.000000:n/0:d/0:w/0:e/0:s/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:tall/east:none/up:true/south:tall/north:low,box=4.000000/0.000000/4.000000:12.000000/16.000000/12.000000:n/0:d/0:w/0:e/0:s/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:none/east:none/up:false/south:tall/north:low,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:low/east:none/up:false/south:tall/north:low,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:tall/east:none/up:false/south:tall/north:low,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:none/east:none/up:true/south:none/north:tall,box=4.000000/0.000000/4.000000:12.000000/16.000000/12.000000:n/0:d/0:w/0:e/0:s/0:u/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:low/east:none/up:true/south:none/north:tall,box=4.000000/0.000000/4.000000:12.000000/16.000000/12.000000:n/0:d/0:w/0:e/0:s/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:tall/east:none/up:true/south:none/north:tall,box=4.000000/0.000000/4.000000:12.000000/16.000000/12.000000:n/0:d/0:w/0:e/0:s/0:u/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:none/east:none/up:false/south:none/north:tall,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:low/east:none/up:false/south:none/north:tall,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:tall/east:none/up:false/south:none/north:tall,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:none/east:none/up:true/south:low/north:tall,box=4.000000/0.000000/4.000000:12.000000/16.000000/12.000000:n/0:d/0:w/0:e/0:s/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:low/east:none/up:true/south:low/north:tall,box=4.000000/0.000000/4.000000:12.000000/16.000000/12.000000:n/0:d/0:w/0:e/0:s/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:tall/east:none/up:true/south:low/north:tall,box=4.000000/0.000000/4.000000:12.000000/16.000000/12.000000:n/0:d/0:w/0:e/0:s/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:none/east:none/up:false/south:low/north:tall,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:low/east:none/up:false/south:low/north:tall,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:tall/east:none/up:false/south:low/north:tall,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:none/east:none/up:true/south:tall/north:tall,box=4.000000/0.000000/4.000000:12.000000/16.000000/12.000000:n/0:d/0:w/0:e/0:s/0:u/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:low/east:none/up:true/south:tall/north:tall,box=4.000000/0.000000/4.000000:12.000000/16.000000/12.000000:n/0:d/0:w/0:e/0:s/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:tall/east:none/up:true/south:tall/north:tall,box=4.000000/0.000000/4.000000:12.000000/16.000000/12.000000:n/0:d/0:w/0:e/0:s/0:u/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:none/east:none/up:false/south:tall/north:tall,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:low/east:none/up:false/south:tall/north:tall,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:tall/east:none/up:false/south:tall/north:tall,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:none/east:low/up:true/south:none/north:none,box=4.000000/0.000000/4.000000:12.000000/16.000000/12.000000:n/0:d/0:w/0:e/0:s/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:low/east:low/up:true/south:none/north:none,box=4.000000/0.000000/4.000000:12.000000/16.000000/12.000000:n/0:d/0:w/0:e/0:s/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:tall/east:low/up:true/south:none/north:none,box=4.000000/0.000000/4.000000:12.000000/16.000000/12.000000:n/0:d/0:w/0:e/0:s/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:none/east:low/up:false/south:none/north:none,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:low/east:low/up:false/south:none/north:none,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:tall/east:low/up:false/south:none/north:none,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:none/east:low/up:true/south:low/north:none,box=4.000000/0.000000/4.000000:12.000000/16.000000/12.000000:n/0:d/0:w/0:e/0:s/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:low/east:low/up:true/south:low/north:none,box=4.000000/0.000000/4.000000:12.000000/16.000000/12.000000:n/0:d/0:w/0:e/0:s/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:tall/east:low/up:true/south:low/north:none,box=4.000000/0.000000/4.000000:12.000000/16.000000/12.000000:n/0:d/0:w/0:e/0:s/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:none/east:low/up:false/south:low/north:none,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:low/east:low/up:false/south:low/north:none,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:tall/east:low/up:false/south:low/north:none,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:none/east:low/up:true/south:tall/north:none,box=4.000000/0.000000/4.000000:12.000000/16.000000/12.000000:n/0:d/0:w/0:e/0:s/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:low/east:low/up:true/south:tall/north:none,box=4.000000/0.000000/4.000000:12.000000/16.000000/12.000000:n/0:d/0:w/0:e/0:s/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:tall/east:low/up:true/south:tall/north:none,box=4.000000/0.000000/4.000000:12.000000/16.000000/12.000000:n/0:d/0:w/0:e/0:s/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:none/east:low/up:false/south:tall/north:none,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:low/east:low/up:false/south:tall/north:none,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:tall/east:low/up:false/south:tall/north:none,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:none/east:low/up:true/south:none/north:low,box=4.000000/0.000000/4.000000:12.000000/16.000000/12.000000:n/0:d/0:w/0:e/0:s/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:low/east:low/up:true/south:none/north:low,box=4.000000/0.000000/4.000000:12.000000/16.000000/12.000000:n/0:d/0:w/0:e/0:s/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:tall/east:low/up:true/south:none/north:low,box=4.000000/0.000000/4.000000:12.000000/16.000000/12.000000:n/0:d/0:w/0:e/0:s/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:none/east:low/up:false/south:none/north:low,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:low/east:low/up:false/south:none/north:low,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:tall/east:low/up:false/south:none/north:low,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:none/east:low/up:true/south:low/north:low,box=4.000000/0.000000/4.000000:12.000000/16.000000/12.000000:n/0:d/0:w/0:e/0:s/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:low/east:low/up:true/south:low/north:low,box=4.000000/0.000000/4.000000:12.000000/16.000000/12.000000:n/0:d/0:w/0:e/0:s/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:tall/east:low/up:true/south:low/north:low,box=4.000000/0.000000/4.000000:12.000000/16.000000/12.000000:n/0:d/0:w/0:e/0:s/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:none/east:low/up:false/south:low/north:low,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:low/east:low/up:false/south:low/north:low,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:tall/east:low/up:false/south:low/north:low,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:none/east:low/up:true/south:tall/north:low,box=4.000000/0.000000/4.000000:12.000000/16.000000/12.000000:n/0:d/0:w/0:e/0:s/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:low/east:low/up:true/south:tall/north:low,box=4.000000/0.000000/4.000000:12.000000/16.000000/12.000000:n/0:d/0:w/0:e/0:s/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:tall/east:low/up:true/south:tall/north:low,box=4.000000/0.000000/4.000000:12.000000/16.000000/12.000000:n/0:d/0:w/0:e/0:s/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:none/east:low/up:false/south:tall/north:low,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:low/east:low/up:false/south:tall/north:low,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:tall/east:low/up:false/south:tall/north:low,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:none/east:low/up:true/south:none/north:tall,box=4.000000/0.000000/4.000000:12.000000/16.000000/12.000000:n/0:d/0:w/0:e/0:s/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:low/east:low/up:true/south:none/north:tall,box=4.000000/0.000000/4.000000:12.000000/16.000000/12.000000:n/0:d/0:w/0:e/0:s/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:tall/east:low/up:true/south:none/north:tall,box=4.000000/0.000000/4.000000:12.000000/16.000000/12.000000:n/0:d/0:w/0:e/0:s/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:none/east:low/up:false/south:none/north:tall,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:low/east:low/up:false/south:none/north:tall,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:tall/east:low/up:false/south:none/north:tall,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:none/east:low/up:true/south:low/north:tall,box=4.000000/0.000000/4.000000:12.000000/16.000000/12.000000:n/0:d/0:w/0:e/0:s/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:low/east:low/up:true/south:low/north:tall,box=4.000000/0.000000/4.000000:12.000000/16.000000/12.000000:n/0:d/0:w/0:e/0:s/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:tall/east:low/up:true/south:low/north:tall,box=4.000000/0.000000/4.000000:12.000000/16.000000/12.000000:n/0:d/0:w/0:e/0:s/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:none/east:low/up:false/south:low/north:tall,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:low/east:low/up:false/south:low/north:tall,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:tall/east:low/up:false/south:low/north:tall,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:none/east:low/up:true/south:tall/north:tall,box=4.000000/0.000000/4.000000:12.000000/16.000000/12.000000:n/0:d/0:w/0:e/0:s/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:low/east:low/up:true/south:tall/north:tall,box=4.000000/0.000000/4.000000:12.000000/16.000000/12.000000:n/0:d/0:w/0:e/0:s/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:tall/east:low/up:true/south:tall/north:tall,box=4.000000/0.000000/4.000000:12.000000/16.000000/12.000000:n/0:d/0:w/0:e/0:s/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:none/east:low/up:false/south:tall/north:tall,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:low/east:low/up:false/south:tall/north:tall,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:tall/east:low/up:false/south:tall/north:tall,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:none/east:tall/up:true/south:none/north:none,box=4.000000/0.000000/4.000000:12.000000/16.000000/12.000000:n/0:d/0:w/0:e/0:s/0:u/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:low/east:tall/up:true/south:none/north:none,box=4.000000/0.000000/4.000000:12.000000/16.000000/12.000000:n/0:d/0:w/0:e/0:s/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:tall/east:tall/up:true/south:none/north:none,box=4.000000/0.000000/4.000000:12.000000/16.000000/12.000000:n/0:d/0:w/0:e/0:s/0:u/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:none/east:tall/up:false/south:none/north:none,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:low/east:tall/up:false/south:none/north:none,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:tall/east:tall/up:false/south:none/north:none,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:none/east:tall/up:true/south:low/north:none,box=4.000000/0.000000/4.000000:12.000000/16.000000/12.000000:n/0:d/0:w/0:e/0:s/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:low/east:tall/up:true/south:low/north:none,box=4.000000/0.000000/4.000000:12.000000/16.000000/12.000000:n/0:d/0:w/0:e/0:s/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:tall/east:tall/up:true/south:low/north:none,box=4.000000/0.000000/4.000000:12.000000/16.000000/12.000000:n/0:d/0:w/0:e/0:s/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:none/east:tall/up:false/south:low/north:none,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:low/east:tall/up:false/south:low/north:none,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:tall/east:tall/up:false/south:low/north:none,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:none/east:tall/up:true/south:tall/north:none,box=4.000000/0.000000/4.000000:12.000000/16.000000/12.000000:n/0:d/0:w/0:e/0:s/0:u/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:low/east:tall/up:true/south:tall/north:none,box=4.000000/0.000000/4.000000:12.000000/16.000000/12.000000:n/0:d/0:w/0:e/0:s/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:tall/east:tall/up:true/south:tall/north:none,box=4.000000/0.000000/4.000000:12.000000/16.000000/12.000000:n/0:d/0:w/0:e/0:s/0:u/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:none/east:tall/up:false/south:tall/north:none,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:low/east:tall/up:false/south:tall/north:none,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:tall/east:tall/up:false/south:tall/north:none,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:none/east:tall/up:true/south:none/north:low,box=4.000000/0.000000/4.000000:12.000000/16.000000/12.000000:n/0:d/0:w/0:e/0:s/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:low/east:tall/up:true/south:none/north:low,box=4.000000/0.000000/4.000000:12.000000/16.000000/12.000000:n/0:d/0:w/0:e/0:s/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:tall/east:tall/up:true/south:none/north:low,box=4.000000/0.000000/4.000000:12.000000/16.000000/12.000000:n/0:d/0:w/0:e/0:s/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:none/east:tall/up:false/south:none/north:low,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:low/east:tall/up:false/south:none/north:low,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:tall/east:tall/up:false/south:none/north:low,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:none/east:tall/up:true/south:low/north:low,box=4.000000/0.000000/4.000000:12.000000/16.000000/12.000000:n/0:d/0:w/0:e/0:s/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:low/east:tall/up:true/south:low/north:low,box=4.000000/0.000000/4.000000:12.000000/16.000000/12.000000:n/0:d/0:w/0:e/0:s/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:tall/east:tall/up:true/south:low/north:low,box=4.000000/0.000000/4.000000:12.000000/16.000000/12.000000:n/0:d/0:w/0:e/0:s/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:none/east:tall/up:false/south:low/north:low,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:low/east:tall/up:false/south:low/north:low,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:tall/east:tall/up:false/south:low/north:low,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:none/east:tall/up:true/south:tall/north:low,box=4.000000/0.000000/4.000000:12.000000/16.000000/12.000000:n/0:d/0:w/0:e/0:s/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:low/east:tall/up:true/south:tall/north:low,box=4.000000/0.000000/4.000000:12.000000/16.000000/12.000000:n/0:d/0:w/0:e/0:s/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:tall/east:tall/up:true/south:tall/north:low,box=4.000000/0.000000/4.000000:12.000000/16.000000/12.000000:n/0:d/0:w/0:e/0:s/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:none/east:tall/up:false/south:tall/north:low,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:low/east:tall/up:false/south:tall/north:low,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:tall/east:tall/up:false/south:tall/north:low,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:none/east:tall/up:true/south:none/north:tall,box=4.000000/0.000000/4.000000:12.000000/16.000000/12.000000:n/0:d/0:w/0:e/0:s/0:u/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:low/east:tall/up:true/south:none/north:tall,box=4.000000/0.000000/4.000000:12.000000/16.000000/12.000000:n/0:d/0:w/0:e/0:s/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:tall/east:tall/up:true/south:none/north:tall,box=4.000000/0.000000/4.000000:12.000000/16.000000/12.000000:n/0:d/0:w/0:e/0:s/0:u/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:none/east:tall/up:false/south:none/north:tall,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:low/east:tall/up:false/south:none/north:tall,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:tall/east:tall/up:false/south:none/north:tall,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:none/east:tall/up:true/south:low/north:tall,box=4.000000/0.000000/4.000000:12.000000/16.000000/12.000000:n/0:d/0:w/0:e/0:s/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:low/east:tall/up:true/south:low/north:tall,box=4.000000/0.000000/4.000000:12.000000/16.000000/12.000000:n/0:d/0:w/0:e/0:s/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:tall/east:tall/up:true/south:low/north:tall,box=4.000000/0.000000/4.000000:12.000000/16.000000/12.000000:n/0:d/0:w/0:e/0:s/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:none/east:tall/up:false/south:low/north:tall,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:low/east:tall/up:false/south:low/north:tall,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:tall/east:tall/up:false/south:low/north:tall,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:none/east:tall/up:true/south:tall/north:tall,box=4.000000/0.000000/4.000000:12.000000/16.000000/12.000000:n/0:d/0:w/0:e/0:s/0:u/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:low/east:tall/up:true/south:tall/north:tall,box=4.000000/0.000000/4.000000:12.000000/16.000000/12.000000:n/0:d/0:w/0:e/0:s/0:u/0,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:tall/east:tall/up:true/south:tall/north:tall,box=4.000000/0.000000/4.000000:12.000000/16.000000/12.000000:n/0:d/0:w/0:e/0:s/0:u/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:none/east:tall/up:false/south:tall/north:tall,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:low/east:tall/up:false/south:tall/north:tall,box=5.000000/0.000000/0.000000:11.000000/14.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0 +[1.19-]modellist:id=%mud_brick_wall,state=west:tall/east:tall/up:false/south:tall/north:tall,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/90/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/180/0,box=5.000000/0.000000/0.000000:11.000000/16.000000/8.000000:n/0:d/0:w/0:e/0:u/0:R/0/270/0 +[1.19-]modellist:id=%sculk_vein,state=east:true/south:true/north:true/west:true/up:true/down:true,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/90/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/180/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/270/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/270/0/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/90/0/0 +[1.19-]modellist:id=%sculk_vein,state=east:true/south:true/north:true/west:false/up:true/down:true,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/90/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/180/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/270/0/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/90/0/0 +[1.19-]modellist:id=%sculk_vein,state=east:true/south:true/north:true/west:true/up:false/down:true,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/90/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/180/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/270/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/90/0/0 +[1.19-]modellist:id=%sculk_vein,state=east:true/south:true/north:true/west:false/up:false/down:true,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/90/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/180/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/90/0/0 +[1.19-]modellist:id=%sculk_vein,state=east:true/south:false/north:true/west:true/up:true/down:true,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/90/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/270/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/270/0/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/90/0/0 +[1.19-]modellist:id=%sculk_vein,state=east:true/south:false/north:true/west:false/up:true/down:true,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/90/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/270/0/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/90/0/0 +[1.19-]modellist:id=%sculk_vein,state=east:true/south:false/north:true/west:true/up:false/down:true,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/90/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/270/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/90/0/0 +[1.19-]modellist:id=%sculk_vein,state=east:true/south:false/north:true/west:false/up:false/down:true,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/90/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/90/0/0 +[1.19-]modellist:id=%sculk_vein,state=east:true/south:true/north:false/west:true/up:true/down:true,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/90/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/180/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/270/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/270/0/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/90/0/0 +[1.19-]modellist:id=%sculk_vein,state=east:true/south:true/north:false/west:false/up:true/down:true,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/90/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/180/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/270/0/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/90/0/0 +[1.19-]modellist:id=%sculk_vein,state=east:true/south:true/north:false/west:true/up:false/down:true,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/90/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/180/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/270/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/90/0/0 +[1.19-]modellist:id=%sculk_vein,state=east:true/south:true/north:false/west:false/up:false/down:true,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/90/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/180/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/90/0/0 +[1.19-]modellist:id=%sculk_vein,state=east:true/south:false/north:false/west:true/up:true/down:true,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/90/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/270/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/270/0/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/90/0/0 +[1.19-]modellist:id=%sculk_vein,state=east:true/south:false/north:false/west:false/up:true/down:true,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/90/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/270/0/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/90/0/0 +[1.19-]modellist:id=%sculk_vein,state=east:true/south:false/north:false/west:true/up:false/down:true,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/90/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/270/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/90/0/0 +[1.19-]modellist:id=%sculk_vein,state=east:true/south:false/north:false/west:false/up:false/down:true,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/90/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/90/0/0 +[1.19-]modellist:id=%sculk_vein,state=east:false/south:true/north:true/west:true/up:true/down:true,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/180/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/270/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/270/0/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/90/0/0 +[1.19-]modellist:id=%sculk_vein,state=east:false/south:true/north:true/west:false/up:true/down:true,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/180/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/270/0/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/90/0/0 +[1.19-]modellist:id=%sculk_vein,state=east:false/south:true/north:true/west:true/up:false/down:true,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/180/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/270/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/90/0/0 +[1.19-]modellist:id=%sculk_vein,state=east:false/south:true/north:true/west:false/up:false/down:true,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/180/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/90/0/0 +[1.19-]modellist:id=%sculk_vein,state=east:false/south:false/north:true/west:true/up:true/down:true,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/270/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/270/0/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/90/0/0 +[1.19-]modellist:id=%sculk_vein,state=east:false/south:false/north:true/west:false/up:true/down:true,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/270/0/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/90/0/0 +[1.19-]modellist:id=%sculk_vein,state=east:false/south:false/north:true/west:true/up:false/down:true,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/270/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/90/0/0 +[1.19-]modellist:id=%sculk_vein,state=east:false/south:false/north:true/west:false/up:false/down:true,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/90/0/0 +[1.19-]modellist:id=%sculk_vein,state=east:false/south:true/north:false/west:true/up:true/down:true,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/180/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/270/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/270/0/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/90/0/0 +[1.19-]modellist:id=%sculk_vein,state=east:false/south:true/north:false/west:false/up:true/down:true,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/180/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/270/0/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/90/0/0 +[1.19-]modellist:id=%sculk_vein,state=east:false/south:true/north:false/west:true/up:false/down:true,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/180/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/270/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/90/0/0 +[1.19-]modellist:id=%sculk_vein,state=east:false/south:true/north:false/west:false/up:false/down:true,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/180/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/90/0/0 +[1.19-]modellist:id=%sculk_vein,state=east:false/south:false/north:false/west:true/up:true/down:true,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/270/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/270/0/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/90/0/0 +[1.19-]modellist:id=%sculk_vein,state=east:false/south:false/north:false/west:false/up:true/down:true,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/270/0/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/90/0/0 +[1.19-]modellist:id=%sculk_vein,state=east:false/south:false/north:false/west:true/up:false/down:true,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/270/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/90/0/0 +[1.19-]modellist:id=%sculk_vein,state=east:false/south:false/north:false/west:false/up:false/down:true,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/90/0/0 +[1.19-]modellist:id=%sculk_vein,state=east:true/south:true/north:true/west:true/up:true/down:false,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/90/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/180/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/270/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/270/0/0 +[1.19-]modellist:id=%sculk_vein,state=east:true/south:true/north:true/west:false/up:true/down:false,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/90/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/180/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/270/0/0 +[1.19-]modellist:id=%sculk_vein,state=east:true/south:true/north:true/west:true/up:false/down:false,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/90/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/180/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/270/0 +[1.19-]modellist:id=%sculk_vein,state=east:true/south:true/north:true/west:false/up:false/down:false,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/90/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/180/0 +[1.19-]modellist:id=%sculk_vein,state=east:true/south:false/north:true/west:true/up:true/down:false,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/90/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/270/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/270/0/0 +[1.19-]modellist:id=%sculk_vein,state=east:true/south:false/north:true/west:false/up:true/down:false,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/90/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/270/0/0 +[1.19-]modellist:id=%sculk_vein,state=east:true/south:false/north:true/west:true/up:false/down:false,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/90/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/270/0 +[1.19-]modellist:id=%sculk_vein,state=east:true/south:false/north:true/west:false/up:false/down:false,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/90/0 +[1.19-]modellist:id=%sculk_vein,state=east:true/south:true/north:false/west:true/up:true/down:false,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/90/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/180/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/270/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/270/0/0 +[1.19-]modellist:id=%sculk_vein,state=east:true/south:true/north:false/west:false/up:true/down:false,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/90/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/180/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/270/0/0 +[1.19-]modellist:id=%sculk_vein,state=east:true/south:true/north:false/west:true/up:false/down:false,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/90/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/180/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/270/0 +[1.19-]modellist:id=%sculk_vein,state=east:true/south:true/north:false/west:false/up:false/down:false,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/90/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/180/0 +[1.19-]modellist:id=%sculk_vein,state=east:true/south:false/north:false/west:true/up:true/down:false,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/90/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/270/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/270/0/0 +[1.19-]modellist:id=%sculk_vein,state=east:true/south:false/north:false/west:false/up:true/down:false,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/90/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/270/0/0 +[1.19-]modellist:id=%sculk_vein,state=east:true/south:false/north:false/west:true/up:false/down:false,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/90/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/270/0 +[1.19-]modellist:id=%sculk_vein,state=east:true/south:false/north:false/west:false/up:false/down:false,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/90/0 +[1.19-]modellist:id=%sculk_vein,state=east:false/south:true/north:true/west:true/up:true/down:false,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/180/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/270/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/270/0/0 +[1.19-]modellist:id=%sculk_vein,state=east:false/south:true/north:true/west:false/up:true/down:false,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/180/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/270/0/0 +[1.19-]modellist:id=%sculk_vein,state=east:false/south:true/north:true/west:true/up:false/down:false,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/180/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/270/0 +[1.19-]modellist:id=%sculk_vein,state=east:false/south:true/north:true/west:false/up:false/down:false,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/180/0 +[1.19-]modellist:id=%sculk_vein,state=east:false/south:false/north:true/west:true/up:true/down:false,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/270/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/270/0/0 +[1.19-]modellist:id=%sculk_vein,state=east:false/south:false/north:true/west:false/up:true/down:false,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/270/0/0 +[1.19-]modellist:id=%sculk_vein,state=east:false/south:false/north:true/west:true/up:false/down:false,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/270/0 +[1.19-]modellist:id=%sculk_vein,state=east:false/south:false/north:true/west:false/up:false/down:false,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000 +[1.19-]modellist:id=%sculk_vein,state=east:false/south:true/north:false/west:true/up:true/down:false,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/180/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/270/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/270/0/0 +[1.19-]modellist:id=%sculk_vein,state=east:false/south:true/north:false/west:false/up:true/down:false,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/180/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/270/0/0 +[1.19-]modellist:id=%sculk_vein,state=east:false/south:true/north:false/west:true/up:false/down:false,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/180/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/270/0 +[1.19-]modellist:id=%sculk_vein,state=east:false/south:true/north:false/west:false/up:false/down:false,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/180/0 +[1.19-]modellist:id=%sculk_vein,state=east:false/south:false/north:false/west:true/up:true/down:false,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/270/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/270/0/0 +[1.19-]modellist:id=%sculk_vein,state=east:false/south:false/north:false/west:false/up:true/down:false,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/270/0/0 +[1.19-]modellist:id=%sculk_vein,state=east:false/south:false/north:false/west:true/up:false/down:false,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/270/0 +[1.19-]modellist:id=%sculk_vein,state=east:false/south:false/north:false/west:false/up:false/down:false,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/90/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/180/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/0/270/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/270/0/0,box=0.000000/0.000000/0.100000:16.000000/16.000000/0.100000:n/0/0.000000/0.000000/16.000000/16.000000:s/0/0.000000/0.000000/16.000000/16.000000:R/90/0/0 +[1.19-]modellist:id=%sculk_shrieker,state=can_summon:true,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/2/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/1/0.000000/0.000000/16.000000/16.000000,box=1.000000/8.000000/1.000000:15.000000/15.000000/15.000000:n/0/1.000000/1.000000/15.000000/8.000000:w/0/1.000000/1.000000/15.000000/8.000000:e/0/1.000000/1.000000/15.000000/8.000000:s/0/1.000000/1.000000/15.000000/8.000000:u/3/1.000000/1.000000/15.000000/15.000000,box=1.000000/14.980000/1.000000:15.000000/14.980000/15.000000:d/3/1.000000/1.000000/15.000000/15.000000,box=1.000000/8.000000/14.980000:15.000000/15.000000/14.980000:n/0/1.000000/1.000000/15.000000/8.000000,box=1.000000/8.000000/1.020000:15.000000/15.000000/1.020000:s/0/1.000000/1.000000/15.000000/8.000000,box=14.980000/8.000000/1.000000:14.980000/15.000000/15.000000:w/0/1.000000/1.000000/15.000000/8.000000,box=1.020000/8.000000/1.000000:1.020000/15.000000/15.000000:e/0/1.000000/1.000000/15.000000/8.000000 +[1.19-]modellist:id=%sculk_shrieker,state=can_summon:false,box=0.000000/0.000000/0.000000:16.000000/8.000000/16.000000:n/0/0.000000/8.000000/16.000000/16.000000:d/2/0.000000/0.000000/16.000000/16.000000:w/0/0.000000/8.000000/16.000000/16.000000:e/0/0.000000/8.000000/16.000000/16.000000:s/0/0.000000/8.000000/16.000000/16.000000:u/1/0.000000/0.000000/16.000000/16.000000,box=1.000000/8.000000/1.000000:15.000000/15.000000/15.000000:n/0/1.000000/1.000000/15.000000/8.000000:w/0/1.000000/1.000000/15.000000/8.000000:e/0/1.000000/1.000000/15.000000/8.000000:s/0/1.000000/1.000000/15.000000/8.000000:u/3/1.000000/1.000000/15.000000/15.000000,box=1.000000/14.980000/1.000000:15.000000/14.980000/15.000000:d/3/1.000000/1.000000/15.000000/15.000000,box=1.000000/8.000000/14.980000:15.000000/15.000000/14.980000:n/0/1.000000/1.000000/15.000000/8.000000,box=1.000000/8.000000/1.020000:15.000000/15.000000/1.020000:s/0/1.000000/1.000000/15.000000/8.000000,box=14.980000/8.000000/1.000000:14.980000/15.000000/15.000000:w/0/1.000000/1.000000/15.000000/8.000000,box=1.020000/8.000000/1.000000:1.020000/15.000000/15.000000:e/0/1.000000/1.000000/15.000000/8.000000 +[1.19-]modellist:id=%ochre_froglight,state=axis:x,box=0.000000/0.000000/0.000000:16.000000/16.000000/16.000000:n/0:d/1:w/0:e/0:s/0:u180/1:R/90/90/0 +[1.19-]modellist:id=%ochre_froglight,state=axis:z,box=0.000000/0.000000/0.000000:16.000000/16.000000/16.000000:n/0:d/1:w/0:e/0:s/0:u180/1:R/90/0/0 +[1.19-]modellist:id=%verdant_froglight,state=axis:x,box=0.000000/0.000000/0.000000:16.000000/16.000000/16.000000:n/0:d/1:w/0:e/0:s/0:u180/1:R/90/90/0 +[1.19-]modellist:id=%verdant_froglight,state=axis:z,box=0.000000/0.000000/0.000000:16.000000/16.000000/16.000000:n/0:d/1:w/0:e/0:s/0:u180/1:R/90/0/0 +[1.19-]modellist:id=%pearlescent_froglight,state=axis:x,box=0.000000/0.000000/0.000000:16.000000/16.000000/16.000000:n/0:d/1:w/0:e/0:s/0:u180/1:R/90/90/0 +[1.19-]modellist:id=%pearlescent_froglight,state=axis:z,box=0.000000/0.000000/0.000000:16.000000/16.000000/16.000000:n/0:d/1:w/0:e/0:s/0:u180/1:R/90/0/0 +[1.19-]modellist:id=%frogspawn,box=0.000000/0.250000/0.000000:16.000000/0.250000/16.000000:d/0/0.000000/16.000000/16.000000/0.000000:u/0/0.000000/0.000000/16.000000/16.000000 +[1.19-]modellist:id=%potted_mangrove_propagule,box=4.500000/9.000000/8.000000:11.500000/15.000000/8.000000/0.000000/45.000000/0.000000/8.000000/0.000000/8.000000:n/0/11.000000/1.000000/4.000000/7.000000:s/0/4.000000/1.000000/11.000000/7.000000,box=8.000000/9.000000/4.500000:8.000000/15.000000/11.500000/0.000000/45.000000/0.000000/8.000000/0.000000/8.000000:w/0/4.000000/1.000000/11.000000/7.000000:e/0/11.000000/1.000000/4.000000/7.000000,box=8.000000/0.000000/7.000000:8.000000/9.000000/9.000000/0.000000/45.000000/0.000000/8.000000/0.000000/8.000000:w/0/7.000000/7.000000/9.000000/16.000000:e/0/7.000000/7.000000/9.000000/16.000000,box=7.000000/0.000000/8.000000:9.000000/9.000000/8.000000/0.000000/45.000000/0.000000/8.000000/0.000000/8.000000:n/0/7.000000/7.000000/9.000000/16.000000:s/0/7.000000/7.000000/9.000000/16.000000,box=5.000000/0.000000/5.000000:6.000000/6.000000/11.000000:n/1/10.000000/10.000000/11.000000/16.000000:d/1/5.000000/5.000000/6.000000/11.000000:w/1/5.000000/10.000000/11.000000/16.000000:e/1/5.000000/10.000000/11.000000/16.000000:s/1/5.000000/10.000000/6.000000/16.000000:u/1/5.000000/5.000000/6.000000/11.000000,box=10.000000/0.000000/5.000000:11.000000/6.000000/11.000000:n/1/5.000000/10.000000/6.000000/16.000000:d/1/10.000000/5.000000/11.000000/11.000000:w/1/5.000000/10.000000/11.000000/16.000000:e/1/5.000000/10.000000/11.000000/16.000000:s/1/10.000000/10.000000/11.000000/16.000000:u/1/10.000000/5.000000/11.000000/11.000000,box=6.000000/0.000000/5.000000:10.000000/6.000000/6.000000:n/1/6.000000/10.000000/10.000000/16.000000:d/1/6.000000/10.000000/10.000000/11.000000:s/1/6.000000/10.000000/10.000000/16.000000:u/1/6.000000/5.000000/10.000000/6.000000,box=6.000000/0.000000/10.000000:10.000000/6.000000/11.000000:n/1/6.000000/10.000000/10.000000/16.000000:d/1/6.000000/5.000000/10.000000/6.000000:s/1/6.000000/10.000000/10.000000/16.000000:u/1/6.000000/10.000000/10.000000/11.000000,box=6.000000/0.000000/6.000000:10.000000/4.000000/10.000000:d/1/6.000000/12.000000/10.000000/16.000000:u/2/6.000000/6.000000/10.000000/10.000000 +[1.19-]modellist:id=%potted_azalea_bush,box=5.000000/0.000000/5.000000:6.000000/6.000000/11.000000:n/0/10.000000/10.000000/11.000000/16.000000:d/0/5.000000/5.000000/6.000000/11.000000:w/0/5.000000/10.000000/11.000000/16.000000:e/0/5.000000/10.000000/11.000000/16.000000:s/0/5.000000/10.000000/6.000000/16.000000:u/0/5.000000/5.000000/6.000000/11.000000,box=10.000000/0.000000/5.000000:11.000000/6.000000/11.000000:n/0/5.000000/10.000000/6.000000/16.000000:d/0/10.000000/5.000000/11.000000/11.000000:w/0/5.000000/10.000000/11.000000/16.000000:e/0/5.000000/10.000000/11.000000/16.000000:s/0/10.000000/10.000000/11.000000/16.000000:u/0/10.000000/5.000000/11.000000/11.000000,box=6.000000/0.000000/5.000000:10.000000/6.000000/6.000000:n/0/6.000000/10.000000/10.000000/16.000000:d/0/6.000000/10.000000/10.000000/11.000000:s/0/6.000000/10.000000/10.000000/16.000000:u/0/6.000000/5.000000/10.000000/6.000000,box=6.000000/0.000000/10.000000:10.000000/6.000000/11.000000:n/0/6.000000/10.000000/10.000000/16.000000:d/0/6.000000/5.000000/10.000000/6.000000:s/0/6.000000/10.000000/10.000000/16.000000:u/0/6.000000/10.000000/10.000000/11.000000,box=6.000000/0.000000/6.000000:10.000000/4.000000/10.000000:d/0/6.000000/12.000000/10.000000/16.000000:u/1/6.000000/6.000000/10.000000/10.000000,box=4.000000/15.900000/4.000000:12.000000/16.000000/12.000000:d/2/4.000000/12.000000/12.000000/4.000000:u/2/4.000000/4.000000/12.000000/12.000000,box=4.000000/8.000000/4.000000:12.000000/16.000000/4.000000:n/3/4.000000/5.000000/12.000000/13.000000:s/3/12.000000/5.000000/4.000000/13.000000,box=4.000000/8.000000/12.000000:12.000000/16.000000/12.000000:n/3/12.000000/5.000000/4.000000/13.000000:s/3/4.000000/5.000000/12.000000/13.000000,box=4.000000/8.000000/4.000000:4.000000/16.000000/12.000000:w/3/4.000000/5.000000/12.000000/13.000000:e/3/12.000000/5.000000/4.000000/13.000000,box=12.000000/8.000000/4.000000:12.000000/16.000000/12.000000:w/3/12.000000/5.000000/4.000000/13.000000:e/3/4.000000/5.000000/12.000000/13.000000,box=2.600000/4.000000/8.000000:13.400000/16.000000/8.000000/0.000000/45.000000/0.000000/8.000000/8.000000/8.000000:n/4/0.000000/4.000000/16.000000/16.000000:s/4/0.000000/4.000000/16.000000/16.000000,box=8.000000/4.000000/2.600000:8.000000/16.000000/13.400000/0.000000/45.000000/0.000000/8.000000/8.000000/8.000000:w/4/0.000000/4.000000/16.000000/16.000000:e/4/0.000000/4.000000/16.000000/16.000000 +[1.19-]modellist:id=%potted_flowering_azalea_bush,box=5.000000/0.000000/5.000000:6.000000/6.000000/11.000000:n/0/10.000000/10.000000/11.000000/16.000000:d/0/5.000000/5.000000/6.000000/11.000000:w/0/5.000000/10.000000/11.000000/16.000000:e/0/5.000000/10.000000/11.000000/16.000000:s/0/5.000000/10.000000/6.000000/16.000000:u/0/5.000000/5.000000/6.000000/11.000000,box=10.000000/0.000000/5.000000:11.000000/6.000000/11.000000:n/0/5.000000/10.000000/6.000000/16.000000:d/0/10.000000/5.000000/11.000000/11.000000:w/0/5.000000/10.000000/11.000000/16.000000:e/0/5.000000/10.000000/11.000000/16.000000:s/0/10.000000/10.000000/11.000000/16.000000:u/0/10.000000/5.000000/11.000000/11.000000,box=6.000000/0.000000/5.000000:10.000000/6.000000/6.000000:n/0/6.000000/10.000000/10.000000/16.000000:d/0/6.000000/10.000000/10.000000/11.000000:s/0/6.000000/10.000000/10.000000/16.000000:u/0/6.000000/5.000000/10.000000/6.000000,box=6.000000/0.000000/10.000000:10.000000/6.000000/11.000000:n/0/6.000000/10.000000/10.000000/16.000000:d/0/6.000000/5.000000/10.000000/6.000000:s/0/6.000000/10.000000/10.000000/16.000000:u/0/6.000000/10.000000/10.000000/11.000000,box=6.000000/0.000000/6.000000:10.000000/4.000000/10.000000:d/0/6.000000/12.000000/10.000000/16.000000:u/1/6.000000/6.000000/10.000000/10.000000,box=4.000000/15.900000/4.000000:12.000000/16.000000/12.000000:d/2/4.000000/12.000000/12.000000/4.000000:u/2/4.000000/4.000000/12.000000/12.000000,box=4.000000/8.000000/4.000000:12.000000/16.000000/4.000000:n/3/4.000000/5.000000/12.000000/13.000000:s/3/12.000000/5.000000/4.000000/13.000000,box=4.000000/8.000000/12.000000:12.000000/16.000000/12.000000:n/3/12.000000/5.000000/4.000000/13.000000:s/3/4.000000/5.000000/12.000000/13.000000,box=4.000000/8.000000/4.000000:4.000000/16.000000/12.000000:w/3/4.000000/5.000000/12.000000/13.000000:e/3/12.000000/5.000000/4.000000/13.000000,box=12.000000/8.000000/4.000000:12.000000/16.000000/12.000000:w/3/12.000000/5.000000/4.000000/13.000000:e/3/4.000000/5.000000/12.000000/13.000000,box=2.600000/4.000000/8.000000:13.400000/16.000000/8.000000/0.000000/45.000000/0.000000/8.000000/8.000000/8.000000:n/4/0.000000/4.000000/16.000000/16.000000:s/4/0.000000/4.000000/16.000000/16.000000,box=8.000000/4.000000/2.600000:8.000000/16.000000/13.400000/0.000000/45.000000/0.000000/8.000000/8.000000/8.000000:w/4/0.000000/4.000000/16.000000/16.000000:e/4/0.000000/4.000000/16.000000/16.000000 +[1.19-]modellist:id=%lightning_rod,state=powered:true/facing:north,box=6.000000/12.000000/6.000000/false:10.000000/16.000000/10.000000:n/0/0.000000/0.000000/4.000000/4.000000:d/0/0.000000/0.000000/4.000000/4.000000:w/0/0.000000/0.000000/4.000000/4.000000:e/0/0.000000/0.000000/4.000000/4.000000:s/0/0.000000/0.000000/4.000000/4.000000:u/0/4.000000/4.000000/0.000000/0.000000:R/90/0/0,box=7.000000/0.000000/7.000000/false:9.000000/12.000000/9.000000:n/0/0.000000/4.000000/2.000000/16.000000:d/0/0.000000/4.000000/2.000000/16.000000:w/0/0.000000/4.000000/2.000000/16.000000:e/0/0.000000/4.000000/2.000000/16.000000:s/0/0.000000/4.000000/2.000000/16.000000:R/90/0/0 +[1.19-]modellist:id=%lightning_rod,state=powered:false/facing:north,box=6.000000/12.000000/6.000000:10.000000/16.000000/10.000000:n/0/0.000000/0.000000/4.000000/4.000000:d/0/0.000000/0.000000/4.000000/4.000000:w/0/0.000000/0.000000/4.000000/4.000000:e/0/0.000000/0.000000/4.000000/4.000000:s/0/0.000000/0.000000/4.000000/4.000000:u/0/4.000000/4.000000/0.000000/0.000000:R/90/0/0,box=7.000000/0.000000/7.000000:9.000000/12.000000/9.000000:n/0/0.000000/4.000000/2.000000/16.000000:d/0/0.000000/4.000000/2.000000/6.000000:w/0/0.000000/4.000000/2.000000/16.000000:e/0/0.000000/4.000000/2.000000/16.000000:s/0/0.000000/4.000000/2.000000/16.000000:R/90/0/0 +[1.19-]modellist:id=%lightning_rod,state=powered:true/facing:east,box=6.000000/12.000000/6.000000/false:10.000000/16.000000/10.000000:n/0/0.000000/0.000000/4.000000/4.000000:d/0/0.000000/0.000000/4.000000/4.000000:w/0/0.000000/0.000000/4.000000/4.000000:e/0/0.000000/0.000000/4.000000/4.000000:s/0/0.000000/0.000000/4.000000/4.000000:u/0/4.000000/4.000000/0.000000/0.000000:R/90/90/0,box=7.000000/0.000000/7.000000/false:9.000000/12.000000/9.000000:n/0/0.000000/4.000000/2.000000/16.000000:d/0/0.000000/4.000000/2.000000/16.000000:w/0/0.000000/4.000000/2.000000/16.000000:e/0/0.000000/4.000000/2.000000/16.000000:s/0/0.000000/4.000000/2.000000/16.000000:R/90/90/0 +[1.19-]modellist:id=%lightning_rod,state=powered:false/facing:east,box=6.000000/12.000000/6.000000:10.000000/16.000000/10.000000:n/0/0.000000/0.000000/4.000000/4.000000:d/0/0.000000/0.000000/4.000000/4.000000:w/0/0.000000/0.000000/4.000000/4.000000:e/0/0.000000/0.000000/4.000000/4.000000:s/0/0.000000/0.000000/4.000000/4.000000:u/0/4.000000/4.000000/0.000000/0.000000:R/90/90/0,box=7.000000/0.000000/7.000000:9.000000/12.000000/9.000000:n/0/0.000000/4.000000/2.000000/16.000000:d/0/0.000000/4.000000/2.000000/6.000000:w/0/0.000000/4.000000/2.000000/16.000000:e/0/0.000000/4.000000/2.000000/16.000000:s/0/0.000000/4.000000/2.000000/16.000000:R/90/90/0 +[1.19-]modellist:id=%lightning_rod,state=powered:true/facing:south,box=6.000000/12.000000/6.000000/false:10.000000/16.000000/10.000000:n/0/0.000000/0.000000/4.000000/4.000000:d/0/0.000000/0.000000/4.000000/4.000000:w/0/0.000000/0.000000/4.000000/4.000000:e/0/0.000000/0.000000/4.000000/4.000000:s/0/0.000000/0.000000/4.000000/4.000000:u/0/4.000000/4.000000/0.000000/0.000000:R/90/180/0,box=7.000000/0.000000/7.000000/false:9.000000/12.000000/9.000000:n/0/0.000000/4.000000/2.000000/16.000000:d/0/0.000000/4.000000/2.000000/16.000000:w/0/0.000000/4.000000/2.000000/16.000000:e/0/0.000000/4.000000/2.000000/16.000000:s/0/0.000000/4.000000/2.000000/16.000000:R/90/180/0 +[1.19-]modellist:id=%lightning_rod,state=powered:false/facing:south,box=6.000000/12.000000/6.000000:10.000000/16.000000/10.000000:n/0/0.000000/0.000000/4.000000/4.000000:d/0/0.000000/0.000000/4.000000/4.000000:w/0/0.000000/0.000000/4.000000/4.000000:e/0/0.000000/0.000000/4.000000/4.000000:s/0/0.000000/0.000000/4.000000/4.000000:u/0/4.000000/4.000000/0.000000/0.000000:R/90/180/0,box=7.000000/0.000000/7.000000:9.000000/12.000000/9.000000:n/0/0.000000/4.000000/2.000000/16.000000:d/0/0.000000/4.000000/2.000000/6.000000:w/0/0.000000/4.000000/2.000000/16.000000:e/0/0.000000/4.000000/2.000000/16.000000:s/0/0.000000/4.000000/2.000000/16.000000:R/90/180/0 +[1.19-]modellist:id=%lightning_rod,state=powered:true/facing:west,box=6.000000/12.000000/6.000000/false:10.000000/16.000000/10.000000:n/0/0.000000/0.000000/4.000000/4.000000:d/0/0.000000/0.000000/4.000000/4.000000:w/0/0.000000/0.000000/4.000000/4.000000:e/0/0.000000/0.000000/4.000000/4.000000:s/0/0.000000/0.000000/4.000000/4.000000:u/0/4.000000/4.000000/0.000000/0.000000:R/90/270/0,box=7.000000/0.000000/7.000000/false:9.000000/12.000000/9.000000:n/0/0.000000/4.000000/2.000000/16.000000:d/0/0.000000/4.000000/2.000000/16.000000:w/0/0.000000/4.000000/2.000000/16.000000:e/0/0.000000/4.000000/2.000000/16.000000:s/0/0.000000/4.000000/2.000000/16.000000:R/90/270/0 +[1.19-]modellist:id=%lightning_rod,state=powered:false/facing:west,box=6.000000/12.000000/6.000000:10.000000/16.000000/10.000000:n/0/0.000000/0.000000/4.000000/4.000000:d/0/0.000000/0.000000/4.000000/4.000000:w/0/0.000000/0.000000/4.000000/4.000000:e/0/0.000000/0.000000/4.000000/4.000000:s/0/0.000000/0.000000/4.000000/4.000000:u/0/4.000000/4.000000/0.000000/0.000000:R/90/270/0,box=7.000000/0.000000/7.000000:9.000000/12.000000/9.000000:n/0/0.000000/4.000000/2.000000/16.000000:d/0/0.000000/4.000000/2.000000/6.000000:w/0/0.000000/4.000000/2.000000/16.000000:e/0/0.000000/4.000000/2.000000/16.000000:s/0/0.000000/4.000000/2.000000/16.000000:R/90/270/0 +[1.19-]modellist:id=%lightning_rod,state=powered:true/facing:up,box=6.000000/12.000000/6.000000/false:10.000000/16.000000/10.000000:n/0/0.000000/0.000000/4.000000/4.000000:d/0/0.000000/0.000000/4.000000/4.000000:w/0/0.000000/0.000000/4.000000/4.000000:e/0/0.000000/0.000000/4.000000/4.000000:s/0/0.000000/0.000000/4.000000/4.000000:u/0/4.000000/4.000000/0.000000/0.000000,box=7.000000/0.000000/7.000000/false:9.000000/12.000000/9.000000:n/0/0.000000/4.000000/2.000000/16.000000:d/0/0.000000/4.000000/2.000000/16.000000:w/0/0.000000/4.000000/2.000000/16.000000:e/0/0.000000/4.000000/2.000000/16.000000:s/0/0.000000/4.000000/2.000000/16.000000 +[1.19-]modellist:id=%lightning_rod,state=powered:false/facing:up,box=6.000000/12.000000/6.000000:10.000000/16.000000/10.000000:n/0/0.000000/0.000000/4.000000/4.000000:d/0/0.000000/0.000000/4.000000/4.000000:w/0/0.000000/0.000000/4.000000/4.000000:e/0/0.000000/0.000000/4.000000/4.000000:s/0/0.000000/0.000000/4.000000/4.000000:u/0/4.000000/4.000000/0.000000/0.000000,box=7.000000/0.000000/7.000000:9.000000/12.000000/9.000000:n/0/0.000000/4.000000/2.000000/16.000000:d/0/0.000000/4.000000/2.000000/6.000000:w/0/0.000000/4.000000/2.000000/16.000000:e/0/0.000000/4.000000/2.000000/16.000000:s/0/0.000000/4.000000/2.000000/16.000000 +[1.19-]modellist:id=%lightning_rod,state=powered:true/facing:down,box=6.000000/12.000000/6.000000/false:10.000000/16.000000/10.000000:n/0/0.000000/0.000000/4.000000/4.000000:d/0/0.000000/0.000000/4.000000/4.000000:w/0/0.000000/0.000000/4.000000/4.000000:e/0/0.000000/0.000000/4.000000/4.000000:s/0/0.000000/0.000000/4.000000/4.000000:u/0/4.000000/4.000000/0.000000/0.000000:R/180/0/0,box=7.000000/0.000000/7.000000/false:9.000000/12.000000/9.000000:n/0/0.000000/4.000000/2.000000/16.000000:d/0/0.000000/4.000000/2.000000/16.000000:w/0/0.000000/4.000000/2.000000/16.000000:e/0/0.000000/4.000000/2.000000/16.000000:s/0/0.000000/4.000000/2.000000/16.000000:R/180/0/0 +[1.19-]modellist:id=%lightning_rod,state=powered:false/facing:down,box=6.000000/12.000000/6.000000:10.000000/16.000000/10.000000:n/0/0.000000/0.000000/4.000000/4.000000:d/0/0.000000/0.000000/4.000000/4.000000:w/0/0.000000/0.000000/4.000000/4.000000:e/0/0.000000/0.000000/4.000000/4.000000:s/0/0.000000/0.000000/4.000000/4.000000:u/0/4.000000/4.000000/0.000000/0.000000:R/180/0/0,box=7.000000/0.000000/7.000000:9.000000/12.000000/9.000000:n/0/0.000000/4.000000/2.000000/16.000000:d/0/0.000000/4.000000/2.000000/6.000000:w/0/0.000000/4.000000/2.000000/16.000000:e/0/0.000000/4.000000/2.000000/16.000000:s/0/0.000000/4.000000/2.000000/16.000000:R/180/0/0 diff --git a/DynmapCore/src/main/resources/texture_1.txt b/DynmapCore/src/main/resources/texture_1.txt index a437348b..42cde168 100644 --- a/DynmapCore/src/main/resources/texture_1.txt +++ b/DynmapCore/src/main/resources/texture_1.txt @@ -3201,3 +3201,535 @@ block:id=%attached_melon_stem,patch0=0:melon_stem,patch1=0:attached_melon_stem,b block:id=%pumpkin_stem,patch0=0:pumpkin_stem,blockcolor=foliagebiome,transparency=TRANSPARENT,stdrot=true # Melon stem block:id=%melon_stem,patch0=0:melon_stem,blockcolor=foliagebiome,transparency=TRANSPARENT,stdrot=true + +[1.19-]texture:id=mangrove_planks,filename=assets/minecraft/textures/block/mangrove_planks.png,xcount=1,ycount=1 +[1.19-]texture:id=mangrove_propagule_hanging,filename=assets/minecraft/textures/block/mangrove_propagule_hanging.png,xcount=1,ycount=1 +[1.19-]texture:id=mangrove_propagule,filename=assets/minecraft/textures/block/mangrove_propagule.png,xcount=1,ycount=1 +[1.19-]texture:id=mangrove_log,filename=assets/minecraft/textures/block/mangrove_log.png,xcount=1,ycount=1 +[1.19-]texture:id=mangrove_log_top,filename=assets/minecraft/textures/block/mangrove_log_top.png,xcount=1,ycount=1 +[1.19-]texture:id=mangrove_roots_side,filename=assets/minecraft/textures/block/mangrove_roots_side.png,xcount=1,ycount=1 +[1.19-]texture:id=mangrove_roots_top,filename=assets/minecraft/textures/block/mangrove_roots_top.png,xcount=1,ycount=1 +[1.19-]texture:id=mangrove_door_top,filename=assets/minecraft/textures/block/mangrove_door_top.png,xcount=1,ycount=1 +[1.19-]texture:id=mangrove_door_bottom,filename=assets/minecraft/textures/block/mangrove_door_bottom.png,xcount=1,ycount=1 +[1.19-]texture:id=muddy_mangrove_roots_side,filename=assets/minecraft/textures/block/muddy_mangrove_roots_side.png,xcount=1,ycount=1 +[1.19-]texture:id=muddy_mangrove_roots_top,filename=assets/minecraft/textures/block/muddy_mangrove_roots_top.png,xcount=1,ycount=1 +[1.19-]texture:id=stripped_mangrove_log,filename=assets/minecraft/textures/block/stripped_mangrove_log.png,xcount=1,ycount=1 +[1.19-]texture:id=stripped_mangrove_log_top,filename=assets/minecraft/textures/block/stripped_mangrove_log_top.png,xcount=1,ycount=1 +[1.19-]texture:id=mangrove_leaves,filename=assets/minecraft/textures/block/mangrove_leaves.png,xcount=1,ycount=1 +[1.19-]texture:id=mangrove_trapdoor,filename=assets/minecraft/textures/block/mangrove_trapdoor.png,xcount=1,ycount=1 +[1.19-]texture:id=foliage,filename=assets/minecraft/textures/colormap/foliage.png,xcount=1,ycount=1,format=BIOME +[1.19-]texturefile:id=mangrove_sign,filename=assets/minecraft/textures/entity/signs/mangrove.png,format=SIGN +[1.19-]texture:id=packed_mud,filename=assets/minecraft/textures/block/packed_mud.png,xcount=1,ycount=1 +[1.19-]texture:id=mud_bricks,filename=assets/minecraft/textures/block/mud_bricks.png,xcount=1,ycount=1 +[1.19-]texture:id=mud,filename=assets/minecraft/textures/block/mud.png,xcount=1,ycount=1 +[1.19-]texture:id=sculk,filename=assets/minecraft/textures/block/sculk.png,xcount=1,ycount=1 +[1.19-]texture:id=sculk_vein,filename=assets/minecraft/textures/block/sculk_vein.png,xcount=1,ycount=1 +[1.19-]texture:id=sculk_catalyst_side_bloom,filename=assets/minecraft/textures/block/sculk_catalyst_side_bloom.png,xcount=1,ycount=1 +[1.19-]texture:id=sculk_catalyst_top_bloom,filename=assets/minecraft/textures/block/sculk_catalyst_top_bloom.png,xcount=1,ycount=1 +[1.19-]texture:id=sculk_catalyst_bottom,filename=assets/minecraft/textures/block/sculk_catalyst_bottom.png,xcount=1,ycount=1 +[1.19-]texture:id=sculk_catalyst_side,filename=assets/minecraft/textures/block/sculk_catalyst_side.png,xcount=1,ycount=1 +[1.19-]texture:id=sculk_catalyst_top,filename=assets/minecraft/textures/block/sculk_catalyst_top.png,xcount=1,ycount=1 +[1.19-]texture:id=sculk_shrieker_side,filename=assets/minecraft/textures/block/sculk_shrieker_side.png,xcount=1,ycount=1 +[1.19-]texture:id=sculk_shrieker_can_summon_inner_top,filename=assets/minecraft/textures/block/sculk_shrieker_can_summon_inner_top.png,xcount=1,ycount=1 +[1.19-]texture:id=sculk_shrieker_bottom,filename=assets/minecraft/textures/block/sculk_shrieker_bottom.png,xcount=1,ycount=1 +[1.19-]texture:id=sculk_shrieker_top,filename=assets/minecraft/textures/block/sculk_shrieker_top.png,xcount=1,ycount=1 +[1.19-]texture:id=sculk_shrieker_inner_top,filename=assets/minecraft/textures/block/sculk_shrieker_inner_top.png,xcount=1,ycount=1 +[1.19-]texture:id=ochre_froglight_side,filename=assets/minecraft/textures/block/ochre_froglight_side.png,xcount=1,ycount=1 +[1.19-]texture:id=ochre_froglight_top,filename=assets/minecraft/textures/block/ochre_froglight_top.png,xcount=1,ycount=1 +[1.19-]texture:id=verdant_froglight_side,filename=assets/minecraft/textures/block/verdant_froglight_side.png,xcount=1,ycount=1 +[1.19-]texture:id=verdant_froglight_top,filename=assets/minecraft/textures/block/verdant_froglight_top.png,xcount=1,ycount=1 +[1.19-]texture:id=pearlescent_froglight_side,filename=assets/minecraft/textures/block/pearlescent_froglight_side.png,xcount=1,ycount=1 +[1.19-]texture:id=pearlescent_froglight_top,filename=assets/minecraft/textures/block/pearlescent_froglight_top.png,xcount=1,ycount=1 +[1.19-]texture:id=frogspawn,filename=assets/minecraft/textures/block/frogspawn.png,xcount=1,ycount=1 +[1.19-]texture:id=reinforced_deepslate_side,filename=assets/minecraft/textures/block/reinforced_deepslate_side.png,xcount=1,ycount=1 +[1.19-]texture:id=reinforced_deepslate_top,filename=assets/minecraft/textures/block/reinforced_deepslate_top.png,xcount=1,ycount=1 +[1.19-]texture:id=reinforced_deepslate_bottom,filename=assets/minecraft/textures/block/reinforced_deepslate_bottom.png,xcount=1,ycount=1 +[1.19-]texture:id=lightning_rod_on,filename=assets/minecraft/textures/block/lightning_rod_on.png,xcount=1,ycount=1 +[1.19-]texture:id=lightning_rod,filename=assets/minecraft/textures/block/lightning_rod.png,xcount=1,ycount=1 +[1.19-]texture:id=potted_azalea_bush_top,filename=assets/minecraft/textures/block/potted_azalea_bush_top.png,xcount=1,ycount=1 +[1.19-]texture:id=potted_azalea_bush_side,filename=assets/minecraft/textures/block/potted_azalea_bush_side.png,xcount=1,ycount=1 +[1.19-]texture:id=potted_azalea_bush_plant,filename=assets/minecraft/textures/block/potted_azalea_bush_plant.png,xcount=1,ycount=1 +[1.19-]texture:id=potted_flowering_azalea_bush_top,filename=assets/minecraft/textures/block/potted_flowering_azalea_bush_top.png,xcount=1,ycount=1 +[1.19-]texture:id=potted_flowering_azalea_bush_side,filename=assets/minecraft/textures/block/potted_flowering_azalea_bush_side.png,xcount=1,ycount=1 +[1.19-]block:id=%stripped_mangrove_wood,state=axis:x,patch0=0:stripped_mangrove_log,stdrot=true +[1.19-]block:id=%stripped_mangrove_wood,state=axis:y,patch0=0:stripped_mangrove_log,patch1=0:stripped_mangrove_log,patch2=0:stripped_mangrove_log,patch3=0:stripped_mangrove_log,patch4=0:stripped_mangrove_log,patch5=0:stripped_mangrove_log,stdrot=true +[1.19-]block:id=%stripped_mangrove_wood,state=axis:z,patch0=0:stripped_mangrove_log,stdrot=true +[1.19-]block:id=%mangrove_planks,patch0=0:mangrove_planks,patch1=0:mangrove_planks,patch2=0:mangrove_planks,patch3=0:mangrove_planks,patch4=0:mangrove_planks,patch5=0:mangrove_planks,stdrot=true +[1.19-]block:id=%mangrove_propagule,state=hanging:true/age:0,patch0=0:mangrove_propagule_hanging,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_propagule,state=hanging:false/age:0,patch0=0:mangrove_propagule,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_propagule,state=hanging:true/age:1,patch0=0:mangrove_propagule_hanging,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_propagule,state=hanging:false/age:1,patch0=0:mangrove_propagule,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_propagule,state=hanging:true/age:2,patch0=0:mangrove_propagule_hanging,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_propagule,state=hanging:false/age:2,patch0=0:mangrove_propagule,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_propagule,state=hanging:true/age:3,patch0=0:mangrove_propagule_hanging,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_propagule,state=hanging:false/age:3,patch0=0:mangrove_propagule,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_propagule,state=hanging:true/age:4,patch0=0:mangrove_propagule_hanging,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_propagule,state=hanging:false/age:4,patch0=0:mangrove_propagule,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_log,state=axis:x,patch0=0:mangrove_log,patch1=0:mangrove_log_top,stdrot=true +[1.19-]block:id=%mangrove_log,state=axis:y,patch0=0:mangrove_log,patch1=0:mangrove_log_top,patch2=0:mangrove_log,patch3=0:mangrove_log,patch4=0:mangrove_log_top,patch5=0:mangrove_log,stdrot=true +[1.19-]block:id=%mangrove_log,state=axis:z,patch0=0:mangrove_log,patch1=0:mangrove_log_top,stdrot=true +[1.19-]block:id=%mangrove_roots,patch0=0:mangrove_roots_side,patch1=0:mangrove_roots_top,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%muddy_mangrove_roots,state=axis:x,patch0=0:muddy_mangrove_roots_side,patch1=0:muddy_mangrove_roots_top,stdrot=true +[1.19-]block:id=%muddy_mangrove_roots,state=axis:y,patch0=0:muddy_mangrove_roots_side,patch1=0:muddy_mangrove_roots_top,patch2=0:muddy_mangrove_roots_side,patch3=0:muddy_mangrove_roots_side,patch4=0:muddy_mangrove_roots_top,patch5=0:muddy_mangrove_roots_side,stdrot=true +[1.19-]block:id=%muddy_mangrove_roots,state=axis:z,patch0=0:muddy_mangrove_roots_side,patch1=0:muddy_mangrove_roots_top,stdrot=true +[1.19-]block:id=%stripped_mangrove_log,state=axis:x,patch0=0:stripped_mangrove_log,patch1=0:stripped_mangrove_log_top,stdrot=true +[1.19-]block:id=%stripped_mangrove_log,state=axis:y,patch0=0:stripped_mangrove_log,patch1=0:stripped_mangrove_log_top,patch2=0:stripped_mangrove_log,patch3=0:stripped_mangrove_log,patch4=0:stripped_mangrove_log_top,patch5=0:stripped_mangrove_log,stdrot=true +[1.19-]block:id=%stripped_mangrove_log,state=axis:z,patch0=0:stripped_mangrove_log,patch1=0:stripped_mangrove_log_top,stdrot=true +[1.19-]block:id=%mangrove_wood,state=axis:x,patch0=0:mangrove_log,stdrot=true +[1.19-]block:id=%mangrove_wood,state=axis:y,patch0=0:mangrove_log,patch1=0:mangrove_log,patch2=0:mangrove_log,patch3=0:mangrove_log,patch4=0:mangrove_log,patch5=0:mangrove_log,stdrot=true +[1.19-]block:id=%mangrove_wood,state=axis:z,patch0=0:mangrove_log,stdrot=true +[1.19-]block:id=%mangrove_leaves,patch0=0:mangrove_leaves,patch1=0:mangrove_leaves,patch2=0:mangrove_leaves,patch3=0:mangrove_leaves,patch4=0:mangrove_leaves,patch5=0:mangrove_leaves,blockcolor=foliage,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_pressure_plate,state=powered:true,patch0=0:mangrove_planks,transparency=TRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_pressure_plate,state=powered:false,patch0=0:mangrove_planks,transparency=TRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_trapdoor,state=facing:north/half:top/open:true,patch0=0:mangrove_trapdoor,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_trapdoor,state=facing:north/half:top/open:false,patch0=0:mangrove_trapdoor,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_trapdoor,state=facing:north/half:bottom/open:true,patch0=0:mangrove_trapdoor,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_trapdoor,state=facing:north/half:bottom/open:false,patch0=0:mangrove_trapdoor,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_trapdoor,state=facing:south/half:top/open:true,patch0=0:mangrove_trapdoor,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_trapdoor,state=facing:south/half:top/open:false,patch0=0:mangrove_trapdoor,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_trapdoor,state=facing:south/half:bottom/open:true,patch0=0:mangrove_trapdoor,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_trapdoor,state=facing:south/half:bottom/open:false,patch0=0:mangrove_trapdoor,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_trapdoor,state=facing:west/half:top/open:true,patch0=0:mangrove_trapdoor,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_trapdoor,state=facing:west/half:top/open:false,patch0=0:mangrove_trapdoor,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_trapdoor,state=facing:west/half:bottom/open:true,patch0=0:mangrove_trapdoor,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_trapdoor,state=facing:west/half:bottom/open:false,patch0=0:mangrove_trapdoor,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_trapdoor,state=facing:east/half:top/open:true,patch0=0:mangrove_trapdoor,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_trapdoor,state=facing:east/half:top/open:false,patch0=0:mangrove_trapdoor,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_trapdoor,state=facing:east/half:bottom/open:true,patch0=0:mangrove_trapdoor,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_trapdoor,state=facing:east/half:bottom/open:false,patch0=0:mangrove_trapdoor,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_button,state=facing:north/face:floor/powered:true,patch0=0:mangrove_planks,transparency=TRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_button,state=facing:north/face:floor/powered:false,patch0=0:mangrove_planks,transparency=TRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_button,state=facing:south/face:floor/powered:true,patch0=0:mangrove_planks,transparency=TRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_button,state=facing:south/face:floor/powered:false,patch0=0:mangrove_planks,transparency=TRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_button,state=facing:west/face:floor/powered:true,patch0=0:mangrove_planks,transparency=TRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_button,state=facing:west/face:floor/powered:false,patch0=0:mangrove_planks,transparency=TRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_button,state=facing:east/face:floor/powered:true,patch0=0:mangrove_planks,transparency=TRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_button,state=facing:east/face:floor/powered:false,patch0=0:mangrove_planks,transparency=TRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_button,state=facing:north/face:wall/powered:true,patch0=0:mangrove_planks,transparency=TRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_button,state=facing:north/face:wall/powered:false,patch0=0:mangrove_planks,transparency=TRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_button,state=facing:south/face:wall/powered:true,patch0=0:mangrove_planks,transparency=TRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_button,state=facing:south/face:wall/powered:false,patch0=0:mangrove_planks,transparency=TRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_button,state=facing:west/face:wall/powered:true,patch0=0:mangrove_planks,transparency=TRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_button,state=facing:west/face:wall/powered:false,patch0=0:mangrove_planks,transparency=TRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_button,state=facing:east/face:wall/powered:true,patch0=0:mangrove_planks,transparency=TRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_button,state=facing:east/face:wall/powered:false,patch0=0:mangrove_planks,transparency=TRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_button,state=facing:north/face:ceiling/powered:true,patch0=0:mangrove_planks,transparency=TRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_button,state=facing:north/face:ceiling/powered:false,patch0=0:mangrove_planks,transparency=TRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_button,state=facing:south/face:ceiling/powered:true,patch0=0:mangrove_planks,transparency=TRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_button,state=facing:south/face:ceiling/powered:false,patch0=0:mangrove_planks,transparency=TRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_button,state=facing:west/face:ceiling/powered:true,patch0=0:mangrove_planks,transparency=TRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_button,state=facing:west/face:ceiling/powered:false,patch0=0:mangrove_planks,transparency=TRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_button,state=facing:east/face:ceiling/powered:true,patch0=0:mangrove_planks,transparency=TRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_button,state=facing:east/face:ceiling/powered:false,patch0=0:mangrove_planks,transparency=TRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_stairs,state=facing:north/half:top/shape:straight,patch0=0:mangrove_planks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_stairs,state=facing:north/half:top/shape:inner_left,patch0=0:mangrove_planks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_stairs,state=facing:north/half:top/shape:inner_right,patch0=0:mangrove_planks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_stairs,state=facing:north/half:top/shape:outer_left,patch0=0:mangrove_planks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_stairs,state=facing:north/half:top/shape:outer_right,patch0=0:mangrove_planks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_stairs,state=facing:north/half:bottom/shape:straight,patch0=0:mangrove_planks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_stairs,state=facing:north/half:bottom/shape:inner_left,patch0=0:mangrove_planks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_stairs,state=facing:north/half:bottom/shape:inner_right,patch0=0:mangrove_planks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_stairs,state=facing:north/half:bottom/shape:outer_left,patch0=0:mangrove_planks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_stairs,state=facing:north/half:bottom/shape:outer_right,patch0=0:mangrove_planks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_stairs,state=facing:south/half:top/shape:straight,patch0=0:mangrove_planks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_stairs,state=facing:south/half:top/shape:inner_left,patch0=0:mangrove_planks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_stairs,state=facing:south/half:top/shape:inner_right,patch0=0:mangrove_planks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_stairs,state=facing:south/half:top/shape:outer_left,patch0=0:mangrove_planks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_stairs,state=facing:south/half:top/shape:outer_right,patch0=0:mangrove_planks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_stairs,state=facing:south/half:bottom/shape:straight,patch0=0:mangrove_planks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_stairs,state=facing:south/half:bottom/shape:inner_left,patch0=0:mangrove_planks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_stairs,state=facing:south/half:bottom/shape:inner_right,patch0=0:mangrove_planks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_stairs,state=facing:south/half:bottom/shape:outer_left,patch0=0:mangrove_planks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_stairs,state=facing:south/half:bottom/shape:outer_right,patch0=0:mangrove_planks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_stairs,state=facing:west/half:top/shape:straight,patch0=0:mangrove_planks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_stairs,state=facing:west/half:top/shape:inner_left,patch0=0:mangrove_planks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_stairs,state=facing:west/half:top/shape:inner_right,patch0=0:mangrove_planks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_stairs,state=facing:west/half:top/shape:outer_left,patch0=0:mangrove_planks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_stairs,state=facing:west/half:top/shape:outer_right,patch0=0:mangrove_planks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_stairs,state=facing:west/half:bottom/shape:straight,patch0=0:mangrove_planks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_stairs,state=facing:west/half:bottom/shape:inner_left,patch0=0:mangrove_planks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_stairs,state=facing:west/half:bottom/shape:inner_right,patch0=0:mangrove_planks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_stairs,state=facing:west/half:bottom/shape:outer_left,patch0=0:mangrove_planks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_stairs,state=facing:west/half:bottom/shape:outer_right,patch0=0:mangrove_planks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_stairs,state=facing:east/half:top/shape:straight,patch0=0:mangrove_planks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_stairs,state=facing:east/half:top/shape:inner_left,patch0=0:mangrove_planks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_stairs,state=facing:east/half:top/shape:inner_right,patch0=0:mangrove_planks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_stairs,state=facing:east/half:top/shape:outer_left,patch0=0:mangrove_planks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_stairs,state=facing:east/half:top/shape:outer_right,patch0=0:mangrove_planks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_stairs,state=facing:east/half:bottom/shape:straight,patch0=0:mangrove_planks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_stairs,state=facing:east/half:bottom/shape:inner_left,patch0=0:mangrove_planks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_stairs,state=facing:east/half:bottom/shape:inner_right,patch0=0:mangrove_planks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_stairs,state=facing:east/half:bottom/shape:outer_left,patch0=0:mangrove_planks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_stairs,state=facing:east/half:bottom/shape:outer_right,patch0=0:mangrove_planks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_slab,state=type:top,patch0=0:mangrove_planks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_slab,state=type:bottom,patch0=0:mangrove_planks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_slab,state=type:double,patch0=0:mangrove_planks,patch1=0:mangrove_planks,patch2=0:mangrove_planks,patch3=0:mangrove_planks,patch4=0:mangrove_planks,patch5=0:mangrove_planks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_fence_gate,state=facing:north/in_wall:true/open:true,patch0=0:mangrove_planks,transparency=TRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_fence_gate,state=facing:north/in_wall:true/open:false,patch0=0:mangrove_planks,transparency=TRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_fence_gate,state=facing:north/in_wall:false/open:true,patch0=0:mangrove_planks,transparency=TRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_fence_gate,state=facing:north/in_wall:false/open:false,patch0=0:mangrove_planks,transparency=TRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_fence_gate,state=facing:south/in_wall:true/open:true,patch0=0:mangrove_planks,transparency=TRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_fence_gate,state=facing:south/in_wall:true/open:false,patch0=0:mangrove_planks,transparency=TRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_fence_gate,state=facing:south/in_wall:false/open:true,patch0=0:mangrove_planks,transparency=TRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_fence_gate,state=facing:south/in_wall:false/open:false,patch0=0:mangrove_planks,transparency=TRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_fence_gate,state=facing:west/in_wall:true/open:true,patch0=0:mangrove_planks,transparency=TRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_fence_gate,state=facing:west/in_wall:true/open:false,patch0=0:mangrove_planks,transparency=TRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_fence_gate,state=facing:west/in_wall:false/open:true,patch0=0:mangrove_planks,transparency=TRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_fence_gate,state=facing:west/in_wall:false/open:false,patch0=0:mangrove_planks,transparency=TRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_fence_gate,state=facing:east/in_wall:true/open:true,patch0=0:mangrove_planks,transparency=TRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_fence_gate,state=facing:east/in_wall:true/open:false,patch0=0:mangrove_planks,transparency=TRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_fence_gate,state=facing:east/in_wall:false/open:true,patch0=0:mangrove_planks,transparency=TRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_fence_gate,state=facing:east/in_wall:false/open:false,patch0=0:mangrove_planks,transparency=TRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_fence,state=west:true/east:true/south:true/north:true,patch0=0:mangrove_planks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_fence,state=west:false/east:true/south:true/north:true,patch0=0:mangrove_planks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_fence,state=west:true/east:true/south:false/north:true,patch0=0:mangrove_planks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_fence,state=west:false/east:true/south:false/north:true,patch0=0:mangrove_planks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_fence,state=west:true/east:true/south:true/north:false,patch0=0:mangrove_planks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_fence,state=west:false/east:true/south:true/north:false,patch0=0:mangrove_planks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_fence,state=west:true/east:true/south:false/north:false,patch0=0:mangrove_planks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_fence,state=west:false/east:true/south:false/north:false,patch0=0:mangrove_planks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_fence,state=west:true/east:false/south:true/north:true,patch0=0:mangrove_planks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_fence,state=west:false/east:false/south:true/north:true,patch0=0:mangrove_planks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_fence,state=west:true/east:false/south:false/north:true,patch0=0:mangrove_planks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_fence,state=west:false/east:false/south:false/north:true,patch0=0:mangrove_planks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_fence,state=west:true/east:false/south:true/north:false,patch0=0:mangrove_planks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_fence,state=west:false/east:false/south:true/north:false,patch0=0:mangrove_planks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_fence,state=west:true/east:false/south:false/north:false,patch0=0:mangrove_planks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_fence,state=west:false/east:false/south:false/north:false,patch0=0:mangrove_planks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_door,state=facing:north/hinge:left/half:upper/open:true,patch0=0:mangrove_door_top,transparency=TRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_door,state=facing:north/hinge:left/half:upper/open:false,patch0=0:mangrove_door_top,transparency=TRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_door,state=facing:north/hinge:right/half:upper/open:true,patch0=0:mangrove_door_top,transparency=TRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_door,state=facing:north/hinge:right/half:upper/open:false,patch0=0:mangrove_door_top,transparency=TRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_door,state=facing:north/hinge:left/half:lower/open:true,patch0=0:mangrove_door_bottom,transparency=TRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_door,state=facing:north/hinge:left/half:lower/open:false,patch0=0:mangrove_door_bottom,transparency=TRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_door,state=facing:north/hinge:right/half:lower/open:true,patch0=0:mangrove_door_bottom,transparency=TRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_door,state=facing:north/hinge:right/half:lower/open:false,patch0=0:mangrove_door_bottom,transparency=TRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_door,state=facing:south/hinge:left/half:upper/open:true,patch0=0:mangrove_door_top,transparency=TRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_door,state=facing:south/hinge:left/half:upper/open:false,patch0=0:mangrove_door_top,transparency=TRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_door,state=facing:south/hinge:right/half:upper/open:true,patch0=0:mangrove_door_top,transparency=TRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_door,state=facing:south/hinge:right/half:upper/open:false,patch0=0:mangrove_door_top,transparency=TRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_door,state=facing:south/hinge:left/half:lower/open:true,patch0=0:mangrove_door_bottom,transparency=TRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_door,state=facing:south/hinge:left/half:lower/open:false,patch0=0:mangrove_door_bottom,transparency=TRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_door,state=facing:south/hinge:right/half:lower/open:true,patch0=0:mangrove_door_bottom,transparency=TRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_door,state=facing:south/hinge:right/half:lower/open:false,patch0=0:mangrove_door_bottom,transparency=TRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_door,state=facing:west/hinge:left/half:upper/open:true,patch0=0:mangrove_door_top,transparency=TRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_door,state=facing:west/hinge:left/half:upper/open:false,patch0=0:mangrove_door_top,transparency=TRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_door,state=facing:west/hinge:right/half:upper/open:true,patch0=0:mangrove_door_top,transparency=TRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_door,state=facing:west/hinge:right/half:upper/open:false,patch0=0:mangrove_door_top,transparency=TRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_door,state=facing:west/hinge:left/half:lower/open:true,patch0=0:mangrove_door_bottom,transparency=TRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_door,state=facing:west/hinge:left/half:lower/open:false,patch0=0:mangrove_door_bottom,transparency=TRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_door,state=facing:west/hinge:right/half:lower/open:true,patch0=0:mangrove_door_bottom,transparency=TRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_door,state=facing:west/hinge:right/half:lower/open:false,patch0=0:mangrove_door_bottom,transparency=TRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_door,state=facing:east/hinge:left/half:upper/open:true,patch0=0:mangrove_door_top,transparency=TRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_door,state=facing:east/hinge:left/half:upper/open:false,patch0=0:mangrove_door_top,transparency=TRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_door,state=facing:east/hinge:right/half:upper/open:true,patch0=0:mangrove_door_top,transparency=TRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_door,state=facing:east/hinge:right/half:upper/open:false,patch0=0:mangrove_door_top,transparency=TRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_door,state=facing:east/hinge:left/half:lower/open:true,patch0=0:mangrove_door_bottom,transparency=TRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_door,state=facing:east/hinge:left/half:lower/open:false,patch0=0:mangrove_door_bottom,transparency=TRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_door,state=facing:east/hinge:right/half:lower/open:true,patch0=0:mangrove_door_bottom,transparency=TRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_door,state=facing:east/hinge:right/half:lower/open:false,patch0=0:mangrove_door_bottom,transparency=TRANSPARENT,stdrot=true +[1.19-]block:id=%mangrove_sign,patch0=0,patch1=1,patch2=2,patch3=3,patch4=4,patch5=5,patch6=6,patch7=7,patch8=8,patch9=9,transparency=TRANSPARENT,txtid=mangrove_sign +[1.19-]block:id=%mangrove_wall_sign,patch0=0,patch1=1,patch2=2,patch3=3,patch4=4,patch5=5,transparency=TRANSPARENT,txtid=mangrove_sign +[1.19-]block:id=%packed_mud,patch0=0:packed_mud,patch1=0:packed_mud,patch2=0:packed_mud,patch3=0:packed_mud,patch4=0:packed_mud,patch5=0:packed_mud,stdrot=true +[1.19-]block:id=%mud_bricks,patch0=0:mud_bricks,stdrot=true +[1.19-]block:id=%mud_brick_stairs,state=facing:north/half:top/shape:straight,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_stairs,state=facing:north/half:top/shape:inner_left,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_stairs,state=facing:north/half:top/shape:inner_right,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_stairs,state=facing:north/half:top/shape:outer_left,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_stairs,state=facing:north/half:top/shape:outer_right,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_stairs,state=facing:north/half:bottom/shape:straight,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_stairs,state=facing:north/half:bottom/shape:inner_left,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_stairs,state=facing:north/half:bottom/shape:inner_right,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_stairs,state=facing:north/half:bottom/shape:outer_left,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_stairs,state=facing:north/half:bottom/shape:outer_right,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_stairs,state=facing:south/half:top/shape:straight,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_stairs,state=facing:south/half:top/shape:inner_left,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_stairs,state=facing:south/half:top/shape:inner_right,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_stairs,state=facing:south/half:top/shape:outer_left,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_stairs,state=facing:south/half:top/shape:outer_right,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_stairs,state=facing:south/half:bottom/shape:straight,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_stairs,state=facing:south/half:bottom/shape:inner_left,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_stairs,state=facing:south/half:bottom/shape:inner_right,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_stairs,state=facing:south/half:bottom/shape:outer_left,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_stairs,state=facing:south/half:bottom/shape:outer_right,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_stairs,state=facing:west/half:top/shape:straight,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_stairs,state=facing:west/half:top/shape:inner_left,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_stairs,state=facing:west/half:top/shape:inner_right,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_stairs,state=facing:west/half:top/shape:outer_left,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_stairs,state=facing:west/half:top/shape:outer_right,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_stairs,state=facing:west/half:bottom/shape:straight,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_stairs,state=facing:west/half:bottom/shape:inner_left,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_stairs,state=facing:west/half:bottom/shape:inner_right,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_stairs,state=facing:west/half:bottom/shape:outer_left,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_stairs,state=facing:west/half:bottom/shape:outer_right,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_stairs,state=facing:east/half:top/shape:straight,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_stairs,state=facing:east/half:top/shape:inner_left,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_stairs,state=facing:east/half:top/shape:inner_right,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_stairs,state=facing:east/half:top/shape:outer_left,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_stairs,state=facing:east/half:top/shape:outer_right,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_stairs,state=facing:east/half:bottom/shape:straight,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_stairs,state=facing:east/half:bottom/shape:inner_left,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_stairs,state=facing:east/half:bottom/shape:inner_right,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_stairs,state=facing:east/half:bottom/shape:outer_left,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_stairs,state=facing:east/half:bottom/shape:outer_right,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_slab,state=type:top,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_slab,state=type:bottom,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_slab,state=type:double,patch0=0:mud_bricks,patch1=0:mud_bricks,patch2=0:mud_bricks,patch3=0:mud_bricks,patch4=0:mud_bricks,patch5=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:none/east:none/up:true/south:none/north:none,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:low/east:none/up:true/south:none/north:none,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:tall/east:none/up:true/south:none/north:none,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:none/east:none/up:false/south:none/north:none,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:low/east:none/up:false/south:none/north:none,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:tall/east:none/up:false/south:none/north:none,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:none/east:none/up:true/south:low/north:none,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:low/east:none/up:true/south:low/north:none,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:tall/east:none/up:true/south:low/north:none,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:none/east:none/up:false/south:low/north:none,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:low/east:none/up:false/south:low/north:none,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:tall/east:none/up:false/south:low/north:none,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:none/east:none/up:true/south:tall/north:none,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:low/east:none/up:true/south:tall/north:none,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:tall/east:none/up:true/south:tall/north:none,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:none/east:none/up:false/south:tall/north:none,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:low/east:none/up:false/south:tall/north:none,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:tall/east:none/up:false/south:tall/north:none,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:none/east:none/up:true/south:none/north:low,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:low/east:none/up:true/south:none/north:low,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:tall/east:none/up:true/south:none/north:low,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:none/east:none/up:false/south:none/north:low,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:low/east:none/up:false/south:none/north:low,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:tall/east:none/up:false/south:none/north:low,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:none/east:none/up:true/south:low/north:low,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:low/east:none/up:true/south:low/north:low,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:tall/east:none/up:true/south:low/north:low,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:none/east:none/up:false/south:low/north:low,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:low/east:none/up:false/south:low/north:low,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:tall/east:none/up:false/south:low/north:low,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:none/east:none/up:true/south:tall/north:low,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:low/east:none/up:true/south:tall/north:low,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:tall/east:none/up:true/south:tall/north:low,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:none/east:none/up:false/south:tall/north:low,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:low/east:none/up:false/south:tall/north:low,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:tall/east:none/up:false/south:tall/north:low,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:none/east:none/up:true/south:none/north:tall,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:low/east:none/up:true/south:none/north:tall,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:tall/east:none/up:true/south:none/north:tall,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:none/east:none/up:false/south:none/north:tall,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:low/east:none/up:false/south:none/north:tall,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:tall/east:none/up:false/south:none/north:tall,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:none/east:none/up:true/south:low/north:tall,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:low/east:none/up:true/south:low/north:tall,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:tall/east:none/up:true/south:low/north:tall,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:none/east:none/up:false/south:low/north:tall,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:low/east:none/up:false/south:low/north:tall,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:tall/east:none/up:false/south:low/north:tall,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:none/east:none/up:true/south:tall/north:tall,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:low/east:none/up:true/south:tall/north:tall,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:tall/east:none/up:true/south:tall/north:tall,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:none/east:none/up:false/south:tall/north:tall,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:low/east:none/up:false/south:tall/north:tall,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:tall/east:none/up:false/south:tall/north:tall,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:none/east:low/up:true/south:none/north:none,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:low/east:low/up:true/south:none/north:none,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:tall/east:low/up:true/south:none/north:none,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:none/east:low/up:false/south:none/north:none,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:low/east:low/up:false/south:none/north:none,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:tall/east:low/up:false/south:none/north:none,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:none/east:low/up:true/south:low/north:none,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:low/east:low/up:true/south:low/north:none,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:tall/east:low/up:true/south:low/north:none,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:none/east:low/up:false/south:low/north:none,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:low/east:low/up:false/south:low/north:none,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:tall/east:low/up:false/south:low/north:none,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:none/east:low/up:true/south:tall/north:none,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:low/east:low/up:true/south:tall/north:none,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:tall/east:low/up:true/south:tall/north:none,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:none/east:low/up:false/south:tall/north:none,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:low/east:low/up:false/south:tall/north:none,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:tall/east:low/up:false/south:tall/north:none,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:none/east:low/up:true/south:none/north:low,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:low/east:low/up:true/south:none/north:low,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:tall/east:low/up:true/south:none/north:low,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:none/east:low/up:false/south:none/north:low,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:low/east:low/up:false/south:none/north:low,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:tall/east:low/up:false/south:none/north:low,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:none/east:low/up:true/south:low/north:low,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:low/east:low/up:true/south:low/north:low,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:tall/east:low/up:true/south:low/north:low,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:none/east:low/up:false/south:low/north:low,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:low/east:low/up:false/south:low/north:low,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:tall/east:low/up:false/south:low/north:low,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:none/east:low/up:true/south:tall/north:low,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:low/east:low/up:true/south:tall/north:low,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:tall/east:low/up:true/south:tall/north:low,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:none/east:low/up:false/south:tall/north:low,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:low/east:low/up:false/south:tall/north:low,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:tall/east:low/up:false/south:tall/north:low,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:none/east:low/up:true/south:none/north:tall,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:low/east:low/up:true/south:none/north:tall,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:tall/east:low/up:true/south:none/north:tall,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:none/east:low/up:false/south:none/north:tall,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:low/east:low/up:false/south:none/north:tall,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:tall/east:low/up:false/south:none/north:tall,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:none/east:low/up:true/south:low/north:tall,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:low/east:low/up:true/south:low/north:tall,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:tall/east:low/up:true/south:low/north:tall,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:none/east:low/up:false/south:low/north:tall,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:low/east:low/up:false/south:low/north:tall,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:tall/east:low/up:false/south:low/north:tall,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:none/east:low/up:true/south:tall/north:tall,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:low/east:low/up:true/south:tall/north:tall,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:tall/east:low/up:true/south:tall/north:tall,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:none/east:low/up:false/south:tall/north:tall,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:low/east:low/up:false/south:tall/north:tall,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:tall/east:low/up:false/south:tall/north:tall,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:none/east:tall/up:true/south:none/north:none,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:low/east:tall/up:true/south:none/north:none,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:tall/east:tall/up:true/south:none/north:none,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:none/east:tall/up:false/south:none/north:none,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:low/east:tall/up:false/south:none/north:none,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:tall/east:tall/up:false/south:none/north:none,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:none/east:tall/up:true/south:low/north:none,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:low/east:tall/up:true/south:low/north:none,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:tall/east:tall/up:true/south:low/north:none,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:none/east:tall/up:false/south:low/north:none,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:low/east:tall/up:false/south:low/north:none,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:tall/east:tall/up:false/south:low/north:none,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:none/east:tall/up:true/south:tall/north:none,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:low/east:tall/up:true/south:tall/north:none,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:tall/east:tall/up:true/south:tall/north:none,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:none/east:tall/up:false/south:tall/north:none,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:low/east:tall/up:false/south:tall/north:none,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:tall/east:tall/up:false/south:tall/north:none,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:none/east:tall/up:true/south:none/north:low,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:low/east:tall/up:true/south:none/north:low,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:tall/east:tall/up:true/south:none/north:low,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:none/east:tall/up:false/south:none/north:low,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:low/east:tall/up:false/south:none/north:low,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:tall/east:tall/up:false/south:none/north:low,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:none/east:tall/up:true/south:low/north:low,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:low/east:tall/up:true/south:low/north:low,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:tall/east:tall/up:true/south:low/north:low,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:none/east:tall/up:false/south:low/north:low,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:low/east:tall/up:false/south:low/north:low,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:tall/east:tall/up:false/south:low/north:low,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:none/east:tall/up:true/south:tall/north:low,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:low/east:tall/up:true/south:tall/north:low,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:tall/east:tall/up:true/south:tall/north:low,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:none/east:tall/up:false/south:tall/north:low,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:low/east:tall/up:false/south:tall/north:low,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:tall/east:tall/up:false/south:tall/north:low,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:none/east:tall/up:true/south:none/north:tall,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:low/east:tall/up:true/south:none/north:tall,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:tall/east:tall/up:true/south:none/north:tall,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:none/east:tall/up:false/south:none/north:tall,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:low/east:tall/up:false/south:none/north:tall,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:tall/east:tall/up:false/south:none/north:tall,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:none/east:tall/up:true/south:low/north:tall,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:low/east:tall/up:true/south:low/north:tall,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:tall/east:tall/up:true/south:low/north:tall,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:none/east:tall/up:false/south:low/north:tall,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:low/east:tall/up:false/south:low/north:tall,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:tall/east:tall/up:false/south:low/north:tall,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:none/east:tall/up:true/south:tall/north:tall,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:low/east:tall/up:true/south:tall/north:tall,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:tall/east:tall/up:true/south:tall/north:tall,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:none/east:tall/up:false/south:tall/north:tall,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:low/east:tall/up:false/south:tall/north:tall,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud_brick_wall,state=west:tall/east:tall/up:false/south:tall/north:tall,patch0=0:mud_bricks,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%mud,patch0=0:mud,patch1=0:mud,patch2=0:mud,patch3=0:mud,patch4=0:mud,patch5=0:mud,stdrot=true +[1.19-]block:id=%sculk,patch0=0:sculk,patch1=0:sculk,patch2=0:sculk,patch3=0:sculk,patch4=0:sculk,patch5=0:sculk,stdrot=true +[1.19-]block:id=%sculk_vein,state=east:true/south:true/north:true/west:true/up:true/down:true,patch0=0:sculk_vein,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%sculk_vein,state=east:true/south:true/north:true/west:false/up:true/down:true,patch0=0:sculk_vein,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%sculk_vein,state=east:true/south:true/north:true/west:true/up:false/down:true,patch0=0:sculk_vein,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%sculk_vein,state=east:true/south:true/north:true/west:false/up:false/down:true,patch0=0:sculk_vein,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%sculk_vein,state=east:true/south:false/north:true/west:true/up:true/down:true,patch0=0:sculk_vein,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%sculk_vein,state=east:true/south:false/north:true/west:false/up:true/down:true,patch0=0:sculk_vein,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%sculk_vein,state=east:true/south:false/north:true/west:true/up:false/down:true,patch0=0:sculk_vein,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%sculk_vein,state=east:true/south:false/north:true/west:false/up:false/down:true,patch0=0:sculk_vein,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%sculk_vein,state=east:true/south:true/north:false/west:true/up:true/down:true,patch0=0:sculk_vein,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%sculk_vein,state=east:true/south:true/north:false/west:false/up:true/down:true,patch0=0:sculk_vein,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%sculk_vein,state=east:true/south:true/north:false/west:true/up:false/down:true,patch0=0:sculk_vein,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%sculk_vein,state=east:true/south:true/north:false/west:false/up:false/down:true,patch0=0:sculk_vein,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%sculk_vein,state=east:true/south:false/north:false/west:true/up:true/down:true,patch0=0:sculk_vein,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%sculk_vein,state=east:true/south:false/north:false/west:false/up:true/down:true,patch0=0:sculk_vein,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%sculk_vein,state=east:true/south:false/north:false/west:true/up:false/down:true,patch0=0:sculk_vein,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%sculk_vein,state=east:true/south:false/north:false/west:false/up:false/down:true,patch0=0:sculk_vein,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%sculk_vein,state=east:false/south:true/north:true/west:true/up:true/down:true,patch0=0:sculk_vein,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%sculk_vein,state=east:false/south:true/north:true/west:false/up:true/down:true,patch0=0:sculk_vein,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%sculk_vein,state=east:false/south:true/north:true/west:true/up:false/down:true,patch0=0:sculk_vein,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%sculk_vein,state=east:false/south:true/north:true/west:false/up:false/down:true,patch0=0:sculk_vein,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%sculk_vein,state=east:false/south:false/north:true/west:true/up:true/down:true,patch0=0:sculk_vein,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%sculk_vein,state=east:false/south:false/north:true/west:false/up:true/down:true,patch0=0:sculk_vein,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%sculk_vein,state=east:false/south:false/north:true/west:true/up:false/down:true,patch0=0:sculk_vein,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%sculk_vein,state=east:false/south:false/north:true/west:false/up:false/down:true,patch0=0:sculk_vein,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%sculk_vein,state=east:false/south:true/north:false/west:true/up:true/down:true,patch0=0:sculk_vein,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%sculk_vein,state=east:false/south:true/north:false/west:false/up:true/down:true,patch0=0:sculk_vein,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%sculk_vein,state=east:false/south:true/north:false/west:true/up:false/down:true,patch0=0:sculk_vein,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%sculk_vein,state=east:false/south:true/north:false/west:false/up:false/down:true,patch0=0:sculk_vein,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%sculk_vein,state=east:false/south:false/north:false/west:true/up:true/down:true,patch0=0:sculk_vein,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%sculk_vein,state=east:false/south:false/north:false/west:false/up:true/down:true,patch0=0:sculk_vein,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%sculk_vein,state=east:false/south:false/north:false/west:true/up:false/down:true,patch0=0:sculk_vein,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%sculk_vein,state=east:false/south:false/north:false/west:false/up:false/down:true,patch0=0:sculk_vein,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%sculk_vein,state=east:true/south:true/north:true/west:true/up:true/down:false,patch0=0:sculk_vein,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%sculk_vein,state=east:true/south:true/north:true/west:false/up:true/down:false,patch0=0:sculk_vein,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%sculk_vein,state=east:true/south:true/north:true/west:true/up:false/down:false,patch0=0:sculk_vein,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%sculk_vein,state=east:true/south:true/north:true/west:false/up:false/down:false,patch0=0:sculk_vein,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%sculk_vein,state=east:true/south:false/north:true/west:true/up:true/down:false,patch0=0:sculk_vein,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%sculk_vein,state=east:true/south:false/north:true/west:false/up:true/down:false,patch0=0:sculk_vein,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%sculk_vein,state=east:true/south:false/north:true/west:true/up:false/down:false,patch0=0:sculk_vein,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%sculk_vein,state=east:true/south:false/north:true/west:false/up:false/down:false,patch0=0:sculk_vein,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%sculk_vein,state=east:true/south:true/north:false/west:true/up:true/down:false,patch0=0:sculk_vein,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%sculk_vein,state=east:true/south:true/north:false/west:false/up:true/down:false,patch0=0:sculk_vein,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%sculk_vein,state=east:true/south:true/north:false/west:true/up:false/down:false,patch0=0:sculk_vein,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%sculk_vein,state=east:true/south:true/north:false/west:false/up:false/down:false,patch0=0:sculk_vein,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%sculk_vein,state=east:true/south:false/north:false/west:true/up:true/down:false,patch0=0:sculk_vein,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%sculk_vein,state=east:true/south:false/north:false/west:false/up:true/down:false,patch0=0:sculk_vein,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%sculk_vein,state=east:true/south:false/north:false/west:true/up:false/down:false,patch0=0:sculk_vein,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%sculk_vein,state=east:true/south:false/north:false/west:false/up:false/down:false,patch0=0:sculk_vein,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%sculk_vein,state=east:false/south:true/north:true/west:true/up:true/down:false,patch0=0:sculk_vein,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%sculk_vein,state=east:false/south:true/north:true/west:false/up:true/down:false,patch0=0:sculk_vein,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%sculk_vein,state=east:false/south:true/north:true/west:true/up:false/down:false,patch0=0:sculk_vein,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%sculk_vein,state=east:false/south:true/north:true/west:false/up:false/down:false,patch0=0:sculk_vein,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%sculk_vein,state=east:false/south:false/north:true/west:true/up:true/down:false,patch0=0:sculk_vein,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%sculk_vein,state=east:false/south:false/north:true/west:false/up:true/down:false,patch0=0:sculk_vein,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%sculk_vein,state=east:false/south:false/north:true/west:true/up:false/down:false,patch0=0:sculk_vein,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%sculk_vein,state=east:false/south:false/north:true/west:false/up:false/down:false,patch0=0:sculk_vein,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%sculk_vein,state=east:false/south:true/north:false/west:true/up:true/down:false,patch0=0:sculk_vein,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%sculk_vein,state=east:false/south:true/north:false/west:false/up:true/down:false,patch0=0:sculk_vein,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%sculk_vein,state=east:false/south:true/north:false/west:true/up:false/down:false,patch0=0:sculk_vein,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%sculk_vein,state=east:false/south:true/north:false/west:false/up:false/down:false,patch0=0:sculk_vein,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%sculk_vein,state=east:false/south:false/north:false/west:true/up:true/down:false,patch0=0:sculk_vein,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%sculk_vein,state=east:false/south:false/north:false/west:false/up:true/down:false,patch0=0:sculk_vein,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%sculk_vein,state=east:false/south:false/north:false/west:true/up:false/down:false,patch0=0:sculk_vein,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%sculk_vein,state=east:false/south:false/north:false/west:false/up:false/down:false,patch0=0:sculk_vein,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%sculk_catalyst,state=bloom:true,patch0=0:sculk_catalyst_side_bloom,patch1=0:sculk_catalyst_bottom,patch2=0:sculk_catalyst_side_bloom,patch3=0:sculk_catalyst_side_bloom,patch4=0:sculk_catalyst_top_bloom,patch5=0:sculk_catalyst_side_bloom,stdrot=true +[1.19-]block:id=%sculk_catalyst,state=bloom:false,patch0=0:sculk_catalyst_side,patch1=0:sculk_catalyst_bottom,patch2=0:sculk_catalyst_side,patch3=0:sculk_catalyst_side,patch4=0:sculk_catalyst_top,patch5=0:sculk_catalyst_side,stdrot=true +[1.19-]block:id=%sculk_shrieker,state=can_summon:true,patch0=0:sculk_shrieker_side,patch1=0:sculk_shrieker_can_summon_inner_top,patch2=0:sculk_shrieker_bottom,patch3=0:sculk_shrieker_top,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%sculk_shrieker,state=can_summon:false,patch0=0:sculk_shrieker_side,patch1=0:sculk_shrieker_inner_top,patch2=0:sculk_shrieker_bottom,patch3=0:sculk_shrieker_top,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%ochre_froglight,state=axis:x,patch0=0:ochre_froglight_side,patch1=0:ochre_froglight_top,stdrot=true +[1.19-]block:id=%ochre_froglight,state=axis:y,patch0=0:ochre_froglight_side,patch1=0:ochre_froglight_top,patch2=0:ochre_froglight_side,patch3=0:ochre_froglight_side,patch4=0:ochre_froglight_top,patch5=0:ochre_froglight_side,stdrot=true +[1.19-]block:id=%ochre_froglight,state=axis:z,patch0=0:ochre_froglight_side,patch1=0:ochre_froglight_top,stdrot=true +[1.19-]block:id=%verdant_froglight,state=axis:x,patch0=0:verdant_froglight_side,patch1=0:verdant_froglight_top,stdrot=true +[1.19-]block:id=%verdant_froglight,state=axis:y,patch0=0:verdant_froglight_side,patch1=0:verdant_froglight_top,patch2=0:verdant_froglight_side,patch3=0:verdant_froglight_side,patch4=0:verdant_froglight_top,patch5=0:verdant_froglight_side,stdrot=true +[1.19-]block:id=%verdant_froglight,state=axis:z,patch0=0:verdant_froglight_side,patch1=0:verdant_froglight_top,stdrot=true +[1.19-]block:id=%pearlescent_froglight,state=axis:x,patch0=0:pearlescent_froglight_side,patch1=0:pearlescent_froglight_top,stdrot=true +[1.19-]block:id=%pearlescent_froglight,state=axis:y,patch0=0:pearlescent_froglight_side,patch1=0:pearlescent_froglight_top,patch2=0:pearlescent_froglight_side,patch3=0:pearlescent_froglight_side,patch4=0:pearlescent_froglight_top,patch5=0:pearlescent_froglight_side,stdrot=true +[1.19-]block:id=%pearlescent_froglight,state=axis:z,patch0=0:pearlescent_froglight_side,patch1=0:pearlescent_froglight_top,stdrot=true +[1.19-]block:id=%frogspawn,patch0=0:frogspawn,transparency=TRANSPARENT,stdrot=true +[1.19-]block:id=%potted_mangrove_propagule,patch0=0:mangrove_propagule,patch1=0:flower_pot,patch2=0:dirt,transparency=TRANSPARENT,stdrot=true +[1.19-]block:id=%potted_azalea_bush,patch0=0:flower_pot,patch1=0:dirt,patch2=0:potted_azalea_bush_top,patch3=0:potted_azalea_bush_side,patch4=0:potted_azalea_bush_plant,transparency=TRANSPARENT,stdrot=true +[1.19-]block:id=%potted_flowering_azalea_bush,patch0=0:flower_pot,patch1=0:dirt,patch2=0:potted_flowering_azalea_bush_top,patch3=0:potted_flowering_azalea_bush_side,patch4=0:potted_azalea_bush_plant,transparency=TRANSPARENT,stdrot=true +[1.19-]block:id=%reinforced_deepslate,patch0=0:reinforced_deepslate_side,patch1=0:reinforced_deepslate_bottom,patch2=0:reinforced_deepslate_side,patch3=0:reinforced_deepslate_side,patch4=0:reinforced_deepslate_top,patch5=0:reinforced_deepslate_side,stdrot=true +[1.19-]block:id=%lightning_rod,state=powered:true/facing:north,patch0=0:lightning_rod_on,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%lightning_rod,state=powered:false/facing:north,patch0=0:lightning_rod,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%lightning_rod,state=powered:true/facing:east,patch0=0:lightning_rod_on,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%lightning_rod,state=powered:false/facing:east,patch0=0:lightning_rod,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%lightning_rod,state=powered:true/facing:south,patch0=0:lightning_rod_on,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%lightning_rod,state=powered:false/facing:south,patch0=0:lightning_rod,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%lightning_rod,state=powered:true/facing:west,patch0=0:lightning_rod_on,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%lightning_rod,state=powered:false/facing:west,patch0=0:lightning_rod,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%lightning_rod,state=powered:true/facing:up,patch0=0:lightning_rod_on,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%lightning_rod,state=powered:false/facing:up,patch0=0:lightning_rod,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%lightning_rod,state=powered:true/facing:down,patch0=0:lightning_rod_on,transparency=SEMITRANSPARENT,stdrot=true +[1.19-]block:id=%lightning_rod,state=powered:false/facing:down,patch0=0:lightning_rod,transparency=SEMITRANSPARENT,stdrot=true diff --git a/DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/frogspawn.png b/DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/frogspawn.png new file mode 100644 index 0000000000000000000000000000000000000000..2289054037930df07fc414b34c86a64559f786b9 GIT binary patch literal 157 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`DV{ElAr_~T6Amyf+kSohs?+}L z$!tXo9*ZT!5C4DkB;ykgLnh0^7Ki>&mRPs0;*Gm{M4l&=O6oli5*2vs8^hK4O---W zrFwEi>le?AA2|mLG|i5xsHW$1UCcfBIzNf2KTVQ{A?4sy)4o-f%YpVWc)I$ztaD0e F0sw#gI3NH3 literal 0 HcmV?d00001 diff --git a/DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/mangrove_door_bottom.png b/DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/mangrove_door_bottom.png new file mode 100644 index 0000000000000000000000000000000000000000..d8ab5639a951c591be5fc7062b1578325ba1a5b6 GIT binary patch literal 278 zcmV+x0qOpUP)ve{y9 z>y<1|fb%#E*ToX&H6DrJCnw30p;XZnBoBhf3C{#&hy!o{pPuJoBD^oBIRR@&N`T0X zz}xDT>TJog=1Nd6_W@`C^23l{9b`!*h-h&lK|@QTg@(17P=}_BQ)RU2opiOQ|)$@ zF$w}f3`O@KVxyH{A?yfRiM^ezo&8i|=>cp#uwP#I6K5B)Lz2x)Cdmw+>*;+tN~EB_ z&SUmCK>pieImmt<#>Z~26UEYbqz7Qba$m0ydm!Z*R7+a+lGwSOD}Yi80Kcc{fg4b3 zMRT3*(l8CsC!5pJ-F0v@ZkDS+PMX~;03P+m2;cq|6K XL|M>$u$2~n00000NkvXXu0mjf28?dH literal 0 HcmV?d00001 diff --git a/DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/mangrove_leaves.png b/DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/mangrove_leaves.png new file mode 100644 index 0000000000000000000000000000000000000000..ec40483b9bf9ca06a243fb960b2cb0cb99584020 GIT binary patch literal 279 zcmV+y0qFjTP)21FxeCIY}y8op2gxXZwZ=8;xL)WL!PzyJUcmpOdh zVU~wCC9RR2Z2{h9?M+#0P_`Yt%SS;=}#28^ZIpAIszT1;z!B zF$X-Zr_D%2it!C`K5Qp+hnQ-j;$EHistjJaR+F-h_^rS%9hocWfM1dwbuN>@<+|iL zbx+p2*@7lorFFBY$;?IC@mfnxif(}a7)pMCK8Qq;TAKuEWlYpVkHt0mDw7ww_K+Ob sd7vXjnr{7heBB>L@(OFK>wH4I07NvtkfagEq5uE@07*qoM6N<$g1l&FmH+?% literal 0 HcmV?d00001 diff --git a/DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/mangrove_log_top.png b/DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/mangrove_log_top.png new file mode 100644 index 0000000000000000000000000000000000000000..f2c4d64f1c5bbb82f9e3a79d4d138e3a1621fc99 GIT binary patch literal 285 zcmV+&0pk9NP)dZ22;_e$&@J9C#iZ6gBEhZ##UxkOx9}H%{Avq* z1RlE8=L3QN3#FMTwNO>i2j4;%Wf7DHN6?Uk7GM#9AK_o%9n>3vzg-IC*A^`WCS58%;vH&_Y)szP}c$?}mt0e^18t{cy~UpL!s%IWNJdI%#sB+iUE z6y|vUfS`oD^N~A-WY2^qBS7Fi*Ar_~T6Be***oA$wPYM1} zzsa;(=j*@s7gIjY*O5MXiRTi-rHK9ZZ|q&`@@Ktpoyn-`+c!m$fs6hB;e$`4nYh?D zE$-LSW5`@~f^|X0k{hgs;=(7)8J5gkbcE%SPhb*LrrMMl460}RW~`bfxfW<8gQu&X J%Q~loCIDL`IKTh^ literal 0 HcmV?d00001 diff --git a/DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/mangrove_propagule_hanging.png b/DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/mangrove_propagule_hanging.png new file mode 100644 index 0000000000000000000000000000000000000000..1ebc363927241edfe85dd231795e979a3344c82b GIT binary patch literal 258 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Cp}#pLo7}wXRO%xFFq#W*L+5f zoK0W<-<~efbW>qMRKgGY?WZKp9p`eG<=ED6L*cBPuUG-E!r7~Hul?Y)*kS(b|0PMi z1XqQ#in9-W%ywYcy%_cXbW_N|Sq`&or&S&1{qgtprFwy5*$f`WCjTa7 z_V*sKH&z1D%Ne&FJN5tW8q&t;uc GLK6Ugac1}c literal 0 HcmV?d00001 diff --git a/DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/mangrove_roots_side.png b/DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/mangrove_roots_side.png new file mode 100644 index 0000000000000000000000000000000000000000..658754e4632b66a4b89f60fdf2bc267349523b17 GIT binary patch literal 250 zcmVgaS=428<}QMTwMKJJ$#Ez6qW!3_qATGIq zYOYExg1ZDS;8TkUXjwbbs!@V!q{}Xe1ng!qQWMfhlf)V&E+zt(csJHMWX1GQh{f0F z6@8@1=t+`KAi5lUs5|~>;+zBVMBt7m5+z{KKlAwNZuF+UApigX07*qoM6N<$g4wWU AZU6uP literal 0 HcmV?d00001 diff --git a/DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/mangrove_roots_top.png b/DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/mangrove_roots_top.png new file mode 100644 index 0000000000000000000000000000000000000000..5e2eb107e338a6c99ac12afce6045b9eb1da93df GIT binary patch literal 266 zcmV+l0rmcgP)KFDjuf^b)z%k;5oWi=U<$!P#c4yS#LC{AOnq^U1eTPd#Q3~3^nytlHR zsiG55l084hv~XAxN~ry7OL(z)ZTeK5#0^iQ#M$a$xfh#9<-e$#nSXMUUHR(>;&7!0WWH!ehhDdI?$^B3}Y3(KD2Eyh6p2sG#funauH6sva0awQ-2~65tCsTLR55| z+X})!3`FxozEqG>un1nj;{X57$}F69c6xSKtisMqI70jC(RSkR<<&071;_V}Q^% zG#wIMoUH5$BBb2uXY1>d&Oza4tO5=da|7}LmnIX51o+M8d4mQHoVUvT!-Ky_w&G}} h0uDQ0UFwcb_AjBau}IJyG8F&-002ovPDHLkV1f(Fd))v4 literal 0 HcmV?d00001 diff --git a/DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/mud_bricks.png b/DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/mud_bricks.png new file mode 100644 index 0000000000000000000000000000000000000000..f138a525060c916fb9d793d2b644d3a6e102f08c GIT binary patch literal 209 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbL!bbwEYE0B)!aLf#JtBdvMN%x;x z7%;aYW_4TQy8c4*=~cIY(u^fRe!&b5&u*jvIVqkljv*3~tOpwd859{Lz)YTnpShqim&Sl8jd3x02MYr!u!12eAK`;xXl2|GoR$1MBaXtw2#5l)z4*}Q$iB} DU9n8` literal 0 HcmV?d00001 diff --git a/DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/muddy_mangrove_roots_side.png b/DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/muddy_mangrove_roots_side.png new file mode 100644 index 0000000000000000000000000000000000000000..9436714368d10ea18681327a2d3c441ce82f71dc GIT binary patch literal 330 zcmV-Q0k!^#P){ z(P{!g3`O%T_Q4mWV5x}MRp?r5Dg6Nd|36mFz!@*ohp?G!?oD!&nhyKr^!n25c=%}c zcU~`VyW=vyubNMe@$aAC<$l{VA548+ruHBRh#)}Xe2u5iSHC{zYY$)$P%#s&KKc|X zl5uQ{N+d}@EQ{o5#2W!Nf+e6M3CN+CV}k1)5WobJB*3;6lsrc*mA5Ux3Bb<+yX|vp zT?0puKuxkEtFlH%fV>i5MOBs{Zv{QKgDfH=tm-0me*FuD2LJ#7 literal 0 HcmV?d00001 diff --git a/DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/muddy_mangrove_roots_top.png b/DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/muddy_mangrove_roots_top.png new file mode 100644 index 0000000000000000000000000000000000000000..dbbe6b0e9666850b1d6310c377abddb6c4c1409b GIT binary patch literal 336 zcmV-W0k8gvP)s9}HoA#Hd zhrU_AR_vZ9eKFq@PQU?&L&%5Ieh#xv00Iyaz2n~^@Z^KHJXjqCNfgVX*Y9QF%|xpc z{G(+4xT-J77RY8FyM1p+BSy)N^7+0kqRDx#5$u{?&}}r$JH4<$ji5YDgg__4g8!*& zI?TaK=LFBrX|gI?IxRuTIBi$vKAz59#dps*N`sufuc7IzP-0GEWFb5*klNu%LqqBH62UyGG9=O|@jn&R7! iX1RI%UoNLRV}Aj%39R8^Hf8Jp0000@gidb-3O!#}Qw_ub;6)CO zpA_^!z7-H9!FCc6Ie0gW(o7IJcYpxKY+tmspB>;kIFHj! z@P&C;D5@1`WoeMZX9<3^q-AyBodc7yU_*-4N9MgRw1iQ0miHTv-IT&*JVluR0000< KMNUMnLSTXug=mTZ literal 0 HcmV?d00001 diff --git a/DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/ochre_froglight_top.png b/DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/ochre_froglight_top.png new file mode 100644 index 0000000000000000000000000000000000000000..68cfb4255a9e7e87f4c895fbb12ccb26913a3b23 GIT binary patch literal 205 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61SBU+%rFB|Q#@T9Lp08>4RYjaFyMLJUE9Y0 zL37@pmV369Vl4el9k(V4cJsV+kcchl%=Auqv#N5%_LVoUi+#OO%}{eOoJp1Y<|*f| z4Kt(^fA0|s;qO@J$@KqEVZx*+uB<6)t~sWHd;)?qnAbgcpUbv?>HO$Jix%k~T)1Fq zdfOu1Nbj2&KV0_6ZhH86=I5N#LXUW7iYqftXS--m#X$Elc)I$ztaD0e F0st~EQDguB literal 0 HcmV?d00001 diff --git a/DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/packed_mud.png b/DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/packed_mud.png new file mode 100644 index 0000000000000000000000000000000000000000..c1539af5849eda61042314e456787970faccc7f2 GIT binary patch literal 265 zcmV+k0rvihP)$W7!RzZ>Rlu z-oG|DBm9P~vIKZDP6;C7Utw1hE($44fBAW*Pz?Cn?+8!8>dkkd#v9$`+D P00000NkvXXu0mjf?3-)} literal 0 HcmV?d00001 diff --git a/DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/pearlescent_froglight_side.png b/DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/pearlescent_froglight_side.png new file mode 100644 index 0000000000000000000000000000000000000000..8f15ce6ae75dbe11d25aed35481b080c32350d81 GIT binary patch literal 257 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61SBU+%rFB|Cp=voLp09!PO|1>GURcot>Zhu zX~7`N>fv$Wg1&eHcNABK#t)uZFA{TmTAoy>f3rAwOZfE7s_i#U_uX#(Yr!-9v!{dH znk!lR1TCvB{Vg*MJy4iGHPrWjng2aE75RmiqZ^&pKR+D8Y{*bCvH7t&tL=n*Ru|6= zb6s5c?(r@*5e8Dfx~CNGUU=r~fmptOKjt_6T7FvWws`K_boL*7=N^{`*Cfh`b!D+e zMM^#S5ZNTJn;9uv@%+FNof{L9zD}%s&#jvnGWY3Uw#v|ra$O1!4gvkd;OXk;vd$@? F2>{BbXTJad literal 0 HcmV?d00001 diff --git a/DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/pearlescent_froglight_top.png b/DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/pearlescent_froglight_top.png new file mode 100644 index 0000000000000000000000000000000000000000..c8cb05115ccfe2578ec4a73962debf47869981a9 GIT binary patch literal 204 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61SBU+%rFB|lRaG=Lp08>4cg7s;K1|xe|`IZ z#TSp(*)M2b-K@uF7gcmbsr`$CMb$xXpJ*lDt9+&AU;i5QulT)<=|T5CA&tlrVREb3 zk6hundA)K$l>?8j(2wW+%#*JK1uQnvOj_Mp(9m%}rhv6R-}r~_-#bELqPd)Wth%AT}nZE{H3zasiGQ^ez49$8yWSV6}1lUw#rNy+4n}IGisn z=iFnSCJW7>Mm32)>+9LBx4Q{SDeZV#EbxyY3^k}707!t$;##YP3JJv*wS*)LK&6-~ z6M|q)T|onF;$AV~_sl$<_*#q&5bc?{$OY#+z(e-zYu*5`vL*QC2HM0uDMYW%_k`Yt z0la_oKyWfKYT>{wP2qt}_k$-$e6Yq`z`Y;=AEdhY@d3(Gmsq}k?_!b<^c)u- z^?|xjLhlEDyZa!mQ3r|0Ncn$&n0(-zQ6Kowd>fN}kbA%d|N4NSpiMYD4>XG}lh8Nj TvaLWK00000NkvXXu0mjfzV?ct literal 0 HcmV?d00001 diff --git a/DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/reinforced_deepslate_top.png b/DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/reinforced_deepslate_top.png new file mode 100644 index 0000000000000000000000000000000000000000..bee3fab0dca4c3f42e21f9b05d94f2c35adbda90 GIT binary patch literal 299 zcmV+`0o4A9P)dV01kuX1Q@O}@OK6RXf!0l1w4sd}GZj-=Cw68!{^?VR`QsM3RT)1;m zorAzFGw}*m)OLfwlip`-0f6sw2B^|kRj%Zad=Wsx+4G+Jao`Whhv^P#9-(}RdY1l_ xeI~Ak6V>to^D}9s0H6~w1Jy_{KhwY8`2&fz@iDguI12y(002ovPDHLkV1lHcfz|*3 literal 0 HcmV?d00001 diff --git a/DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/sculk.png b/DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/sculk.png new file mode 100644 index 0000000000000000000000000000000000000000..fef9d9760a94d0db924c610feca9e4a12020194a GIT binary patch literal 370 zcmV-&0ge8NP) zF$w}P5Jd-MOABp8thUtB8`y}Y7qIb2g6H!99zq#m!q4AHq6?y{DZ;{J_Gj`lc|^w3 z*$u~J(T35i*5S+Z789JnL>AMbF%z{B1axA)-6cgVr#T)X5lN|YWtf9;!33{lOJ=Vu zF5X^MaJ1PMD~n9@s^ER&&$d7$z~y-!aK*s`UWG+C7WDxe>BYPXB7s~Zc`JugzzJ+5 zZ)H0j6zMb)SD>OS5^ceA*)uW~6E7*ZZ>~f2cj3Euu)JK0Jdo45@*u?n z4fN)L{;VgE6Djh*I_tAMuqH`~zRUv_?ZpG{Dpww4c)*TV9<)hTzJ~|u?ho()%}Tuw zxY>&D13bYP);|@PzN7&VjkX6zs6NJ|iOp)A$J1Gv z*Jg%)vRJy}z5`CeEtbd#vlx)cD-rFs=G2yMjEG;T8iA2JFamDB8bL+mVjd+FF&cr3 zS(j+ZDiM)5-|Zanvl9_tl3UWBsD53h Y4wZ>A-^6X!)&Kwi07*qoM6N<$g4rZ-ga7~l literal 0 HcmV?d00001 diff --git a/DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/sculk_catalyst_side.png b/DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/sculk_catalyst_side.png new file mode 100644 index 0000000000000000000000000000000000000000..1225e9650ccf3ff4fbbe7fe09255c89129a3f483 GIT binary patch literal 314 zcmV-A0mc4_P)#R3Tf*3Cay{T!Pf0P&G|;69mC=0UQR&2{5%BpojRIZ<9B9OqLb1 z|G#hEd^2Zq$APKDXcPW3}$YI-@iJ zdB;l)wH<(96hZ}@Lz?PBBnM%3jX?84b>0C4VJ7XQ0$jtVvAds<7m1uC9O#;R^M9bF zkdRq-|C;W;^w32RPQSak7UvEgX7hyf0oAS-Qp2( z6hD(SYyufd{OOtM|7*H?XI?t9u|6CXjg9eEid6Nig}LIXozd%q6W3q0D-9>Sb%ns#=4-B z8X;LV1T-z=$g2TOFek1_Hc$@6Plpa zb4||0Z4CyK{btf-$l+=+YMKE=ny}4=+K-@d{5}u#1q literal 0 HcmV?d00001 diff --git a/DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/sculk_catalyst_side_bloom.png.mcmeta b/DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/sculk_catalyst_side_bloom.png.mcmeta new file mode 100644 index 00000000..d1cd0799 --- /dev/null +++ b/DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/sculk_catalyst_side_bloom.png.mcmeta @@ -0,0 +1,5 @@ +{ + "animation": { + "frametime": 1 + } +} diff --git a/DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/sculk_catalyst_top.png b/DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/sculk_catalyst_top.png new file mode 100644 index 0000000000000000000000000000000000000000..00ee9fad84d8302cd78c2a071bb37391b73fec7f GIT binary patch literal 245 zcmVmFrMRbxAIgZb<-5)+&yW^>9bGg>5 zePF>29#pcd#6XHFf^3{$?;#0h;<+@E7_qA|o?$$Az)8lidIdb(tx0&hKmICfCOQ=( zZ?cC4MUa5Xa~`PT09$UEkto)3021Eh%ynPeOq^vvH`gz?km#LkG?W5c1!?uqKT;)W vCped#ks~bJ(Clti5{?}qfjSNnCpF(MdCFAD3&CpM00000NkvXXu0mjfRn%O! literal 0 HcmV?d00001 diff --git a/DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/sculk_catalyst_top_bloom.png b/DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/sculk_catalyst_top_bloom.png new file mode 100644 index 0000000000000000000000000000000000000000..d59da0e276f603a7d544ce25f3eba05fd91ca4d5 GIT binary patch literal 806 zcmV+>1KIqEP)+&ET>5&KMmptfUJ-RlZqt)4%$rsAe*1CPn)DO0^gj3vX z{h&nS;=xn%fK!-k{b17|I#Q;7unFLUC6g}{BB{)DlrQixD8sqM1Fka{9w5#+-bXy( zHsgy!wti5#@{#&M@q@*K#e=8kf%=LwTR*65aHM`v{2+$&hzI`P$852%zArrc?~NlK k48J#yc(A@VKAU>tJrn(Rx}TZ7^8f$<07*qoM6N<$g0iN3R{#J2 literal 0 HcmV?d00001 diff --git a/DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/sculk_catalyst_top_bloom.png.mcmeta b/DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/sculk_catalyst_top_bloom.png.mcmeta new file mode 100644 index 00000000..d1cd0799 --- /dev/null +++ b/DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/sculk_catalyst_top_bloom.png.mcmeta @@ -0,0 +1,5 @@ +{ + "animation": { + "frametime": 1 + } +} diff --git a/DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/sculk_shrieker_bottom.png b/DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/sculk_shrieker_bottom.png new file mode 100644 index 0000000000000000000000000000000000000000..a3bf18fee5f4dff722188310a8a8d8cf3eef0739 GIT binary patch literal 240 zcmVxBz+^DdO%mIohKo-uA=MaLP`SWg&7|~T3_i#SA!AVB5dWC$rT@yInUw@S~6P*g( zn}5cD22gp<165oe=oE!$uHAte>2gj%1MD4=n_REJ1wJG<8Lz{T%^|6Rges)1;9Pb_ qj&k9e_V!jK;pjLL_r!du`TYT6CrQRHqEveT0000Q3*gxf&m56MUB^lwJppLF!H*lWFHdzV_%g|NnvnbMMoh!1F z0ue%CHAPn<&-ytOptmDO>RVA*qtmu}9{n->9yxEbVl)Al$#3$^>?WWS(NTT55PQ$T zCJN{*jJpc+s=5MBBupAkCN`%hl9$SBX*{L!w>Q&|Z0Fy}gAqP)=-1#mDGxaI6Bi&N zE)O_eF{GRiQzmB1RV8EWRx$A)%Q`iOH=5x=v=c=^M5Pw(L}NxkrC|c^L{9;lX?PGh zD$5C%2T{zuWHUVQV(yu<%7ZK?iU%8bppIKp=<-10p3yk14>$*KC7!}56E%sVT{%)6 zluSIp{T`jroS733yyY{MyhFFGO<*E1v4#oJ3Ct#;0#hG&j`AEkLDiIb5Dg7uiuLGV z@fd;0mh!+$TV=$5;z7p5RUYuZh?KZI;Bq(PLdpZoK3xH?#P9&mzU-*?d4R=ba-g6& z6A#92OgPBdXzvTjn{kymXSy#$Z`U_7tql*>iV7x{%L5LXxrA)x0b@QaG$S5pWfq-O zn|OeQ#(%pnV9n^!IK3}06SA9Z*gs(5=q_z5Rbm2`y=uZX9wgh^T)wl*b#_V_9&D}5 zQXXU&^UMo*piXmd@myqi*FKK}9-%`XFbAT@r2PZ#WQ3_)_l4>wRzI=&iN%BJCsseP z`iaGZ>L*q|vHFSCPpp1o^%JX~SpCH6CsseP`iXz0pZEzs3q_$}AgXi#00005P)xWb8cHUhVV&dogipW!*v=s+K)49U zLF`;?=Zo$3^7=H%xPN?@Zf@_U&Bf(B-rk?5z5T;^$nW}hnIm&muE`Ji$L`7LA}|^< zS7c@dqK$<&N5|9V{A_Ah*Yi`}JtZRBORjRFzW=d1)iU6shwC_rnY67Q2$5qhWb{&n@W9%-v52F5g7z|Z3^!|jAN5{m+5qh4PwkUPAfXhv`R-^Y7!q91mi|?TCWQ zR;ICrkbNYvGrL4NnPWq80e;uSeMJ038NJO$o~Y-?yF%AymwY#}4C z9&=v6@F4SjWMG#E>@qJlhCJZAAc~EY2cvBj4+cE&jHw14<_8&_^*!VP3Ye9%Kr%ql zkcCzF6n3Gk){e3eJZQ*^jt6*&x-<&5(IOstC(>KMAdRWyUAm~;@BppvUge&FJ1;of zFnI#mrsIK5$THMnexPSRx{dxD50Hsp=7HWukynO1;J^y8&OA`}>9Z>VG9HYsbUsX7 zy%0s78k4ut*9%Efg?7O?t-A}8_-8U(9$;>qdDleeb(kXTKB}AuEX+$kih|UY>G)hmP@jA;l$+?-mn|mWdar6V5}*##VreHvYJj`v^k&&;2-KB&w?Bxz;m9~@oq1uJWL3tZ z2npKbi2)I2fKYYm@Zb$fmLMFCcB+FWq=wc9+54za1)cTh;$EjK0~kq0om$V=67y%; z;K$O=fCt13^qA6kPw-})7=V5eefJHL07TX93V`8%GlhZS YE&qzZvU5cb>!3=|M_3No}yhfEpcu|Mb!`hhHcQh~lN59lKtkmw1=lkB>d;h=>L2#Rd+MDnPM zly}xoj?YyESGG>!LAWmh2Jqzw~7+Qgd8^)kImog^R;x$kd3|DHXM65VgIJJFJyfgr% zwrVi;@Md9(6(lb*MGsJYnx70XM-SYlRS*1~>cJF72KB(*e!olxspb}sd2blcF^@8dh@*uFlLhRGp4tZUczHg7)zO7>)=dNE{ zoZr`_i}}J2IEN4jY&f9#5+E=h0>cUnZ^oA}VjVd}iIk18^837}l#xl5LFXVniZkmx zKm_3o!04=A?M85r>K8`@IPk$4D0!#Ri~3^@QtAR!btIEmwUfXQQNimj{6!hp8F8>a ziL?3@w46jo(N8k#3_B+dW}oM*Lw4x%35eTZj zMeB7r8}p%J-`B8&{Zs_;u3&EqmVDQptxlHz3rLNs74DG0n_B;X`Ts|2H6?0rjem(oCzq-bk; z!(aSJV$u-OumIESZS@@dDb~>2>dPzuXZ(Lr!5>&mtiL)tOJDc^9b?1oF;a~g00000 LNkvXXu0mjf6uEA{ literal 0 HcmV?d00001 diff --git a/DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/verdant_froglight_side.png b/DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/verdant_froglight_side.png new file mode 100644 index 0000000000000000000000000000000000000000..5f18747c7c6b065c52eaf4cb4134369354634e1b GIT binary patch literal 258 zcmV+d0sa1oP)Pit&{ z-pL=Y!}z!W@W!Mz!wPcrq}%f@DnM~<$x;($i-(svl8@l@RzPTaO`;0GFtCRlK7Llv z1AHrR)Cq5A5y;_pn^Bqwki&2NMasC{Q097|E{Fg4pMv_Q%NENQZS7}g@Ex4SsV3;c zJS;1!6|k~2oU_jo{Ah_Kb=WIs?34r>D3%YVy)Kl5t?DfAH@dBkIx1o`MF0Q*07*qo IM6N<$g5a2IU;qFB literal 0 HcmV?d00001 diff --git a/DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/verdant_froglight_top.png b/DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/block/verdant_froglight_top.png new file mode 100644 index 0000000000000000000000000000000000000000..964bfb7b9203985f108c602df61860131944631b GIT binary patch literal 205 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61SBU+%rFB|Q#@T9Lp08>4Kn0vaNv3U_;2Il z?)?QtUs#pSo$K1n*Q9HiHNm+`L1ym*)n&R9t5)3F_;PyQJ@qSJ?=XCDjhEGkoU_&@ zgsm@D`JCN4=BbUz8Iv03+w=JZc{}!ATGFvr?GdvJ%d-aUAJwxPw|^=2jtJSJY9X@a z%b9>Js@a;-ynaV+D@xm)li956-C>@hFVdQ&MBb@ E06!v5w*UYD literal 0 HcmV?d00001 diff --git a/DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/entity/signs/mangrove.png b/DynmapCore/src/main/resources/texturepacks/standard/assets/minecraft/textures/entity/signs/mangrove.png new file mode 100644 index 0000000000000000000000000000000000000000..c18ac85b87616e3320dad850653cbcc7de719ee0 GIT binary patch literal 506 zcmVb9>2V zvU$Vs(>`ua%iI28kzVkA@e9mZ;Poh9)|MydEBT-ImnQi9VQhQZU6kjo?Sft)e@Mm* ztO0sWIM!N(k8$MuZo}baz6pUI*XF!@xiOiuZcy{Bys16Yf!QSJSy@Vm5cX|1Kh$R4bdTMFB^%8h;L@kqB=UW>0@<&Mk zAy(6u4pHu>!VfzDWPO7*eX=HbeO-JjyGQt=-hWHKHGO+?Lrvez*ZSr?QGQnr@MzhZ z_wM6)>s@EvV_xS1FTbk}&|$?I)SA;_J~jTRN>Crf2XK Date: Fri, 17 Jun 2022 18:47:54 +0100 Subject: [PATCH 25/27] safari coloured search bar added support for coloured bar in apple safari 15+ --- DynmapCore/src/main/resources/extracted/web/index.html | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/DynmapCore/src/main/resources/extracted/web/index.html b/DynmapCore/src/main/resources/extracted/web/index.html index 38bb3e17..575a0ca4 100644 --- a/DynmapCore/src/main/resources/extracted/web/index.html +++ b/DynmapCore/src/main/resources/extracted/web/index.html @@ -10,7 +10,8 @@ - + + @@ -54,4 +55,4 @@
- \ No newline at end of file + From a119844669cb91576da175517a062fdac7de6ad5 Mon Sep 17 00:00:00 2001 From: Mike Primm Date: Sun, 19 Jun 2022 13:34:45 -0500 Subject: [PATCH 26/27] Set to 3.4-beta-4 --- build.gradle | 2 +- oldbuilds/build.gradle | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index b8e6ac94..f486652e 100644 --- a/build.gradle +++ b/build.gradle @@ -38,7 +38,7 @@ allprojects { apply plugin: 'java' group = 'us.dynmap' - version = '3.4-SNAPSHOT' + version = '3.4-beta-4' } diff --git a/oldbuilds/build.gradle b/oldbuilds/build.gradle index cb3a2143..9e3696e3 100644 --- a/oldbuilds/build.gradle +++ b/oldbuilds/build.gradle @@ -25,7 +25,7 @@ allprojects { apply plugin: 'java' group = 'us.dynmap' - version = '3.4-SNAPSHOT' + version = '3.4-beta-4' } From 58189196075f7a5f6cc6dfda7408b127b6fb727e Mon Sep 17 00:00:00 2001 From: Mike Primm Date: Sun, 19 Jun 2022 13:45:23 -0500 Subject: [PATCH 27/27] Update forge used in 1.19 build --- forge-1.19/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/forge-1.19/build.gradle b/forge-1.19/build.gradle index e4c9fcc2..ce729e91 100644 --- a/forge-1.19/build.gradle +++ b/forge-1.19/build.gradle @@ -40,7 +40,7 @@ dependencies { implementation project(path: ":DynmapCore", configuration: "shadow") implementation project(path: ':DynmapCoreAPI') - minecraft 'net.minecraftforge:forge:1.19-41.0.1' + minecraft 'net.minecraftforge:forge:1.19-41.0.38' } processResources