From 3520fe2a4476ea4550e8a51f15d9650c2548462d Mon Sep 17 00:00:00 2001 From: kuroppoi <68156848+kuroppoi@users.noreply.github.com> Date: Sun, 30 May 2021 23:04:01 +0200 Subject: [PATCH] Experimental prefab system & structure generation --- .../java/brainwine/gameserver/GameServer.java | 7 + .../gameserver/command/CommandManager.java | 4 + .../command/commands/ExportCommand.java | 97 ++++++++++ .../command/commands/ImportCommand.java | 60 ++++++ .../java/brainwine/gameserver/item/Item.java | 20 ++ .../brainwine/gameserver/item/ModType.java | 1 + .../gameserver/msgpack/MessagePackHelper.java | 10 +- .../msgpack/templates/BlockArrayTemplate.java | 49 +++++ .../msgpack/templates/ChunkTemplate.java | 16 +- .../msgpack/templates/PrefabTemplate.java | 50 +++++ .../prefab/CorrespondingReplacement.java | 31 ++++ .../brainwine/gameserver/prefab/Prefab.java | 132 ++++++++++++++ .../gameserver/prefab/PrefabManager.java | 98 ++++++++++ .../server/requests/BlockUseRequest.java | 170 ++++++++++++----- .../brainwine/gameserver/util/Vector2i.java | 43 +++++ .../java/brainwine/gameserver/zone/Zone.java | 171 ++++++++++++++++++ .../gameserver/zone/gen/GeneratorConfig.java | 37 ++++ .../gameserver/zone/gen/GeneratorContext.java | 28 +++ .../zone/gen/StructureGenerator.java | 87 +++++++++ .../gameserver/zone/gen/ZoneGenerator.java | 4 +- gameserver/src/main/resources/generators.json | 168 +++++++++++++++++ .../prefabs/dungeon_large_1/blocks.cmp | Bin 0 -> 835 bytes .../prefabs/dungeon_large_1/config.json | 24 +++ .../prefabs/dungeon_large_2/blocks.cmp | Bin 0 -> 997 bytes .../prefabs/dungeon_large_2/config.json | 23 +++ .../prefabs/dungeon_medium_1/blocks.cmp | Bin 0 -> 521 bytes .../prefabs/dungeon_medium_1/config.json | 13 ++ .../prefabs/dungeon_medium_10/blocks.cmp | Bin 0 -> 639 bytes .../prefabs/dungeon_medium_10/config.json | 19 ++ .../prefabs/dungeon_medium_2/blocks.cmp | 2 + .../prefabs/dungeon_medium_2/config.json | 40 ++++ .../prefabs/dungeon_medium_3/blocks.cmp | Bin 0 -> 575 bytes .../prefabs/dungeon_medium_3/config.json | 29 +++ .../prefabs/dungeon_medium_4/blocks.cmp | Bin 0 -> 479 bytes .../prefabs/dungeon_medium_4/config.json | 60 ++++++ .../prefabs/dungeon_medium_5/blocks.cmp | Bin 0 -> 510 bytes .../prefabs/dungeon_medium_5/config.json | 19 ++ .../prefabs/dungeon_medium_6/blocks.cmp | Bin 0 -> 524 bytes .../prefabs/dungeon_medium_6/config.json | 43 +++++ .../prefabs/dungeon_medium_7/blocks.cmp | Bin 0 -> 456 bytes .../prefabs/dungeon_medium_7/config.json | 19 ++ .../prefabs/dungeon_medium_8/blocks.cmp | Bin 0 -> 363 bytes .../prefabs/dungeon_medium_8/config.json | 29 +++ .../prefabs/dungeon_medium_9/blocks.cmp | Bin 0 -> 431 bytes .../prefabs/dungeon_medium_9/config.json | 56 ++++++ .../prefabs/dungeon_small_1/blocks.cmp | 3 + .../prefabs/dungeon_small_1/config.json | 22 +++ .../prefabs/dungeon_small_2/blocks.cmp | Bin 0 -> 390 bytes .../prefabs/dungeon_small_2/config.json | 29 +++ .../prefabs/dungeon_small_3/blocks.cmp | Bin 0 -> 205 bytes .../prefabs/dungeon_small_3/config.json | 6 + .../prefabs/dungeon_small_4/blocks.cmp | Bin 0 -> 347 bytes .../prefabs/dungeon_small_4/config.json | 6 + .../resources/prefabs/head_bunker/blocks.cmp | 1 + .../resources/prefabs/head_bunker/config.json | 43 +++++ .../resources/prefabs/paint_bunker/blocks.cmp | Bin 0 -> 226 bytes .../prefabs/paint_bunker/config.json | 31 ++++ .../prefabs/plain_spawn_tower_1/blocks.cmp | Bin 0 -> 148 bytes .../prefabs/plain_spawn_tower_1/config.json | 38 ++++ .../prefabs/plain_spawn_tower_2/blocks.cmp | Bin 0 -> 86 bytes .../prefabs/plain_spawn_tower_2/config.json | 32 ++++ .../prefabs/plain_spawn_tower_3/blocks.cmp | Bin 0 -> 166 bytes .../prefabs/plain_spawn_tower_3/config.json | 46 +++++ .../prefabs/plain_spawn_tower_4/blocks.cmp | Bin 0 -> 129 bytes .../prefabs/plain_spawn_tower_4/config.json | 15 ++ 65 files changed, 1865 insertions(+), 66 deletions(-) create mode 100644 gameserver/src/main/java/brainwine/gameserver/command/commands/ExportCommand.java create mode 100644 gameserver/src/main/java/brainwine/gameserver/command/commands/ImportCommand.java create mode 100644 gameserver/src/main/java/brainwine/gameserver/msgpack/templates/BlockArrayTemplate.java create mode 100644 gameserver/src/main/java/brainwine/gameserver/msgpack/templates/PrefabTemplate.java create mode 100644 gameserver/src/main/java/brainwine/gameserver/prefab/CorrespondingReplacement.java create mode 100644 gameserver/src/main/java/brainwine/gameserver/prefab/Prefab.java create mode 100644 gameserver/src/main/java/brainwine/gameserver/prefab/PrefabManager.java create mode 100644 gameserver/src/main/java/brainwine/gameserver/util/Vector2i.java create mode 100644 gameserver/src/main/java/brainwine/gameserver/zone/gen/StructureGenerator.java create mode 100644 gameserver/src/main/resources/prefabs/dungeon_large_1/blocks.cmp create mode 100644 gameserver/src/main/resources/prefabs/dungeon_large_1/config.json create mode 100644 gameserver/src/main/resources/prefabs/dungeon_large_2/blocks.cmp create mode 100644 gameserver/src/main/resources/prefabs/dungeon_large_2/config.json create mode 100644 gameserver/src/main/resources/prefabs/dungeon_medium_1/blocks.cmp create mode 100644 gameserver/src/main/resources/prefabs/dungeon_medium_1/config.json create mode 100644 gameserver/src/main/resources/prefabs/dungeon_medium_10/blocks.cmp create mode 100644 gameserver/src/main/resources/prefabs/dungeon_medium_10/config.json create mode 100644 gameserver/src/main/resources/prefabs/dungeon_medium_2/blocks.cmp create mode 100644 gameserver/src/main/resources/prefabs/dungeon_medium_2/config.json create mode 100644 gameserver/src/main/resources/prefabs/dungeon_medium_3/blocks.cmp create mode 100644 gameserver/src/main/resources/prefabs/dungeon_medium_3/config.json create mode 100644 gameserver/src/main/resources/prefabs/dungeon_medium_4/blocks.cmp create mode 100644 gameserver/src/main/resources/prefabs/dungeon_medium_4/config.json create mode 100644 gameserver/src/main/resources/prefabs/dungeon_medium_5/blocks.cmp create mode 100644 gameserver/src/main/resources/prefabs/dungeon_medium_5/config.json create mode 100644 gameserver/src/main/resources/prefabs/dungeon_medium_6/blocks.cmp create mode 100644 gameserver/src/main/resources/prefabs/dungeon_medium_6/config.json create mode 100644 gameserver/src/main/resources/prefabs/dungeon_medium_7/blocks.cmp create mode 100644 gameserver/src/main/resources/prefabs/dungeon_medium_7/config.json create mode 100644 gameserver/src/main/resources/prefabs/dungeon_medium_8/blocks.cmp create mode 100644 gameserver/src/main/resources/prefabs/dungeon_medium_8/config.json create mode 100644 gameserver/src/main/resources/prefabs/dungeon_medium_9/blocks.cmp create mode 100644 gameserver/src/main/resources/prefabs/dungeon_medium_9/config.json create mode 100644 gameserver/src/main/resources/prefabs/dungeon_small_1/blocks.cmp create mode 100644 gameserver/src/main/resources/prefabs/dungeon_small_1/config.json create mode 100644 gameserver/src/main/resources/prefabs/dungeon_small_2/blocks.cmp create mode 100644 gameserver/src/main/resources/prefabs/dungeon_small_2/config.json create mode 100644 gameserver/src/main/resources/prefabs/dungeon_small_3/blocks.cmp create mode 100644 gameserver/src/main/resources/prefabs/dungeon_small_3/config.json create mode 100644 gameserver/src/main/resources/prefabs/dungeon_small_4/blocks.cmp create mode 100644 gameserver/src/main/resources/prefabs/dungeon_small_4/config.json create mode 100644 gameserver/src/main/resources/prefabs/head_bunker/blocks.cmp create mode 100644 gameserver/src/main/resources/prefabs/head_bunker/config.json create mode 100644 gameserver/src/main/resources/prefabs/paint_bunker/blocks.cmp create mode 100644 gameserver/src/main/resources/prefabs/paint_bunker/config.json create mode 100644 gameserver/src/main/resources/prefabs/plain_spawn_tower_1/blocks.cmp create mode 100644 gameserver/src/main/resources/prefabs/plain_spawn_tower_1/config.json create mode 100644 gameserver/src/main/resources/prefabs/plain_spawn_tower_2/blocks.cmp create mode 100644 gameserver/src/main/resources/prefabs/plain_spawn_tower_2/config.json create mode 100644 gameserver/src/main/resources/prefabs/plain_spawn_tower_3/blocks.cmp create mode 100644 gameserver/src/main/resources/prefabs/plain_spawn_tower_3/config.json create mode 100644 gameserver/src/main/resources/prefabs/plain_spawn_tower_4/blocks.cmp create mode 100644 gameserver/src/main/resources/prefabs/plain_spawn_tower_4/config.json diff --git a/gameserver/src/main/java/brainwine/gameserver/GameServer.java b/gameserver/src/main/java/brainwine/gameserver/GameServer.java index 2524adf..f0fd7f4 100644 --- a/gameserver/src/main/java/brainwine/gameserver/GameServer.java +++ b/gameserver/src/main/java/brainwine/gameserver/GameServer.java @@ -10,6 +10,7 @@ import brainwine.gameserver.command.CommandManager; import brainwine.gameserver.entity.player.PlayerManager; import brainwine.gameserver.loot.LootManager; import brainwine.gameserver.msgpack.MessagePackHelper; +import brainwine.gameserver.prefab.PrefabManager; import brainwine.gameserver.server.NetworkRegistry; import brainwine.gameserver.server.Server; import brainwine.gameserver.zone.ZoneManager; @@ -23,6 +24,7 @@ public class GameServer { private final Thread handlerThread; private final Queue tasks = new ConcurrentLinkedQueue<>(); private final LootManager lootManager; + private final PrefabManager prefabManager; private final ZoneManager zoneManager; private final PlayerManager playerManager; private final Server server; @@ -38,6 +40,7 @@ public class GameServer { GameConfiguration.init(); MessagePackHelper.init(); lootManager = new LootManager(); + prefabManager = new PrefabManager(); StaticZoneGenerator.init(); zoneManager = new ZoneManager(); playerManager = new PlayerManager(); @@ -106,6 +109,10 @@ public class GameServer { return lootManager; } + public PrefabManager getPrefabManager() { + return prefabManager; + } + public ZoneManager getZoneManager() { return zoneManager; } diff --git a/gameserver/src/main/java/brainwine/gameserver/command/CommandManager.java b/gameserver/src/main/java/brainwine/gameserver/command/CommandManager.java index b76d216..6dbbbb5 100644 --- a/gameserver/src/main/java/brainwine/gameserver/command/CommandManager.java +++ b/gameserver/src/main/java/brainwine/gameserver/command/CommandManager.java @@ -13,9 +13,11 @@ import org.apache.logging.log4j.Logger; import brainwine.gameserver.command.commands.AdminCommand; import brainwine.gameserver.command.commands.BroadcastCommand; +import brainwine.gameserver.command.commands.ExportCommand; import brainwine.gameserver.command.commands.GenerateZoneCommand; import brainwine.gameserver.command.commands.GiveCommand; import brainwine.gameserver.command.commands.HelpCommand; +import brainwine.gameserver.command.commands.ImportCommand; import brainwine.gameserver.command.commands.KickCommand; import brainwine.gameserver.command.commands.PlayerIdCommand; import brainwine.gameserver.command.commands.PositionCommand; @@ -62,6 +64,8 @@ public class CommandManager { registerCommand(new GiveCommand()); registerCommand(new GenerateZoneCommand()); registerCommand(new SeedCommand()); + registerCommand(new ExportCommand()); + registerCommand(new ImportCommand()); registerCommand(new PositionCommand()); } diff --git a/gameserver/src/main/java/brainwine/gameserver/command/commands/ExportCommand.java b/gameserver/src/main/java/brainwine/gameserver/command/commands/ExportCommand.java new file mode 100644 index 0000000..457e06a --- /dev/null +++ b/gameserver/src/main/java/brainwine/gameserver/command/commands/ExportCommand.java @@ -0,0 +1,97 @@ +package brainwine.gameserver.command.commands; + +import static brainwine.gameserver.entity.player.NotificationType.ALERT; + +import java.util.Arrays; + +import brainwine.gameserver.GameServer; +import brainwine.gameserver.command.Command; +import brainwine.gameserver.command.CommandExecutor; +import brainwine.gameserver.entity.player.Player; +import brainwine.gameserver.prefab.Prefab; +import brainwine.gameserver.prefab.PrefabManager; +import brainwine.gameserver.zone.Zone; + +public class ExportCommand extends Command { + + public static final int SIZE_LIMIT = 10000; + + @Override + public void execute(CommandExecutor executor, String[] args) { + if(args.length < 5) { + executor.notify(String.format("Usage: %s", getUsage(executor)), ALERT); + return; + } + + Zone zone = ((Player)executor).getZone(); + PrefabManager prefabManager = GameServer.getInstance().getPrefabManager(); + String name = String.join(" ", Arrays.copyOfRange(args, 4, args.length)); + + if(prefabManager.getPrefab(name) != null) { + executor.notify("A prefab with that name already exists.", ALERT); + return; + } + + int x = 0; + int y = 0; + int width = 0; + int height = 0; + + try { + x = Integer.parseInt(args[0]); + y = Integer.parseInt(args[1]); + width = Integer.parseInt(args[2]); + height = Integer.parseInt(args[3]); + } catch(NumberFormatException e) { + executor.notify("Parameters must be valid numbers.", ALERT); + return; + } + + if(width < 0 || height < 0) { + executor.notify("Width and height must be positive.", ALERT); + return; + } else if(width * height > SIZE_LIMIT) { + executor.notify(String.format("Sorry, your prefab is too large. Max size: %s blocks.", SIZE_LIMIT), ALERT); + return; + } else if(x < 0 || x + width >= zone.getWidth() || y < 0 || y + height >= zone.getHeight()) { + executor.notify("These coordinates are out of bounds.", ALERT); + return; + } + + Prefab prefab = zone.chop(x, y, width, height); + + if(prefab == null) { + executor.notify("Sorry, something went wrong. Please try again.", ALERT); + return; + } + + executor.notify("Exporting your prefab ...", ALERT); + + try { + prefabManager.registerPrefab(name, prefab); + executor.notify(String.format("Your prefab '%s' was successfully exported!", name), ALERT); + } catch (Exception e) { + executor.notify(String.format("An error occured while exporting prefab '%s': %s", name, e.getMessage()), ALERT); + } + } + + @Override + public String getName() { + return "export"; + } + + @Override + public String getDescription() { + return "Exports a section of a zone to a prefab file."; + } + + @Override + public String getUsage(CommandExecutor executor) { + return "/export "; + } + + @Override + public boolean canExecute(CommandExecutor executor) { + return executor instanceof Player && executor.isAdmin(); + } +} diff --git a/gameserver/src/main/java/brainwine/gameserver/command/commands/ImportCommand.java b/gameserver/src/main/java/brainwine/gameserver/command/commands/ImportCommand.java new file mode 100644 index 0000000..ff3b050 --- /dev/null +++ b/gameserver/src/main/java/brainwine/gameserver/command/commands/ImportCommand.java @@ -0,0 +1,60 @@ +package brainwine.gameserver.command.commands; + +import static brainwine.gameserver.entity.player.NotificationType.ALERT; + +import brainwine.gameserver.GameServer; +import brainwine.gameserver.command.Command; +import brainwine.gameserver.command.CommandExecutor; +import brainwine.gameserver.entity.player.Player; +import brainwine.gameserver.prefab.Prefab; + +public class ImportCommand extends Command { + + @Override + public void execute(CommandExecutor executor, String[] args) { + if(args.length < 3) { + executor.notify(String.format("Usage: %s", getUsage(executor)), ALERT); + return; + } + + int x = 0; + int y = 0; + + try { + x = Integer.parseInt(args[1]); + y = Integer.parseInt(args[2]); + } catch(NumberFormatException e) { + executor.notify("X and Y must be valid numbers.", ALERT); + return; + } + + Prefab prefab = GameServer.getInstance().getPrefabManager().getPrefab(args[0]); + + if(prefab == null) { + executor.notify("Sorry, could not find a prefab with that name.", ALERT); + return; + } + + ((Player)executor).getZone().placePrefab(prefab, x, y); + } + + @Override + public String getName() { + return "import"; + } + + @Override + public String getDescription() { + return "Places a prefab at the specified location."; + } + + @Override + public String getUsage(CommandExecutor executor) { + return "/import "; + } + + @Override + public boolean canExecute(CommandExecutor executor) { + return executor instanceof Player && executor.isAdmin(); + } +} diff --git a/gameserver/src/main/java/brainwine/gameserver/item/Item.java b/gameserver/src/main/java/brainwine/gameserver/item/Item.java index 58bda42..ece9c87 100644 --- a/gameserver/src/main/java/brainwine/gameserver/item/Item.java +++ b/gameserver/src/main/java/brainwine/gameserver/item/Item.java @@ -11,6 +11,8 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonValue; +import brainwine.gameserver.util.Vector2i; + @JsonIgnoreProperties(ignoreUnknown = true) public class Item { @@ -36,6 +38,9 @@ public class Item { @JsonProperty("title") private String title; + @JsonProperty("rotation") + private String rotation; + @JsonProperty("loot_graphic") private LootGraphic lootGraphic = LootGraphic.NONE; @@ -51,6 +56,9 @@ public class Item { @JsonProperty("meta") private MetaType meta = MetaType.NONE; + @JsonProperty("size") + private Vector2i size = new Vector2i(1, 1); + @JsonProperty("field") private int field; @@ -130,6 +138,10 @@ public class Item { return title; } + public boolean isMirrorable() { + return rotation != null && rotation.equalsIgnoreCase("mirror"); + } + public boolean isAir() { return id == 0; } @@ -166,6 +178,14 @@ public class Item { return meta; } + public int getBlockWidth() { + return size.getX(); + } + + public int getBlockHeight() { + return size.getY(); + } + public boolean isDish() { return field > 1; } diff --git a/gameserver/src/main/java/brainwine/gameserver/item/ModType.java b/gameserver/src/main/java/brainwine/gameserver/item/ModType.java index 2c52612..18069ac 100644 --- a/gameserver/src/main/java/brainwine/gameserver/item/ModType.java +++ b/gameserver/src/main/java/brainwine/gameserver/item/ModType.java @@ -5,6 +5,7 @@ import com.fasterxml.jackson.annotation.JsonEnumDefaultValue; public enum ModType { DECAY, + ROTATION, @JsonEnumDefaultValue NONE; diff --git a/gameserver/src/main/java/brainwine/gameserver/msgpack/MessagePackHelper.java b/gameserver/src/main/java/brainwine/gameserver/msgpack/MessagePackHelper.java index 0947505..3f06482 100644 --- a/gameserver/src/main/java/brainwine/gameserver/msgpack/MessagePackHelper.java +++ b/gameserver/src/main/java/brainwine/gameserver/msgpack/MessagePackHelper.java @@ -12,17 +12,19 @@ import org.msgpack.packer.BufferPacker; import org.msgpack.unpacker.BufferUnpacker; import brainwine.gameserver.item.Item; +import brainwine.gameserver.msgpack.models.AppearanceData; import brainwine.gameserver.msgpack.models.BlockUseData; import brainwine.gameserver.msgpack.models.DialogInputData; -import brainwine.gameserver.msgpack.models.AppearanceData; +import brainwine.gameserver.msgpack.templates.AppearanceDataTemplate; +import brainwine.gameserver.msgpack.templates.BlockArrayTemplate; import brainwine.gameserver.msgpack.templates.BlockTemplate; import brainwine.gameserver.msgpack.templates.BlockUseDataTemplate; import brainwine.gameserver.msgpack.templates.ChunkTemplate; import brainwine.gameserver.msgpack.templates.DialogInputDataTemplate; import brainwine.gameserver.msgpack.templates.EnumTemplate; import brainwine.gameserver.msgpack.templates.ItemTemplate; -import brainwine.gameserver.msgpack.templates.AppearanceDataTemplate; -import brainwine.gameserver.reflections.ReflectionsHelper; +import brainwine.gameserver.msgpack.templates.PrefabTemplate; +import brainwine.gameserver.prefab.Prefab; import brainwine.gameserver.util.ReflectionsHelper; import brainwine.gameserver.util.ZipUtils; import brainwine.gameserver.zone.Block; @@ -44,7 +46,9 @@ public class MessagePackHelper { logger.info("Registering MessagePack templates ..."); messagePack.register(Item.class, new ItemTemplate()); messagePack.register(Block.class, new BlockTemplate()); + messagePack.register(Block[].class, new BlockArrayTemplate()); messagePack.register(Chunk.class, new ChunkTemplate()); + messagePack.register(Prefab.class, new PrefabTemplate()); messagePack.register(BlockUseData.class, new BlockUseDataTemplate()); messagePack.register(DialogInputData.class, new DialogInputDataTemplate()); messagePack.register(AppearanceData.class, new AppearanceDataTemplate()); diff --git a/gameserver/src/main/java/brainwine/gameserver/msgpack/templates/BlockArrayTemplate.java b/gameserver/src/main/java/brainwine/gameserver/msgpack/templates/BlockArrayTemplate.java new file mode 100644 index 0000000..f8047c1 --- /dev/null +++ b/gameserver/src/main/java/brainwine/gameserver/msgpack/templates/BlockArrayTemplate.java @@ -0,0 +1,49 @@ +package brainwine.gameserver.msgpack.templates; + +import java.io.IOException; + +import org.msgpack.MessageTypeException; +import org.msgpack.packer.Packer; +import org.msgpack.template.AbstractTemplate; +import org.msgpack.unpacker.Unpacker; + +import brainwine.gameserver.zone.Block; + +public class BlockArrayTemplate extends AbstractTemplate { + + @Override + public void write(Packer packer, Block[] blocks, boolean required) throws IOException { + if(blocks == null) { + if(required) { + throw new MessageTypeException("Attempted to write null"); + } + + packer.writeNil(); + return; + } + + packer.writeArrayBegin(blocks.length * 3); + + for(Block block : blocks) { + packer.write(block); + } + + packer.writeArrayEnd(); + } + + @Override + public Block[] read(Unpacker unpacker, Block[] to, boolean required) throws IOException { + if(!required && unpacker.trySkipNil()) { + return null; + } + + Block[] blocks = new Block[unpacker.readArrayBegin() / 3]; + + for(int i = 0; i < blocks.length; i++) { + blocks[i] = unpacker.read(Block.class); + } + + unpacker.readArrayEnd(); + return blocks; + } +} diff --git a/gameserver/src/main/java/brainwine/gameserver/msgpack/templates/ChunkTemplate.java b/gameserver/src/main/java/brainwine/gameserver/msgpack/templates/ChunkTemplate.java index 019be11..344f9c9 100644 --- a/gameserver/src/main/java/brainwine/gameserver/msgpack/templates/ChunkTemplate.java +++ b/gameserver/src/main/java/brainwine/gameserver/msgpack/templates/ChunkTemplate.java @@ -29,13 +29,7 @@ public class ChunkTemplate extends AbstractTemplate { packer.write(chunk.getY()); packer.write(chunk.getWidth()); packer.write(chunk.getHeight()); - packer.writeArrayBegin(blocks.length * 3); - - for(Block block : blocks) { - packer.write(block); - } - - packer.writeArrayEnd(); + packer.write(blocks); packer.writeArrayEnd(); } @@ -50,15 +44,13 @@ public class ChunkTemplate extends AbstractTemplate { int y = unpacker.readInt(); int width = unpacker.readInt(); int height = unpacker.readInt(); - unpacker.readArrayBegin(); - int numBlocks = width * height; + Block[] blocks = unpacker.read(Block[].class); Chunk chunk = new Chunk(x, y, width, height); - for(int i = 0; i < numBlocks; i++) { - chunk.setBlock(i, unpacker.read(Block.class)); + for(int i = 0; i < blocks.length; i++) { + chunk.setBlock(i, blocks[i]); } - unpacker.readArrayEnd(); unpacker.readArrayEnd(); return chunk; } diff --git a/gameserver/src/main/java/brainwine/gameserver/msgpack/templates/PrefabTemplate.java b/gameserver/src/main/java/brainwine/gameserver/msgpack/templates/PrefabTemplate.java new file mode 100644 index 0000000..49b7742 --- /dev/null +++ b/gameserver/src/main/java/brainwine/gameserver/msgpack/templates/PrefabTemplate.java @@ -0,0 +1,50 @@ +package brainwine.gameserver.msgpack.templates; + +import java.io.IOException; + +import org.msgpack.MessageTypeException; +import org.msgpack.packer.Packer; +import org.msgpack.template.AbstractTemplate; +import org.msgpack.unpacker.Unpacker; + +import brainwine.gameserver.prefab.Prefab; +import brainwine.gameserver.zone.Block; + +public class PrefabTemplate extends AbstractTemplate { + + @Override + public void write(Packer packer, Prefab prefab, boolean required) throws IOException { + if(prefab == null) { + if(required) { + throw new MessageTypeException("Attempted to write null"); + } + + packer.writeNil(); + return; + } + + packer.write(prefab.getWidth()); + packer.write(prefab.getHeight()); + packer.write(prefab.getBlocks()); + } + + @Override + public Prefab read(Unpacker unpacker, Prefab to, boolean required) throws IOException { + if(!required && unpacker.trySkipNil()) { + return null; + } + + int width = unpacker.readInt(); + int height = unpacker.readInt(); + Block[] blocks = unpacker.read(Block[].class); + + if(to != null) { + to.setWidth(width); + to.setHeight(height); + to.setBlocks(blocks); + return to; + } + + return new Prefab(width, height, blocks); + } +} diff --git a/gameserver/src/main/java/brainwine/gameserver/prefab/CorrespondingReplacement.java b/gameserver/src/main/java/brainwine/gameserver/prefab/CorrespondingReplacement.java new file mode 100644 index 0000000..1d838c2 --- /dev/null +++ b/gameserver/src/main/java/brainwine/gameserver/prefab/CorrespondingReplacement.java @@ -0,0 +1,31 @@ +package brainwine.gameserver.prefab; + +import java.util.HashMap; +import java.util.Map; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +import brainwine.gameserver.item.Item; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class CorrespondingReplacement { + + @JsonProperty("key") + private Item key; + + @JsonProperty("values") + private Map values = new HashMap<>(); + + @JsonCreator + private CorrespondingReplacement() {} + + public Item getKey() { + return key; + } + + public Map getValues() { + return values; + } +} diff --git a/gameserver/src/main/java/brainwine/gameserver/prefab/Prefab.java b/gameserver/src/main/java/brainwine/gameserver/prefab/Prefab.java new file mode 100644 index 0000000..989ad6b --- /dev/null +++ b/gameserver/src/main/java/brainwine/gameserver/prefab/Prefab.java @@ -0,0 +1,132 @@ +package brainwine.gameserver.prefab; + +import java.util.HashMap; +import java.util.Map; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +import brainwine.gameserver.GameServer; +import brainwine.gameserver.item.Item; +import brainwine.gameserver.util.WeightedList; +import brainwine.gameserver.zone.Block; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class Prefab { + + @JsonProperty("dungeon") + private boolean dungeon; + + @JsonProperty("ruin") + private boolean ruin; + + @JsonProperty("loot") + private boolean loot; + + @JsonProperty("decay") + private boolean decay; + + @JsonProperty("mirrorable") + private boolean mirrorable; + + @JsonProperty("replace") + private Map> replacements = new HashMap<>(); + + @JsonProperty("corresponding_replace") + private Map correspondingReplacements = new HashMap<>(); + + @JsonProperty("metadata") + private Map> metadata = new HashMap<>(); + + @JsonIgnore + private int width; + + @JsonIgnore + private int height; + + @JsonIgnore + private Block[] blocks; + + @JsonCreator + private Prefab() {} + + @JsonIgnore + public Prefab(int width, int height, Block[] blocks) { + this(width, height, blocks, new HashMap<>()); + } + + @JsonIgnore + public Prefab(int width, int height, Block[] blocks, Map> metadata) { + this.width = width; + this.height = height; + this.blocks = blocks; + this.metadata = metadata; + } + + @JsonCreator + private static Prefab fromName(String name) { + return GameServer.getInstance().getPrefabManager().getPrefab(name); + } + + public boolean isDungeon() { + return dungeon; + } + + public boolean isRuin() { + return ruin; + } + + public boolean hasLoot() { + return loot; + } + + public boolean hasDecay() { + return decay; + } + + public boolean isMirrorable() { + return mirrorable; + } + + public Map getMetadata(int index) { + return metadata.get(index); + } + + public Map> getMetadata() { + return metadata; + } + + public Map> getReplacements() { + return replacements; + } + + public Map getCorrespondingReplacements() { + return correspondingReplacements; + } + + public void setWidth(int width) { + this.width = width; + } + + public int getWidth() { + return width; + } + + public void setHeight(int height) { + this.height = height; + } + + public int getHeight() { + return height; + } + + public void setBlocks(Block[] blocks) { + this.blocks = blocks; + } + + public Block[] getBlocks() { + return blocks; + } +} diff --git a/gameserver/src/main/java/brainwine/gameserver/prefab/PrefabManager.java b/gameserver/src/main/java/brainwine/gameserver/prefab/PrefabManager.java new file mode 100644 index 0000000..f810b1b --- /dev/null +++ b/gameserver/src/main/java/brainwine/gameserver/prefab/PrefabManager.java @@ -0,0 +1,98 @@ +package brainwine.gameserver.prefab; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.msgpack.unpacker.BufferUnpacker; +import org.reflections.Reflections; +import org.reflections.scanners.ResourcesScanner; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import brainwine.gameserver.msgpack.MessagePackHelper; + +public class PrefabManager { + + private static final Logger logger = LogManager.getLogger(); + private final File dataDir = new File("prefabs"); + private final ObjectMapper mapper = new ObjectMapper(); + private final Map prefabs = new HashMap<>(); + + public PrefabManager() { + loadPrefabs(); + } + + private void loadPrefabs() { + logger.info("Loading prefabs ..."); + + if(!dataDir.exists()) { + logger.info("Copying default prefabs ..."); + dataDir.mkdirs(); + Reflections reflections = new Reflections("prefabs", new ResourcesScanner()); + Set fileNames = reflections.getResources(x -> true); + + for(String fileName : fileNames) { + File outputFile = new File(fileName); + outputFile.getParentFile().mkdirs(); + + try { + Files.copy(PrefabManager.class.getResourceAsStream(String.format("/%s", fileName)), outputFile.toPath()); + } catch (IOException e) { + logger.error("Could not copy default prefabs", e); + } + } + } + + File[] files = dataDir.listFiles(); + + for(File file : files) { + if(file.isDirectory()) { + loadPrefab(file); + } + } + + logger.info("Successfully loaded {} prefab(s)", prefabs.size()); + } + + private void loadPrefab(File file) { + String name = file.getName(); + File configFile = new File(file, "config.json"); + + try { + Prefab prefab = mapper.readValue(configFile, Prefab.class); + BufferUnpacker unpacker = MessagePackHelper.readFile(new File(file, "blocks.cmp")); + unpacker.read(prefab); + unpacker.close(); + prefabs.put(name, prefab); + } catch(Exception e) { + logger.error("Could not load prefab {}:", name, e); + } + } + + public void registerPrefab(String name, Prefab structure) throws Exception { + if(prefabs.containsKey(name)) { + logger.warn("Duplicate prefab name: {}", name); + return; + } + + savePrefab(name, structure); + prefabs.put(name, structure); + } + + private void savePrefab(String name, Prefab structure) throws Exception { + File outputDir = new File(dataDir, name); + outputDir.mkdirs(); + MessagePackHelper.writeToFile(new File(outputDir, "blocks.cmp"), structure); + mapper.writerWithDefaultPrettyPrinter().writeValue(new File(outputDir, "config.json"), structure); + } + + public Prefab getPrefab(String name) { + return prefabs.get(name); + } +} diff --git a/gameserver/src/main/java/brainwine/gameserver/server/requests/BlockUseRequest.java b/gameserver/src/main/java/brainwine/gameserver/server/requests/BlockUseRequest.java index 51f3e35..a89e985 100644 --- a/gameserver/src/main/java/brainwine/gameserver/server/requests/BlockUseRequest.java +++ b/gameserver/src/main/java/brainwine/gameserver/server/requests/BlockUseRequest.java @@ -1,18 +1,25 @@ package brainwine.gameserver.server.requests; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Map.Entry; +import brainwine.gameserver.GameServer; +import brainwine.gameserver.entity.player.NotificationType; import brainwine.gameserver.entity.player.Player; import brainwine.gameserver.item.Item; import brainwine.gameserver.item.ItemUseType; import brainwine.gameserver.item.Layer; +import brainwine.gameserver.loot.Loot; +import brainwine.gameserver.loot.LootManager; import brainwine.gameserver.msgpack.models.BlockUseData; import brainwine.gameserver.server.OptionalField; import brainwine.gameserver.server.PlayerRequest; import brainwine.gameserver.util.MapHelper; import brainwine.gameserver.zone.Block; +import brainwine.gameserver.zone.MetaBlock; import brainwine.gameserver.zone.Zone; @SuppressWarnings("unchecked") @@ -33,77 +40,140 @@ public class BlockUseRequest extends PlayerRequest { return; } + Object[] data = this.data == null ? null : this.data.getData(); Block block = zone.getBlock(x, y); + MetaBlock metaBlock = zone.getMetaBlock(x, y); Item item = block.getItem(layer); int mod = block.getMod(layer); - if(data == null) { - if(item.hasUse(ItemUseType.CHANGE)) { - zone.updateBlock(x, y, layer, item, mod == 0 ? 1 : 0, player); - } - } else { - Object[] data = this.data.getData(); - item.getUses().forEach((k, v) -> { - switch(k) { - case DIALOG: - case CREATE_DIALOG: - // TODO rework dialog system and clean this mess up - Map config = (Map)v; - String target = MapHelper.getString(config, "target"); + for(Entry entry : item.getUses().entrySet()) { + ItemUseType use = entry.getKey(); + Object value = entry.getValue(); + + switch(use) { + case DIALOG: + case CREATE_DIALOG: + if(metaBlock != null && player.getDocumentId().equals(metaBlock.getOwner()) && data != null && value instanceof Map) { + Map config = (Map)value; + String target = MapHelper.getString(config, "target", "none"); switch(target) { case "meta": Map metadata = new HashMap<>(); List> sections = MapHelper.getList(config, "sections"); - int i = 0; - for(Map section : sections) { - metadata.put(MapHelper.getString(section, "input.key"), data[i++]); + if(sections != null && data.length == sections.size()) { + for(int i = 0; i < sections.size(); i++) { + Map section = sections.get(i); + String key = MapHelper.getString(section, "input.key"); + + if(key != null) { + metadata.put(key, data[i]); + } else if(MapHelper.getBoolean(section, "input.mod")) { + List options = MapHelper.getList(section, "input.options"); + + if(options != null) { + mod = options.indexOf(data[i]); + mod = mod == -1 ? 0 : mod; + mod *= MapHelper.getInt(section, "input.mod_multiple", 1); + zone.updateBlock(x, y, layer, item, mod, player); + } + } + } + } + + // TODO find out what this is for + if(use == ItemUseType.CREATE_DIALOG) { + metadata.put("cd", true); } zone.setMetaBlock(x, y, item, player, metadata); break; - default: - break; } - break; - case TELEPORT: - if(mod == 1 && data.length == 2 && data[0] instanceof Integer && data[1] instanceof Integer) { - int tX = (int)data[0]; - int tY = (int)data[1]; - Block targetBlock = zone.getBlock(tX, tY); + } + break; + case CHANGE: + zone.updateBlock(x, y, layer, item, mod == 0 ? 1 : 0, player); + break; + case CONTAINER: + if(metaBlock != null) { + Map metadata = metaBlock.getMetadata(); + String specialItem = MapHelper.getString(metadata, "$"); + + if(specialItem != null) { + String dungeonId = MapHelper.getString(metadata, "@"); - if(targetBlock != null) { - Item targetItem = targetBlock.getFrontItem(); + if(dungeonId != null && item.hasUse(ItemUseType.FIELDABLE) && zone.isDungeonIntact(dungeonId)) { + player.alert("This container is secured by protectors in the area."); + break; + } + + if(specialItem.equals("?")) { + metadata.remove("$"); + LootManager lootManager = GameServer.getInstance().getLootManager(); + Loot loot = lootManager.getRandomLoot(15, zone.getBiome(), item.getLootCategories()); // TODO level - if(targetItem.hasUse(ItemUseType.TELEPORT, ItemUseType.ZONE_TELEPORT)) { - player.teleport(tX + 1, tY); + if(loot == null) { + player.alert("How quaint, this container is empty!"); + } else { + player.awardLoot(loot, item.getLootGraphic()); + } + } else { + player.alert("Sorry, this container can't be looted right now."); + } + + if(mod != 0) { + zone.updateBlock(x, y, Layer.FRONT, item, 0); + } + } + } + break; + case TELEPORT: + if(data != null && mod == 1 && data.length == 2 && data[0] instanceof Integer && data[1] instanceof Integer) { + int tX = (int)data[0]; + int tY = (int)data[1]; + MetaBlock target = zone.getMetaBlock(tX, tY); + + if(target != null && target.getItem().hasUse(ItemUseType.TELEPORT, ItemUseType.ZONE_TELEPORT)) { + player.teleport(tX + 1, tY); + } + } else if(mod == 0) { + zone.updateBlock(x, y, layer, item, 1); + player.notify("You repaired a teleporter!", NotificationType.ACCOMPLISHMENT); + player.notifyPeers(String.format("%s repaired a teleporter.", player.getName()), NotificationType.SYSTEM); + } + break; + case SWITCH: + if(data == null) { + if(metaBlock != null) { + // TODO timed switches + + zone.updateBlock(x, y, layer, item, mod % 2 == 0 ? mod + 1 : mod - 1, player, null); + Map metadata = metaBlock.getMetadata(); + List> positions = MapHelper.getList(metadata, ">", Collections.emptyList()); + + for(List position : positions) { + int sX = position.get(0); + int sY = position.get(1); + Block target = zone.getBlock(sX, sY); + + if(target != null) { + Item switchedItem = target.getFrontItem(); + + if(switchedItem.hasUse(ItemUseType.SWITCHED)) { + if(!(item.getUse(ItemUseType.SWITCHED) instanceof String)) { + int switchedMod = target.getFrontMod(); + zone.updateBlock(sX, sY, Layer.FRONT, switchedItem, switchedMod % 2 == 0 ? switchedMod + 1 : switchedMod - 1, null); + } + } } } } - break; - default: - break; } - }); - } - - /* - else if(data.hasMetadata()) { - // TODO - Item item = zone.getBlock(x, y).getItem(layer); - Map metadata = new HashMap<>(); - metadata.putAll(data.getMetadata()); - zone.setMetaBlock(x, y, item, player, metadata); - } else if(data.hasPosition()) { - int[] position = data.getPosition(); - int tX = position[0]; - int tY = position[1]; - Item item = zone.getBlock(tX, tY).getItem(layer); - - if(item.hasUse(ItemUseType.TELEPORT, ItemUseType.ZONE_TELEPORT)) { - player.teleport(tX + 1, tY); + break; + default: + break; } - }*/ + } } } diff --git a/gameserver/src/main/java/brainwine/gameserver/util/Vector2i.java b/gameserver/src/main/java/brainwine/gameserver/util/Vector2i.java new file mode 100644 index 0000000..b3a423a --- /dev/null +++ b/gameserver/src/main/java/brainwine/gameserver/util/Vector2i.java @@ -0,0 +1,43 @@ +package brainwine.gameserver.util; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class Vector2i { + + private int x; + private int y; + + public Vector2i(int x, int y) { + this.x = x; + this.y = y; + } + + @JsonCreator + private Vector2i(int[] positions) { + if(positions.length == 2) { + x = positions[0]; + y = positions[1]; + } else { + x = 1; + y = 1; + } + } + + public void setX(int x) { + this.x = x; + } + + public int getX() { + return x; + } + + public void setY(int y) { + this.y = y; + } + + public int getY() { + return y; + } +} diff --git a/gameserver/src/main/java/brainwine/gameserver/zone/Zone.java b/gameserver/src/main/java/brainwine/gameserver/zone/Zone.java index cb1587d..606f5ff 100644 --- a/gameserver/src/main/java/brainwine/gameserver/zone/Zone.java +++ b/gameserver/src/main/java/brainwine/gameserver/zone/Zone.java @@ -14,6 +14,7 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Queue; +import java.util.Random; import java.util.Set; import java.util.UUID; import java.util.function.Predicate; @@ -37,7 +38,9 @@ import brainwine.gameserver.item.ItemRegistry; import brainwine.gameserver.item.ItemUseType; import brainwine.gameserver.item.Layer; import brainwine.gameserver.item.MetaType; +import brainwine.gameserver.item.ModType; import brainwine.gameserver.msgpack.MessagePackHelper; +import brainwine.gameserver.prefab.Prefab; import brainwine.gameserver.server.Message; import brainwine.gameserver.server.messages.BlockChangeMessage; import brainwine.gameserver.server.messages.BlockMetaMessage; @@ -248,6 +251,174 @@ public class Zone { return false; } + public Prefab chop(int x, int y, int width, int height) { + if(!areCoordinatesInBounds(x, y) || !areCoordinatesInBounds(x + width, y + height)) { + return null; + } + + Block[] blocks = new Block[width * height]; + Map> metadata = new HashMap<>(); + + for(int i = 0; i < width; i++) { + for(int j = 0; j < height; j++) { + int index = j * width + i; + Block block = getBlock(x + i, y + j); + blocks[index] = new Block(block.getBaseItem(), block.getBackItem(), block.getBackMod(), block.getFrontItem(), block.getFrontMod(), block.getLiquidItem(), block.getLiquidMod()); + MetaBlock metaBlock = metaBlocks.get(getBlockIndex(x + i, j + y)); + + if(metaBlock != null) { + Map data = MapHelper.copy(metaBlock.getMetadata()); + + if(!data.isEmpty()) { + List> positions = MapHelper.getList(data, ">", Collections.emptyList()); + + for(List position : positions) { + position.set(0, position.get(0) - x); + position.set(1, position.get(1) - y); + } + + metadata.put(index, data); + } + } + } + } + + return new Prefab(width, height, blocks, metadata); + } + + public void placePrefab(Prefab prefab, int x, int y) { + placePrefab(prefab, x, y, new Random()); + } + + public void placePrefab(Prefab prefab, int x, int y, Random random) { + int width = prefab.getWidth(); + int height = prefab.getHeight(); + Block[] blocks = prefab.getBlocks(); + int guardBlocks = 0; + String dungeonId = prefab.isDungeon() ? UUID.randomUUID().toString() : null; + boolean decay = prefab.hasDecay(); + boolean mirrored = prefab.isMirrorable() && random.nextBoolean(); + Map replacedItems = new HashMap<>(); + + // Replacements + prefab.getReplacements().forEach((item, list) -> { + replacedItems.put(item, list.next(random)); + }); + + // Corresponding replacements + prefab.getCorrespondingReplacements().forEach((item, data) -> { + Item keyReplacement = replacedItems.get(data.getKey()); + + if(keyReplacement != null) { + Item replacement = data.getValues().get(keyReplacement); + + if(replacement != null) { + replacedItems.put(item, replacement); + } + } + }); + + for(int i = 0; i < width; i++) { + for(int j = 0; j < height; j++) { + int index = j * width + (mirrored ? width - 1 - i : i); + Block block = blocks[index]; + Item baseItem = replacedItems.getOrDefault(block.getBaseItem(), block.getBaseItem()); + Item backItem = replacedItems.getOrDefault(block.getBackItem(), block.getBackItem()); + Item frontItem = replacedItems.getOrDefault(block.getFrontItem(), block.getFrontItem()); + Item liquidItem = replacedItems.getOrDefault(block.getLiquidItem(), block.getLiquidItem()); + int backMod = block.getBackMod(); + int frontMod = block.getFrontMod(); + int liquidMod = block.getLiquidMod(); + + // Update base item if it isn't empty + if(!baseItem.isAir()) { + updateBlock(x + i, y + j, Layer.BASE, baseItem); + } + + // Update back item if it isn't empty + if(!backItem.isAir()) { + // Apply decay to back block + if(decay && backItem.getMod() == ModType.DECAY && random.nextBoolean()) { + backMod = random.nextInt(4) + 1; + } + + updateBlock(x + i, y + j, Layer.BACK, backItem, backMod); + } + + // Update front item if either the back, front or liquid item isn't empty + if(!backItem.isAir() || !frontItem.isAir() || !liquidItem.isAir()) { + // Apply mods + if(mirrored && frontItem.getMod() == ModType.ROTATION) { + // If rotation == mirror, swap mods 0 and 4, otherwise 1 and 3 + if(frontItem.isMirrorable()) { + frontMod = frontMod == 0 ? 4 : frontMod == 4 ? 0 : frontMod; + } else { + frontMod = frontMod == 1 ? 3 : frontMod == 3 ? 1 : frontMod; + } + } else if(decay && frontItem.getMod() == ModType.DECAY && random.nextBoolean()) { + frontMod = random.nextInt(4) + 1; + } + + int offset = mirrored ? -(frontItem.getBlockWidth() - 1) : 0; + + // Clear the block it would normally occupy + if(offset != 0) { + updateBlock(x + i, y + j, Layer.FRONT, 0); + } + + Map metadata = prefab.getMetadata(index); + metadata = metadata == null ? new HashMap<>() : MapHelper.copy(metadata); + + // Add dungeon id to guard blocks and containers, and increment guard block count if applicable + if(dungeonId != null && frontItem.hasUse(ItemUseType.CONTAINER, ItemUseType.GUARD)) { + metadata.put("@", dungeonId); + + if(frontItem.hasUse(ItemUseType.GUARD)) { + guardBlocks++; + } + } + + // Determine lootability for containers + if(prefab.hasLoot() && frontItem.hasUse(ItemUseType.CONTAINER)) { + // If the container is a "high end" container, make it lootable. Otherwise 10% chance. + if(frontItem.hasUse(ItemUseType.FIELDABLE) || random.nextDouble() <= 0.1) { + metadata.put("$", "?"); + frontMod = 1; + } + } + + // Block is linked, offset positions + if(metadata.containsKey(">")) { + List> positions = MapHelper.getList(metadata, ">", Collections.emptyList()); + + for(List position : positions) { + int pX = position.get(0); + int pY = position.get(1); + + // Create an offset in case the block is bigger than 1x1 + Item linkedItem = blocks[pY * width + pX].getFrontItem(); + linkedItem = replacedItems.getOrDefault(linkedItem, linkedItem); + int pOffset = -(linkedItem.getBlockWidth() - 1); + position.set(0, (mirrored ? width - 1 - pX + pOffset : pX) + x); + position.set(1, position.get(1) + y); + } + } + + updateBlock(x + i + offset, y + j, Layer.FRONT, frontItem, frontMod, null, metadata); + } + + // Update liquid item if it isn't empty + if(!liquidItem.isAir()) { + updateBlock(x + i, y + j, Layer.LIQUID, liquidItem, liquidMod); + } + } + } + + if(guardBlocks > 0) { + dungeons.put(dungeonId, guardBlocks); + } + } + private void indexDungeons() { List guardBlocks = getMetaBlocksWithUse(ItemUseType.GUARD); diff --git a/gameserver/src/main/java/brainwine/gameserver/zone/gen/GeneratorConfig.java b/gameserver/src/main/java/brainwine/gameserver/zone/gen/GeneratorConfig.java index 993890c..861f38b 100644 --- a/gameserver/src/main/java/brainwine/gameserver/zone/gen/GeneratorConfig.java +++ b/gameserver/src/main/java/brainwine/gameserver/zone/gen/GeneratorConfig.java @@ -10,6 +10,8 @@ import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import brainwine.gameserver.item.Item; +import brainwine.gameserver.prefab.Prefab; +import brainwine.gameserver.util.Vector2i; import brainwine.gameserver.util.WeightedList; import brainwine.gameserver.zone.gen.models.BaseResourceType; import brainwine.gameserver.zone.gen.models.Deposit; @@ -28,6 +30,21 @@ public class GeneratorConfig { @JsonProperty("speleothems") private Item[] speleothems = {}; + @JsonProperty("unique_structures") + private Prefab[] uniqueStructures = {}; + + @JsonProperty("dungeons") + private WeightedList dungeons = new WeightedList<>(); + + @JsonProperty("spawn_towers") + private WeightedList spawnTowers = new WeightedList<>(); + + @JsonProperty("dungeon_region") + private Vector2i dungeonRegion = new Vector2i(80, 64); + + @JsonProperty("dungeon_chance") + private double dungeonRate = 0.25; + @JsonProperty("stone_variants") private WeightedList stoneVariants = new WeightedList<>(); @@ -53,6 +70,26 @@ public class GeneratorConfig { return speleothems; } + public Prefab[] getUniqueStructures() { + return uniqueStructures; + } + + public WeightedList getDungeons() { + return dungeons; + } + + public WeightedList getSpawnTowers() { + return spawnTowers; + } + + public Vector2i getDungeonRegion() { + return dungeonRegion; + } + + public double getDungeonRate() { + return dungeonRate; + } + public WeightedList getStoneVariants() { return stoneVariants; } diff --git a/gameserver/src/main/java/brainwine/gameserver/zone/gen/GeneratorContext.java b/gameserver/src/main/java/brainwine/gameserver/zone/gen/GeneratorContext.java index 5b1acdc..e09f54b 100644 --- a/gameserver/src/main/java/brainwine/gameserver/zone/gen/GeneratorContext.java +++ b/gameserver/src/main/java/brainwine/gameserver/zone/gen/GeneratorContext.java @@ -1,18 +1,24 @@ package brainwine.gameserver.zone.gen; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.Map.Entry; import java.util.Random; import brainwine.gameserver.item.Item; import brainwine.gameserver.item.Layer; +import brainwine.gameserver.prefab.Prefab; import brainwine.gameserver.zone.Chunk; import brainwine.gameserver.zone.Zone; +import brainwine.gameserver.zone.gen.models.BlockPosition; import brainwine.gameserver.zone.gen.models.Cave; public class GeneratorContext { private final List caves = new ArrayList<>(); + private final Map prefabs = new HashMap<>(); private final Zone zone; private final Random random; private final int seed; @@ -39,6 +45,28 @@ public class GeneratorContext { return caves; } + public void placePrefab(Prefab prefab, int x, int y) { + if(!willPrefabOverlap(prefab, x, y)) { + zone.placePrefab(prefab, x, y, random); + prefabs.put(new BlockPosition(x, y), prefab); + } + } + + public boolean willPrefabOverlap(Prefab prefab, int x, int y) { + for(Entry entry : prefabs.entrySet()) { + BlockPosition position = entry.getKey(); + Prefab other = entry.getValue(); + int x2 = position.getX(); + int y2 = position.getY(); + + if(x + prefab.getWidth() >= x2 && x <= x2 + other.getWidth() && y + prefab.getHeight() >= y2 && y <= y2 + other.getHeight()) { + return true; + } + } + + return false; + } + public void updateBlock(int x, int y, Layer layer, int item) { updateBlock(x, y, layer, item, 0); } diff --git a/gameserver/src/main/java/brainwine/gameserver/zone/gen/StructureGenerator.java b/gameserver/src/main/java/brainwine/gameserver/zone/gen/StructureGenerator.java new file mode 100644 index 0000000..bb7943b --- /dev/null +++ b/gameserver/src/main/java/brainwine/gameserver/zone/gen/StructureGenerator.java @@ -0,0 +1,87 @@ +package brainwine.gameserver.zone.gen; + +import brainwine.gameserver.item.Layer; +import brainwine.gameserver.prefab.Prefab; +import brainwine.gameserver.util.Vector2i; +import brainwine.gameserver.util.WeightedList; +import brainwine.gameserver.zone.Block; + +public class StructureGenerator implements GeneratorTask { + + private final Prefab[] uniqueStructures; + private final WeightedList dungeons; + private final WeightedList spawnTowers; + private final Vector2i dungeonRegion; + private final double dungeonRate; + + public StructureGenerator(GeneratorConfig config) { + uniqueStructures = config.getUniqueStructures(); + dungeons = config.getDungeons(); + spawnTowers = config.getSpawnTowers(); + dungeonRegion = config.getDungeonRegion(); + dungeonRate = config.getDungeonRate(); + } + + @Override + public void generate(GeneratorContext ctx) { + int width = ctx.getWidth(); + int height = ctx.getHeight(); + + for(Prefab structure : uniqueStructures) { + int x = ctx.nextInt(width - 2) + 1; + int minY = ctx.getZone().getSurface()[x]; + int y = ctx.nextInt(height - minY - 2) + minY; + ctx.placePrefab(structure, x, y); + } + + if(!dungeons.isEmpty()) { + for(int x = 0; x < width; x += dungeonRegion.getX()) { + for(int y = 0; y < height; y += dungeonRegion.getY()) { + if(ctx.nextDouble() <= dungeonRate) { + Prefab dungeon = dungeons.next(ctx.getRandom()); + int prefabWidth = dungeon.getWidth(); + int prefabHeight = dungeon.getHeight(); + + if(ctx.isUnderground(x, y) && ctx.isUnderground(x + prefabWidth, y)) { + int placeX = x + (prefabWidth >= dungeonRegion.getX() ? x : ctx.nextInt(dungeonRegion.getX() - prefabWidth)); + placeX = Math.max(1, Math.min(placeX, width - prefabWidth - 1)); + int placeY = y + (prefabHeight >= dungeonRegion.getY() ? y : ctx.nextInt(dungeonRegion.getY() - prefabHeight)); + placeY = Math.max(1, Math.min(placeY, height - prefabHeight - 2)); + ctx.placePrefab(dungeon, placeX, placeY); + } + } + } + } + } + + placeRandomSpawnTower(ctx, (int)(width * 0.2)); + placeRandomSpawnTower(ctx, (int)(width * 0.5)); + placeRandomSpawnTower(ctx, (int)(width * 0.8)); + } + + private void placeRandomSpawnTower(GeneratorContext ctx, int x) { + int surface = ctx.getZone().getSurface()[x]; + + if(!spawnTowers.isEmpty()) { + Prefab spawnTower = spawnTowers.next(ctx.getRandom()); + int height = spawnTower.getHeight(); + int y = surface - height; + ctx.placePrefab(spawnTower, x, y); + generateFoundation(ctx, x, y + height, spawnTower.getWidth()); + } else { + ctx.updateBlock(x, surface - 1, Layer.FRONT, 891, 0); + } + } + + private void generateFoundation(GeneratorContext ctx, int x, int y, int width) { + for(int i = x; i < x + width; i++) { + int j = y; + Block block = null; + + while((block = ctx.getZone().getBlock(i, j)) != null && block.getBaseItem().isAir() && !block.getFrontItem().isWhole()) { + ctx.updateBlock(i, j, Layer.BACK, 258); + j++; + } + } + } +} diff --git a/gameserver/src/main/java/brainwine/gameserver/zone/gen/ZoneGenerator.java b/gameserver/src/main/java/brainwine/gameserver/zone/gen/ZoneGenerator.java index 29c42f9..61c8413 100644 --- a/gameserver/src/main/java/brainwine/gameserver/zone/gen/ZoneGenerator.java +++ b/gameserver/src/main/java/brainwine/gameserver/zone/gen/ZoneGenerator.java @@ -7,6 +7,7 @@ public class ZoneGenerator { private final GeneratorTask terrainGenerator; private final GeneratorTask caveGenerator; private final GeneratorTask decorGenerator; + private final GeneratorTask structureGenerator; public ZoneGenerator() { this(new GeneratorConfig()); @@ -16,6 +17,7 @@ public class ZoneGenerator { terrainGenerator = new TerrainGenerator(config); caveGenerator = new CaveGenerator(config); decorGenerator = new DecorGenerator(config); + structureGenerator = new StructureGenerator(config); } public void generate(GeneratorContext ctx) { @@ -25,7 +27,7 @@ public class ZoneGenerator { terrainGenerator.generate(ctx); caveGenerator.generate(ctx); decorGenerator.generate(ctx); - ctx.updateBlock(width / 2, ctx.getZone().getSurface()[width / 2] - 1, Layer.FRONT, 891, 0); // TODO structures + structureGenerator.generate(ctx); for(int x = 0; x < width; x++) { ctx.updateBlock(x, height - 1, Layer.FRONT, 666, 0); diff --git a/gameserver/src/main/resources/generators.json b/gameserver/src/main/resources/generators.json index 610d6a8..1e4923c 100644 --- a/gameserver/src/main/resources/generators.json +++ b/gameserver/src/main/resources/generators.json @@ -15,6 +15,34 @@ "sandstone": 4, "limestone": 2 }, + "unique_structures": [ + "paint_bunker", + "head_bunker" + ], + "dungeons": [ + "dungeon_large_1", + "dungeon_large_2", + "dungeon_medium_1", + "dungeon_medium_2", + "dungeon_medium_3", + "dungeon_medium_4", + "dungeon_medium_5", + "dungeon_medium_6", + "dungeon_medium_7", + "dungeon_medium_8", + "dungeon_medium_9", + "dungeon_medium_10", + "dungeon_small_1", + "dungeon_small_2", + "dungeon_small_3", + "dungeon_small_4" + ], + "spawn_towers": [ + "plain_spawn_tower_1", + "plain_spawn_tower_2", + "plain_spawn_tower_3", + "plain_spawn_tower_4" + ], "base_resources": { "clay": { "per": 1200 @@ -197,6 +225,29 @@ "default": 6, "limestone": 1 }, + "unique_structures": [ + "paint_bunker", + "head_bunker" + ], + "dungeons": [ + "dungeon_large_1", + "dungeon_large_2", + "dungeon_medium_1", + "dungeon_medium_2", + "dungeon_medium_3", + "dungeon_medium_4", + "dungeon_medium_5", + "dungeon_medium_6", + "dungeon_medium_7", + "dungeon_medium_8", + "dungeon_medium_9", + "dungeon_medium_10", + "dungeon_small_1", + "dungeon_small_2", + "dungeon_small_3", + "dungeon_small_4" + ], + "dungeon_chance": 0.333, "base_resources": { "clay": { "per": 1200 @@ -362,6 +413,29 @@ "ground/stalagmite-4", "ground/stalagmite-5" ], + "unique_structures": [ + "paint_bunker", + "head_bunker" + ], + "dungeons": [ + "dungeon_large_1", + "dungeon_large_2", + "dungeon_medium_1", + "dungeon_medium_2", + "dungeon_medium_3", + "dungeon_medium_4", + "dungeon_medium_5", + "dungeon_medium_6", + "dungeon_medium_7", + "dungeon_medium_8", + "dungeon_medium_9", + "dungeon_medium_10", + "dungeon_small_1", + "dungeon_small_2", + "dungeon_small_3", + "dungeon_small_4" + ], + "dungeon_chance": 0.375, "base_resources": { "clay": { "per": 1500 @@ -489,6 +563,29 @@ "default": 6, "limestone": 1 }, + "unique_structures": [ + "paint_bunker", + "head_bunker" + ], + "dungeons": [ + "dungeon_large_1", + "dungeon_large_2", + "dungeon_medium_1", + "dungeon_medium_2", + "dungeon_medium_3", + "dungeon_medium_4", + "dungeon_medium_5", + "dungeon_medium_6", + "dungeon_medium_7", + "dungeon_medium_8", + "dungeon_medium_9", + "dungeon_medium_10", + "dungeon_small_1", + "dungeon_small_2", + "dungeon_small_3", + "dungeon_small_4" + ], + "dungeon_chance": 0.4, "base_resources": { "rocks": { "per": 200 @@ -608,6 +705,29 @@ "default": 3, "sandstone": 1 }, + "unique_structures": [ + "paint_bunker", + "head_bunker" + ], + "dungeons": [ + "dungeon_large_1", + "dungeon_large_2", + "dungeon_medium_1", + "dungeon_medium_2", + "dungeon_medium_3", + "dungeon_medium_4", + "dungeon_medium_5", + "dungeon_medium_6", + "dungeon_medium_7", + "dungeon_medium_8", + "dungeon_medium_9", + "dungeon_medium_10", + "dungeon_small_1", + "dungeon_small_2", + "dungeon_small_3", + "dungeon_small_4" + ], + "dungeon_chance": 0.333, "base_resources": { "clay": { "per": 800 @@ -748,6 +868,30 @@ "default": 17, "limestone": 4 }, + "unique_structures": [ + "paint_bunker", + "head_bunker" + ], + "dungeons": [ + "dungeon_large_1", + "dungeon_large_2", + "dungeon_medium_1", + "dungeon_medium_2", + "dungeon_medium_3", + "dungeon_medium_4", + "dungeon_medium_5", + "dungeon_medium_6", + "dungeon_medium_7", + "dungeon_medium_8", + "dungeon_medium_9", + "dungeon_medium_10", + "dungeon_small_1", + "dungeon_small_2", + "dungeon_small_3", + "dungeon_small_4" + ], + "dungeon_region": [81, 85], + "dungeon_chance": 0.4, "base_resources": { "clay": { "per": 1200 @@ -869,6 +1013,30 @@ "ground/stalagmite-4", "ground/stalagmite-5" ], + "unique_structures": [ + "paint_bunker", + "head_bunker" + ], + "dungeons": [ + "dungeon_large_1", + "dungeon_large_2", + "dungeon_medium_1", + "dungeon_medium_2", + "dungeon_medium_3", + "dungeon_medium_4", + "dungeon_medium_5", + "dungeon_medium_6", + "dungeon_medium_7", + "dungeon_medium_8", + "dungeon_medium_9", + "dungeon_medium_10", + "dungeon_small_1", + "dungeon_small_2", + "dungeon_small_3", + "dungeon_small_4" + ], + "dungeon_region": [81, 81], + "dungeon_chance": 0.333, "base_resources": { "rocks": { "per": 100 diff --git a/gameserver/src/main/resources/prefabs/dungeon_large_1/blocks.cmp b/gameserver/src/main/resources/prefabs/dungeon_large_1/blocks.cmp new file mode 100644 index 0000000000000000000000000000000000000000..f550d91cca554ee59e932e1665b629f1e954fdd1 GIT binary patch literal 835 zcmV-J1HAlroYk2!VKjH#KwqMQ`mo3v0Wb;(s+)b5G?dIOK zk?x|ZagG^*$KjR^ z-YJa}W|7^SG|frebdNkDxEEt@eU3ean3Gy~%T~k>4j0-|hA708KQa6CO?%OPWe((e z?w>2<6oQsj`23wj^KqO*h%FmzFNrl!uqgH?c46B!cEXOtIS6^FE#rLGC=9^l(g_9? z7Us-NY{C;lVggXgzZ8cEQm|LA*Sv7~C2*SE5Xs!jr2 ziY7wv3T=+9L^xEJci?KNvOOfmUYs>b5Z3@Ai7A@lJClamTgl_?QLo#^*t9W0o1(d7 z`XgcS?d zt-jFo?)hNG4=N>%=XDM5nKGbHwqk5@@79-Mqd%DS4tV+`>XX8+4Ty-pH$yq2i$|yg4NQ!uD%u21KSnmm`}z4M|}JPI+&fy zkam4%@h8jJYxKqTia|C4!>LK^AXJz`Dx^IJ(sC_Q>Q*%-c_8n~V3o}Sw0!R~ems8} zYV$^fos}7KfxSXO+jadtC5CafXKYJ(D0_KP5#Ia+ssUEf{Traj$u)~odR7%e>Vb2f z+dw4@i_O2%m8a}|%7`^3t<}=^tm+>NL@1iyWp%1hWm": [[ 49, 7 ]] + }, + "2333": { + "cd": true, + "m": "", + ">": [[ 46, 43 ]] + }, + "1977": { + "cd": true, + "t": "10", + "m": "", + ">": [[ 11, 39 ]] + } + } +} \ No newline at end of file diff --git a/gameserver/src/main/resources/prefabs/dungeon_large_2/blocks.cmp b/gameserver/src/main/resources/prefabs/dungeon_large_2/blocks.cmp new file mode 100644 index 0000000000000000000000000000000000000000..7708b9bb67b9a16daad45e7f464aea28292471b7 GIT binary patch literal 997 zcmVToeH*5mm(0ZbHEg2%N0J36S7(aD*+&0XC30V9zsq z0uDpTT50F;cTdklT7iO=Eoo=^>({g%uiyT8`AkVS(>`Faz^&8EG*8UxvfHU%ELi2E zz6y#(Y?Svyg-!ddRBtlW1fpo1k)ip4T~Q_U?djYQjf(DaG{2+#>MAmZciuGL8QScP zi4mxl{!H#v2)$Hdl5R~i;{%=6H1ReZ1kQfV{sFlhzEt_;UgDi$S&`? zx9zQUXagN@^pzh5F8LN#7;%OWX(PzGby-y_sMU<3yah1G$24+egBqs_YC(~7+yQHW~sME~G*B~dy1COYqKiF7cOay{`!sc8| zD=tEkTF<5Y*bGfZiB?%oqxOcxbN;slN=at~#sB`H=p4nK=GBCJ8mY+!ky|hhs@3nt zYy1Buyo%5wB_iZC##$MoQ@UAj&hshxY8Q=MTeulI+-#ml1k)S+X=Y0-Q?RweZ}~GU z@!#&G6$ais2yM7vA-BRo>7iUd{?}NgTx5x=R>>ZIC-%6zTIF+!N>c7LgAd`FkrLne zD!7VJ_ewQs`AWwVr`*g}$!uISDq0{IBHh~w#3ok^r0pT*s=L+)H5spMqaq2TR1AOFw-Pe(C0@iry?hZ?u$ z?9eSAzb!TTr)BNEw~L0qzeL4_C$O0e&&s@rx$Pxqe55aLP9)pt)1O2x(21B@v9jJB zOhQXdKmt*e$)0^Ie>c|2;z#0TwAh;z|>b;$hdPE5oI*aD2#t8bGN;mivQ zS2Y?kGi1@iM3rEu*{TTfhN3@8ecwUW2E|Y!%T`|QN@?-e4u!O*br8Scvv0l7mstNS zH9H0p^?2d?sQxI!YxI{2#E~}PpjKA1dpy+YeKmU8lRmk$uaQQo|!hKP*oT88IcH{cuy}uW#3}FVDo_fQLa5R$>E": [[ 10, 29 ]] + }, + "416": { + "cd": true, + "m": "", + ">": [[ 36, 30 ]] + }, + "2977": { + "cd": true, + "m": "", + ">": [[ 35, 42 ]] + } + } +} \ No newline at end of file diff --git a/gameserver/src/main/resources/prefabs/dungeon_medium_1/blocks.cmp b/gameserver/src/main/resources/prefabs/dungeon_medium_1/blocks.cmp new file mode 100644 index 0000000000000000000000000000000000000000..2550d05da8592c5dbb0f23b444106ee7d63deb68 GIT binary patch literal 521 zcmV+k0`~oQoZXl^PQ)+}hMfmAM0)@_S|rfYaRgSPS?CZQ5~o3kf;t79$9n<}LlQqS zc4q8xUaWBO+w$7k{~J$i?_Qt(Y)Y|Ik@@#%S)tf3li8VQMV1e?O^O|~mf3;LR!U`~ z6hU!;mN$%B)mHYNw_=Mrw!=ubeLKD;qq410a_&TNtqro*|O!y!fFNH~e? z5a4YUN+xn@sjRHQ>C@Tw`XEkTJ0qsiJZsPwWmZ2ZXlnIKLtjg2a?LSM#f$+R38aC> z!62T3wmyJMf8DWt3`V5SH{Ryu&H)w!temsTbDI3`8ZVyyIm25Hn4u)zEal%&gjag> L;7IuekOKSY7Muad literal 0 HcmV?d00001 diff --git a/gameserver/src/main/resources/prefabs/dungeon_medium_1/config.json b/gameserver/src/main/resources/prefabs/dungeon_medium_1/config.json new file mode 100644 index 0000000..885e79d --- /dev/null +++ b/gameserver/src/main/resources/prefabs/dungeon_medium_1/config.json @@ -0,0 +1,13 @@ +{ + "dungeon": true, + "loot": true, + "decay": true, + "mirrorable": true, + "metadata": { + "1017": { + "cd": true, + "m": "", + ">": [[ 11, 8 ]] + } + } +} \ No newline at end of file diff --git a/gameserver/src/main/resources/prefabs/dungeon_medium_10/blocks.cmp b/gameserver/src/main/resources/prefabs/dungeon_medium_10/blocks.cmp new file mode 100644 index 0000000000000000000000000000000000000000..758ae9beb46d8d5a56cea6c2426c986ba23e799d GIT binary patch literal 639 zcmV-_0)YK^ob6aWR>Lq1c9SwCuN$Z6LN|`U8b&q-UN6IA{l?K+8!GtiI9E&%_`SiW%g+#+x_Ipt+mHSw zzek~PiTH?)g4Gxca+WCLVF)DU2ogct+Ao#>ohRG?2cko=vqvbw8jRXxtb!PL%Ysri zYCdS!NXyQqS3=B%6hVzwu?{s|J~2b6;G7-@h6hVfqK40h2IG2VKxG2+?1Sd>%nr#k zW~h0pAv#YT6Q+rQAnOL|y##gD{z^({kZj4QLmnYw!Vr5Dxdb`Axlvdka&AfDIW__o zx)ZtenP{3?ls~W4RN2bM+-QAS>5p&OA(n2#uWuMk>Gr7@-X$_1s zF7j$M@P5_4q3TMMuh{hwK$o;Jf18k-tNp_O7+fGZ(AX*1jz2jNxmW<845(mv@&aQr zI%&2uQsF~?%Dr%Mg6@>rk{~3nSgBNo^Hf4;&c~@745s9RW^Dvr-sc8q6%weB@8=~q ZDZ+Q&j_=++;IL}rew9arwLjOKHW(mYFM$96 literal 0 HcmV?d00001 diff --git a/gameserver/src/main/resources/prefabs/dungeon_medium_10/config.json b/gameserver/src/main/resources/prefabs/dungeon_medium_10/config.json new file mode 100644 index 0000000..391d3d2 --- /dev/null +++ b/gameserver/src/main/resources/prefabs/dungeon_medium_10/config.json @@ -0,0 +1,19 @@ +{ + "dungeon": true, + "loot": true, + "decay": true, + "mirrorable": true, + "metadata": { + "909": { + "cd": true, + "m": "", + ">": [[ 21, 28 ]] + }, + "425": { + "cd": true, + "t": "10", + "m": "", + ">": [[ 3, 22 ]] + } + } +} \ No newline at end of file diff --git a/gameserver/src/main/resources/prefabs/dungeon_medium_2/blocks.cmp b/gameserver/src/main/resources/prefabs/dungeon_medium_2/blocks.cmp new file mode 100644 index 0000000..228fcdd --- /dev/null +++ b/gameserver/src/main/resources/prefabs/dungeon_medium_2/blocks.cmp @@ -0,0 +1,2 @@ +x;R0e;T % +P2i*a u|('.-kWZ=-dW:7?W-u%~Q'G:lUn;/ -˦yxLƈ91W.r#/.B+)jHK2vx rc6)JjK .b^)p^~IEldjFjĢc+nSs6!/ޗa=8JpU"ro@`:ibBY2*?FXwȪ~hC &a?0%GjN!x(Lj#5CrO<u%m:9r=@W{UELQ՛\U|F(#:BS\83XVb %LҮ.+yd'x/VhE60F-Iߚ3o뷘M=g&*: o'z;̜s %8*@rЂ֓.hf"n k[Υ;::\qųwٙEOup,`vQezayK!<% l{bȺ/2pGԬ:^P}R힙$c \ No newline at end of file diff --git a/gameserver/src/main/resources/prefabs/dungeon_medium_2/config.json b/gameserver/src/main/resources/prefabs/dungeon_medium_2/config.json new file mode 100644 index 0000000..ecc4dff --- /dev/null +++ b/gameserver/src/main/resources/prefabs/dungeon_medium_2/config.json @@ -0,0 +1,40 @@ +{ + "dungeon": true, + "loot": true, + "decay": true, + "mirrorable": true, + "replace": { + "building/roof-brown": [ + "building/roof", + "building/roof-brown" + ] + }, + "corresponding_replace": { + "building/roof-edge": { + "key": "building/roof-brown", + "values": { + "building/roof": "building/roof-brown-edge", + "building/roof-brown": "building/roof-edge" + } + }, + "building/roof-brown-edge": { + "key": "building/roof-brown", + "values": { + "building/roof": "building/roof-edge", + "building/roof-brown": "building/roof-brown-edge" + } + } + }, + "metadata": { + "1220": { + "cd": true, + "m": "", + ">": [[ 13, 17 ]] + }, + "328": { + "cd": true, + "m": "", + ">": [[ 23, 29 ]] + } + } +} \ No newline at end of file diff --git a/gameserver/src/main/resources/prefabs/dungeon_medium_3/blocks.cmp b/gameserver/src/main/resources/prefabs/dungeon_medium_3/blocks.cmp new file mode 100644 index 0000000000000000000000000000000000000000..bdd1dd14d3d434ef45ac81a894b4bc6fb1f5c904 GIT binary patch literal 575 zcmV-F0>J%voW+XoDfgtiwEandOaq#fkKB{r$mcmhsP zZ2AoKQi`g()z%cKo>aN~l~ot{d^L#Qoy3;3aN8Uy0AKF7prK?3bI^oy$+tf3Y~yxB zK37KL%S_(%?dJ<;G)_<(+W()0vKJg*3R#^D`{&DB-n1~B(K3$62+`>^iBOc!+Ko(U z3Fwq~vSOr^sW{BpTmK7L(ND6|&C7u)fdMrt7iUb~dVq)_kKoa!H_Z=qd<`N%EJ4G> zNMZ+%9-(^Empzo#GE0FT2;rKaN;NLS#x3_00ZaT6>cW1`FcML0Q>jxWbrh!Tp;)*5 zO~3x zs0Eh+Bo8zrybCLRDxh`fWQd(w9s`^n$P`L-!3e=Ej&P~}9PdTq=?+eUMAXC2$nU-o z<6(c{UGrvV8|dxy=5m{kd@rX-dNwE0uaMe<(9VBwiGN$iQM)97hU_NQqpvBrxn~OL z3*F7Ec7CF|3sL93jI%I#()o#sdY<824Cjhk592U3`zC~ Nf&r3x{R8AAARBwR8Grx) literal 0 HcmV?d00001 diff --git a/gameserver/src/main/resources/prefabs/dungeon_medium_3/config.json b/gameserver/src/main/resources/prefabs/dungeon_medium_3/config.json new file mode 100644 index 0000000..1929a36 --- /dev/null +++ b/gameserver/src/main/resources/prefabs/dungeon_medium_3/config.json @@ -0,0 +1,29 @@ +{ + "dungeon": true, + "loot": true, + "decay": true, + "mirrorable": true, + "replace": { + "back/wallpaper-1": [ + "back/wallpaper-1", + "back/wallpaper-2", + "back/wallpaper-3", + "back/wallpaper-4", + "back/wallpaper-5", + "back/wallpaper-6", + "back/wallpaper-7", + "back/wallpaper-8", + "back/wallpaper-9", + "back/wallpaper-10", + "back/wallpaper-11", + "back/wallpaper-12" + ] + }, + "metadata": { + "224": { + "cd": true, + "m": "", + ">": [[ 30, 32 ]] + } + } +} \ No newline at end of file diff --git a/gameserver/src/main/resources/prefabs/dungeon_medium_4/blocks.cmp b/gameserver/src/main/resources/prefabs/dungeon_medium_4/blocks.cmp new file mode 100644 index 0000000000000000000000000000000000000000..6340733d0d7591962ca6c9075a2b7982f0fe56f1 GIT binary patch literal 479 zcmV<50U-W(oXwWKPQx$|#~nL#p|Bz(7S@W7l}7-Hfw>z(6$^cniYY2$r7wdJmnYy| zARlgGJLk(ea!M`bA167-zrTI4Gdue^`V>?FxrrdrOY>?-F2qn72M|Yt^nuBRM8*b< zGJ4~V=xB(|Feh(ONFh0FgxmSlmR`~<7AeSAn-x^*bf!)zR1S13-k>GMONs~Aa~6%1 zaFB~+QIdfA+Ezt-Z;m~-m_TMOZ#E`xpZo(A3A_g!L|*O5rdhu4`&a0r#A~m3$4-$z zz6YrfF(92oXTyh|i&QQvu$Mqx8YV!l5HWkiXND8wwXinBpE$CO*Li zjW)IqNG8N|Xqix%T3Y~hg_tO{O9JY{jdQISKSEZ+x%IHuQ2n=5oKBp%Qs-r0H)+CF zrxuR4X$(oUfX|$>2bdeOzU(gq;4?>d0!ZaP$TeCgAA-8|664?Us?7x literal 0 HcmV?d00001 diff --git a/gameserver/src/main/resources/prefabs/dungeon_medium_4/config.json b/gameserver/src/main/resources/prefabs/dungeon_medium_4/config.json new file mode 100644 index 0000000..9a4e4d1 --- /dev/null +++ b/gameserver/src/main/resources/prefabs/dungeon_medium_4/config.json @@ -0,0 +1,60 @@ +{ + "dungeon": true, + "loot": true, + "decay": true, + "mirrorable": true, + "replace": { + "back/wallpaper-1": [ + "back/wallpaper-1", + "back/wallpaper-2", + "back/wallpaper-3", + "back/wallpaper-4", + "back/wallpaper-5", + "back/wallpaper-6", + "back/wallpaper-7", + "back/wallpaper-8", + "back/wallpaper-9", + "back/wallpaper-10", + "back/wallpaper-11", + "back/wallpaper-12" + ], + "back/wallpaper-2": [ + "back/wallpaper-1", + "back/wallpaper-2", + "back/wallpaper-3", + "back/wallpaper-4", + "back/wallpaper-5", + "back/wallpaper-6", + "back/wallpaper-7", + "back/wallpaper-8", + "back/wallpaper-9", + "back/wallpaper-10", + "back/wallpaper-11", + "back/wallpaper-12" + ], + "building/fence-iron-1": [ + "building/fence-iron-1", + "building/fence-iron-2" + ], + "building/roof": [ + "building/roof", + "building/roof-brown" + ] + }, + "corresponding_replace": { + "building/roof-edge": { + "key": "building/roof", + "values": { + "building/roof": "building/roof-edge", + "building/roof-brown": "building/roof-brown-edge" + } + } + }, + "metadata": { + "711": { + "cd": true, + "m": "", + ">": [[ 9, 19 ]] + } + } +} \ No newline at end of file diff --git a/gameserver/src/main/resources/prefabs/dungeon_medium_5/blocks.cmp b/gameserver/src/main/resources/prefabs/dungeon_medium_5/blocks.cmp new file mode 100644 index 0000000000000000000000000000000000000000..0b5dd8bfbdb4d7a46dc7d31c8c22922ebc1440f9 GIT binary patch literal 510 zcmVT$I5vhieSkKGio{(acF-U3=_9;Y^aG6hFV*rab{ezs zJvOrpM}YLsgQeF_W25y@;yUw0E0LoBU9TFIL3WQ-a$5y0vcD-;b8iezb@KP2*f#+! za#)!+c>VrG`B%POwW9Qflb>{iUgzOu+t<`3`yD#W+Iayd^KDD&^J<0GcgwbzU0Gmb z+zNa#%LDM0^C45zIcYCNpt(-6dngT7jtvu)+g z)KDG+Z)~fSWHEMiC$g^}$zqNR>WpU=S#;Z2as|ic^G)L5YCnX2sLvUn@@$EBY3 A2LJ#7 literal 0 HcmV?d00001 diff --git a/gameserver/src/main/resources/prefabs/dungeon_medium_5/config.json b/gameserver/src/main/resources/prefabs/dungeon_medium_5/config.json new file mode 100644 index 0000000..31fa8d3 --- /dev/null +++ b/gameserver/src/main/resources/prefabs/dungeon_medium_5/config.json @@ -0,0 +1,19 @@ +{ + "dungeon": true, + "loot": true, + "decay": true, + "mirrorable": true, + "metadata": { + "708": { + "cd": true, + "t": "10", + "m": "", + ">": [[ 19, 22 ]] + }, + "1289": { + "cd": true, + "m": "", + ">": [[ 11, 7 ]] + } + } +} \ No newline at end of file diff --git a/gameserver/src/main/resources/prefabs/dungeon_medium_6/blocks.cmp b/gameserver/src/main/resources/prefabs/dungeon_medium_6/blocks.cmp new file mode 100644 index 0000000000000000000000000000000000000000..bdbce68f4da60bbcf315e2efcb92a4db9246c412 GIT binary patch literal 524 zcmV+n0`vWNob8ygPQx$|h8;WY(vB=h46s&o=Mh>7iGc~kR`EJWNEHu2S007S6YwsO z$c|$t=d+39Btlrqe{PyI-}%mGr<={!*$4A9;3uDq)~cs{ezVRoCWdy~hJgHbY!t{= zN+QMt_;COsA%VXPg?We&64RO7eK{f9GFyPZc}}oE);4!6W0ku>l={MCoJ5+9J*L24 zmHK({q;v9uxS1pijFDV0w>Z7(%jun0LDFKE$>^Xj`3lCx&eL&wgT)l_s;R-w3Wpu) z4k`$iFN_q(*9bjiIg{dWLGgol?B@Z9cNaN`rO`jve#mE)X4f^^m99rd0_O53Y}bqR=s>M~$XgN@Gu1?n8EyZe|0 zBPMkbH|d5=#~zGSs7;CFvv)3P(JGCm4Bhdl@NW&1mKw5arbSX4CkP>kN$>%g<<2mS zT3u^$TUnyf_l7ZR*LoJCeMI@|`B!Zxl^JI0d70OUcycA>RE!#9Q<_)hF?eN#FU=*& z4C2D*FG+6s$0tfI-*XWY>j75zI$zb|eDlS#I?dk3TuIc&3EFHZ3buHbB&s(LnqAYI OG)8S1to;BSocC}0#Q~lG literal 0 HcmV?d00001 diff --git a/gameserver/src/main/resources/prefabs/dungeon_medium_6/config.json b/gameserver/src/main/resources/prefabs/dungeon_medium_6/config.json new file mode 100644 index 0000000..c487fd3 --- /dev/null +++ b/gameserver/src/main/resources/prefabs/dungeon_medium_6/config.json @@ -0,0 +1,43 @@ +{ + "dungeon": true, + "loot": true, + "decay": true, + "mirrorable": true, + "replace": { + "back/wallpaper-1": [ + "back/wallpaper-1", + "back/wallpaper-2", + "back/wallpaper-3", + "back/wallpaper-4", + "back/wallpaper-5", + "back/wallpaper-6", + "back/wallpaper-7", + "back/wallpaper-8", + "back/wallpaper-9", + "back/wallpaper-10", + "back/wallpaper-11", + "back/wallpaper-12" + ], + "back/wallpaper-2": [ + "back/wallpaper-1", + "back/wallpaper-2", + "back/wallpaper-3", + "back/wallpaper-4", + "back/wallpaper-5", + "back/wallpaper-6", + "back/wallpaper-7", + "back/wallpaper-8", + "back/wallpaper-9", + "back/wallpaper-10", + "back/wallpaper-11", + "back/wallpaper-12" + ] + }, + "metadata": { + "1117": { + "cd": true, + "m": "", + ">": [[ 24, 12 ]] + } + } +} \ No newline at end of file diff --git a/gameserver/src/main/resources/prefabs/dungeon_medium_7/blocks.cmp b/gameserver/src/main/resources/prefabs/dungeon_medium_7/blocks.cmp new file mode 100644 index 0000000000000000000000000000000000000000..3135ffd2252ef5a001010766ce6dce54ee2fb51c GIT binary patch literal 456 zcmV;(0XP15ob8x9Qo}G1hGolCWN5en2Ve*lN1!zwkBXVxCPTpyU^veD1RQ}f2f&u? z#9HgIk}b*OiHd(G%39e^+N@;V-~3+xF$Vd!qoiuhk3)6^#ZzOLQ5vUZMhpDaD_-|? z3bCjPs=iBQ9N325r@4BwFEvxTABUNRaYCMv*?_-z(d|2Nr7Qcp@rH{m2;+b*eW->MK2L-ooR}rDZ-ApE7k@};;dN4A2CVAc-`5r%F>PrU7njGPZJhFD3K?f^ESw? zc!=F+Tnnfq+HsB@acN2%Md{0994QiyxmYXfll8&q@dMvZCxBv;mf=n^TQUdmTMRK| z0sa$(W({>q3%9_%LfOu-hG}bzHHO4sLSlOpAAT=w%LSvza=1oU0D7|KrHh0Zh0gHy zKD-1VdC8oRKRcT2kZwh(;+&-`p=wVtDY&NNSy^IIu`!zWmC}h2#66CL*BeopiuPbC yI|N~Eq%Lv0`lF|*SqZ+j-7fH9RZw2E@pu_QY4x2y@Q_Rt6PsvO(YAleD9X7mC*bw~ literal 0 HcmV?d00001 diff --git a/gameserver/src/main/resources/prefabs/dungeon_medium_7/config.json b/gameserver/src/main/resources/prefabs/dungeon_medium_7/config.json new file mode 100644 index 0000000..203e4aa --- /dev/null +++ b/gameserver/src/main/resources/prefabs/dungeon_medium_7/config.json @@ -0,0 +1,19 @@ +{ + "dungeon": true, + "loot": true, + "decay": true, + "mirrorable": true, + "metadata": { + "835": { + "cd": true, + "t": "10", + "m": "", + ">": [[ 40, 29 ]] + }, + "1241": { + "cd": true, + "m": "", + ">": [[ 18, 7 ]] + } + } +} \ No newline at end of file diff --git a/gameserver/src/main/resources/prefabs/dungeon_medium_8/blocks.cmp b/gameserver/src/main/resources/prefabs/dungeon_medium_8/blocks.cmp new file mode 100644 index 0000000000000000000000000000000000000000..fc587a4e03fad7396418fdf1aa60aa507585d0ef GIT binary patch literal 363 zcmV-x0hIoDob8suPQx$^hMgt|O|3X{Ic%fxV?M+j7x z5I4hn@?5kO>aC>$V&MA+n!PhxdKo|D;n3_@#_nS>gX$$94bz{ zvU(F8D6x3-(xtCRCtqy>teyxL@ySFiZ?ol$dUk;XkD@zZ*apWroRVqX5r2pjo!@|2 z>&>`rKHqt_JXOn6S)PjW%-%BdUs&(;SM}gu4WPLMCf!1;w%w;7+NHg)?VQlw2=)21 z8_Yj*HbVe3TM0*^ez0}h-oaiVQ`5qH2s0A|6R8k$crWDuU>%vp*49L;#7Sd~~9WC>YUJXr(B JwJ+eU4VDV~v}phU literal 0 HcmV?d00001 diff --git a/gameserver/src/main/resources/prefabs/dungeon_medium_8/config.json b/gameserver/src/main/resources/prefabs/dungeon_medium_8/config.json new file mode 100644 index 0000000..ec57fd4 --- /dev/null +++ b/gameserver/src/main/resources/prefabs/dungeon_medium_8/config.json @@ -0,0 +1,29 @@ +{ + "dungeon": true, + "loot": true, + "decay": true, + "mirrorable": true, + "replace": { + "back/wallpaper-1": [ + "back/wallpaper-1", + "back/wallpaper-2", + "back/wallpaper-3", + "back/wallpaper-4", + "back/wallpaper-5", + "back/wallpaper-6", + "back/wallpaper-7", + "back/wallpaper-8", + "back/wallpaper-9", + "back/wallpaper-10", + "back/wallpaper-11", + "back/wallpaper-12" + ] + }, + "metadata": { + "190": { + "cd": true, + "m": "", + ">": [[ 15, 17 ]] + } + } +} \ No newline at end of file diff --git a/gameserver/src/main/resources/prefabs/dungeon_medium_9/blocks.cmp b/gameserver/src/main/resources/prefabs/dungeon_medium_9/blocks.cmp new file mode 100644 index 0000000000000000000000000000000000000000..b264dd5714468a3f66b53373b57a8064170128b4 GIT binary patch literal 431 zcmV;g0Z{&UoXwXpPQ)+}MIAd4MI;&uPC$beL_tAE3ldy_4k)+`qN1fC*I{x3jzJF! zPK-UCiN{$Ju$1p?vYY+yk2Bdl-Ft7JReFGal*``^=L4!El@QV|=#G{(oCgM>zRL0L zoImhGHvYs|>#g>tP%LXeU%le+2 zBp&2KSPE`b{E(J8wU^nbgv4Z0{K5O%r(!o5T*sayI~D@7y%|%vqyF`y<4O_N`pCe&@HO=jKmQn?qXd1@F|xJLf!_G z!mn~a0cwjHa-u(jzO@bg#G6#us-^U{2`1n`zsM2*eHYgst%OnCI~Qj`#^9#``e`nY z1~-K2gIjK3E{RFs)92XRql9!*CatW=vp>>sCQT?flSJDu^p}d_6Mkp|=6o;@W_Z=~ Zsy6!s7A7h?7W@CrP!}0Uj4!N~-X_)z%9a2C literal 0 HcmV?d00001 diff --git a/gameserver/src/main/resources/prefabs/dungeon_medium_9/config.json b/gameserver/src/main/resources/prefabs/dungeon_medium_9/config.json new file mode 100644 index 0000000..d4f3bed --- /dev/null +++ b/gameserver/src/main/resources/prefabs/dungeon_medium_9/config.json @@ -0,0 +1,56 @@ +{ + "dungeon": true, + "loot": true, + "decay": true, + "mirrorable": true, + "replace": { + "back/wallpaper-1": [ + "back/wallpaper-1", + "back/wallpaper-2", + "back/wallpaper-3", + "back/wallpaper-4", + "back/wallpaper-5", + "back/wallpaper-6", + "back/wallpaper-7", + "back/wallpaper-8", + "back/wallpaper-9", + "back/wallpaper-10", + "back/wallpaper-11", + "back/wallpaper-12" + ], + "back/wallpaper-2": [ + "back/wallpaper-1", + "back/wallpaper-2", + "back/wallpaper-3", + "back/wallpaper-4", + "back/wallpaper-5", + "back/wallpaper-6", + "back/wallpaper-7", + "back/wallpaper-8", + "back/wallpaper-9", + "back/wallpaper-10", + "back/wallpaper-11", + "back/wallpaper-12" + ], + "back/brick-mixed": [ + "back/brick-mixed", + "back/brick-tan", + "back/brick-blue" + ], + "ammo/bullets": [ + "ammo/bullets", + "containers/crate-small" + ], + "containers/sack-small": [ + "containers/sack-small", + "building/pitch" + ] + }, + "metadata": { + "886": { + "cd": true, + "m": "", + ">": [[ 23, 7 ]] + } + } +} \ No newline at end of file diff --git a/gameserver/src/main/resources/prefabs/dungeon_small_1/blocks.cmp b/gameserver/src/main/resources/prefabs/dungeon_small_1/blocks.cmp new file mode 100644 index 0000000..b1ea7fa --- /dev/null +++ b/gameserver/src/main/resources/prefabs/dungeon_small_1/blocks.cmp @@ -0,0 +1,3 @@ +xM06xw&.Lҥ8ĕ7&xb C-Y&CtR1Av'Oݵ8F/#RòycJ9NvB.+%P- 8$A>)XL;2MIJpD$w2Mii{υүj)}ћ*/2е{"|@ٞ.CؑPBq +km(\׺"u+ +ٱXNW6\5#Q,&#R'f">a% ;SYLҗNQjEP+Oש \ No newline at end of file diff --git a/gameserver/src/main/resources/prefabs/dungeon_small_1/config.json b/gameserver/src/main/resources/prefabs/dungeon_small_1/config.json new file mode 100644 index 0000000..417c925 --- /dev/null +++ b/gameserver/src/main/resources/prefabs/dungeon_small_1/config.json @@ -0,0 +1,22 @@ +{ + "dungeon": true, + "loot": true, + "decay": true, + "mirrorable": true, + "replace": { + "back/wallpaper-1": [ + "back/wallpaper-1", + "back/wallpaper-2", + "back/wallpaper-3", + "back/wallpaper-4", + "back/wallpaper-5", + "back/wallpaper-6", + "back/wallpaper-7", + "back/wallpaper-8", + "back/wallpaper-9", + "back/wallpaper-10", + "back/wallpaper-11", + "back/wallpaper-12" + ] + } +} \ No newline at end of file diff --git a/gameserver/src/main/resources/prefabs/dungeon_small_2/blocks.cmp b/gameserver/src/main/resources/prefabs/dungeon_small_2/blocks.cmp new file mode 100644 index 0000000000000000000000000000000000000000..3f2a0727756394dedf38de3eb3975ee89d2209ca GIT binary patch literal 390 zcmV;10eSv-oVAuqZo?oDhKaE%RhDvrE_#D1+4Txprpq26$H^gD^*G~Rpogig_%Q?X z0E1cJ7zqDo_-EktLYJW?L=pVC)Kl@h|@lCf-f9)bt{JzPZaXF6-|p8OYj zYsp))zCC2d<>bCJLIyOCy-XX8oaXh}6*FXpCG2w~(dvrd6+CMmJ#INb{)|fK7vcCw zk({Z(MOHbZ->0B6JQyc(8xMnaDR_n*QheuxZ5?ATy3cgX!@q4?L)$GHX88rr+6UDu zDq2>dIlc=v-%O{wfbd&P8z-@rm}Cc}!u$%&t;{BA%f-1kr": [[ 7, 11 ]] + }, + "786": { + "cd": true, + "t": "10", + "m": "", + ">": [[ 21, 11 ]] + }, + "799": { + "cd": true, + "m": "", + ">": [[ 11, 11 ]] + }, + "633": { + "cd": true, + "m": "", + ">": [[ 9, 11 ]] + } + } +} \ No newline at end of file diff --git a/gameserver/src/main/resources/prefabs/dungeon_small_3/blocks.cmp b/gameserver/src/main/resources/prefabs/dungeon_small_3/blocks.cmp new file mode 100644 index 0000000000000000000000000000000000000000..1eeeb9eaf3ecc0e60adae0100bebee30bd98f14a GIT binary patch literal 205 zcmV;;05bo0oD&wg!&1V40?sl`K_)Ooun`P+%>WT+{$q%r`G1xr5G;YfAQ2qq;?hDK z#%2`L1QLxo%hZR@F#Lf8RKpyF=`OsUg&RsBbcu)$G}DMM1h2u!-a#}do9(+4RAGo_Q~E_{g;g5<1Qfagf;0UAw&muGf~uGO~FLuHS)_90M2HspJeK5x$Z&V zBL|xkt}WJRmx2QOl7j{29fKWjW#3qW7F|H7l%6=O&7!3qMMy+5>GQ{%(+0W$^Fhm* z->Se-JS>0HDr5KKCqHj?l&k~Klb6^`a>gl?+V5qfb_x- z$0wLKKQVh&9?&jyHK;-)B8ETM6N0%2)l#5bQIc^OE_N%LsaJ+POpGwp%yk9!IUqV$ tUt4NQ79SzE^G4SR^ExEMg@)8HKy~fLX5ХlHN80q>J0Q[q5܄YzgWC ě Φ6GxBfEk xў _+Swҥ^X=Vu|P`!}e`p+wGbRK1Gg_? `e{=bt֪X?ڐJ \ No newline at end of file diff --git a/gameserver/src/main/resources/prefabs/head_bunker/config.json b/gameserver/src/main/resources/prefabs/head_bunker/config.json new file mode 100644 index 0000000..cb0e82d --- /dev/null +++ b/gameserver/src/main/resources/prefabs/head_bunker/config.json @@ -0,0 +1,43 @@ +{ + "loot": true, + "decay": true, + "mirrorable": true, + "replace": { + "furniture/head-deer": { + "furniture/head-predator": 1, + "furniture/head-tiger": 3, + "furniture/head-fish": 10, + "furniture/head-cthulhu": 50, + "furniture/head-bear": 80, + "furniture/head-deer": 80 + }, + "back/wallpaper-1": [ + "back/wallpaper-1", + "back/wallpaper-2", + "back/wallpaper-3", + "back/wallpaper-4", + "back/wallpaper-5", + "back/wallpaper-6", + "back/wallpaper-7", + "back/wallpaper-8", + "back/wallpaper-9", + "back/wallpaper-10", + "back/wallpaper-11", + "back/wallpaper-12" + ], + "building/pitch": [ + "building/pitch", + "containers/crate-small", + "ammo/bullets" + ], + "containers/crate-small": [ + "containers/crate-small", + "ammo/bullets" + ], + "containers/sack-small": [ + "containers/sack-small", + "building/pitch", + "ammo/bullets" + ] + } +} \ No newline at end of file diff --git a/gameserver/src/main/resources/prefabs/paint_bunker/blocks.cmp b/gameserver/src/main/resources/prefabs/paint_bunker/blocks.cmp new file mode 100644 index 0000000000000000000000000000000000000000..67d39ec0713b7931a3936b2aec3f6d92124828c7 GIT binary patch literal 226 zcmV<803H8$oVAtB4Z<)Cg`K871yw@gz*rm^3Uvg8lpDL42^fYJxsYGgNu3;C)wubd zBdhl5{2m^#EbQ))l&<9vsslJ8!KeTUP_Vl>vLas4Ys+Q%h(9M4;0opN3`toqsuA`} zNCppXMC4}!3I6o?MB": [[ 14, 5 ]] + } + } +} \ No newline at end of file diff --git a/gameserver/src/main/resources/prefabs/plain_spawn_tower_1/blocks.cmp b/gameserver/src/main/resources/prefabs/plain_spawn_tower_1/blocks.cmp new file mode 100644 index 0000000000000000000000000000000000000000..9bd1816168e54f5df1acfad224bca909c95799fa GIT binary patch literal 148 zcmV;F0BiqvoZ}U|!!(@%1)O7GVJcu?ILnleN)#|)2T1DAGO{wDvoLj{TL4xIBhIq; zBMD$}z*(krBmzk(44~*nRtwRcio+WW=<;MMJjIH0zQvrH-2)PUWIp$6i5Qq%xVO(%i?02aMxOBDkr`~Uy| literal 0 HcmV?d00001 diff --git a/gameserver/src/main/resources/prefabs/plain_spawn_tower_2/config.json b/gameserver/src/main/resources/prefabs/plain_spawn_tower_2/config.json new file mode 100644 index 0000000..ee671a6 --- /dev/null +++ b/gameserver/src/main/resources/prefabs/plain_spawn_tower_2/config.json @@ -0,0 +1,32 @@ +{ + "decay": true, + "mirrorable": true, + "replace": { + "building/brick-tan": [ + "building/brick", + "building/brick-mixed", + "building/brick-tan", + "building/brick-blue" + ], + "building/ladder-wood": [ + "building/ladder-wood", + "building/ladder-brass", + "building/ladder-rope" + ], + "building/fence-iron-2": [ + "building/fence-iron-1", + "building/fence-iron-2" + ] + }, + "corresponding_replace": { + "back/brick-tan": { + "key": "building/brick-tan", + "values": { + "building/brick": "back/brick", + "building/brick-mixed": "back/brick-mixed", + "building/brick-tan": "back/brick-tan", + "building/brick-blue": "back/brick-blue" + } + } + } +} \ No newline at end of file diff --git a/gameserver/src/main/resources/prefabs/plain_spawn_tower_3/blocks.cmp b/gameserver/src/main/resources/prefabs/plain_spawn_tower_3/blocks.cmp new file mode 100644 index 0000000000000000000000000000000000000000..35763c846c1b83a065ea7fddd08ec17909330ad1 GIT binary patch literal 166 zcmV;X09pTdoD&kh!@|UX9h_yFOB8`0oMkE@iXd#tSw2xG%X(icyw={Izu=Y literal 0 HcmV?d00001 diff --git a/gameserver/src/main/resources/prefabs/plain_spawn_tower_4/config.json b/gameserver/src/main/resources/prefabs/plain_spawn_tower_4/config.json new file mode 100644 index 0000000..1ff478f --- /dev/null +++ b/gameserver/src/main/resources/prefabs/plain_spawn_tower_4/config.json @@ -0,0 +1,15 @@ +{ + "decay": true, + "mirrorable": true, + "replace": { + "building/fence-iron-2": [ + "building/fence-iron-1", + "building/fence-iron-2" + ], + "building/ladder-wood": [ + "building/ladder-wood", + "building/ladder-brass", + "building/ladder-rope" + ] + } +} \ No newline at end of file