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 0000000..f550d91 Binary files /dev/null and b/gameserver/src/main/resources/prefabs/dungeon_large_1/blocks.cmp differ diff --git a/gameserver/src/main/resources/prefabs/dungeon_large_1/config.json b/gameserver/src/main/resources/prefabs/dungeon_large_1/config.json new file mode 100644 index 0000000..8129767 --- /dev/null +++ b/gameserver/src/main/resources/prefabs/dungeon_large_1/config.json @@ -0,0 +1,24 @@ +{ + "dungeon": true, + "loot": true, + "decay": true, + "mirrorable": true, + "metadata": { + "2316": { + "cd": true, + "m": "", + ">": [[ 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 0000000..7708b9b Binary files /dev/null and b/gameserver/src/main/resources/prefabs/dungeon_large_2/blocks.cmp differ diff --git a/gameserver/src/main/resources/prefabs/dungeon_large_2/config.json b/gameserver/src/main/resources/prefabs/dungeon_large_2/config.json new file mode 100644 index 0000000..c61fe84 --- /dev/null +++ b/gameserver/src/main/resources/prefabs/dungeon_large_2/config.json @@ -0,0 +1,23 @@ +{ + "dungeon": true, + "loot": true, + "decay": true, + "mirrorable": true, + "metadata": { + "2306": { + "cd": true, + "m": "", + ">": [[ 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 0000000..2550d05 Binary files /dev/null and b/gameserver/src/main/resources/prefabs/dungeon_medium_1/blocks.cmp differ 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 0000000..758ae9b Binary files /dev/null and b/gameserver/src/main/resources/prefabs/dungeon_medium_10/blocks.cmp differ 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 0000000..bdd1dd1 Binary files /dev/null and b/gameserver/src/main/resources/prefabs/dungeon_medium_3/blocks.cmp differ 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 0000000..6340733 Binary files /dev/null and b/gameserver/src/main/resources/prefabs/dungeon_medium_4/blocks.cmp differ 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 0000000..0b5dd8b Binary files /dev/null and b/gameserver/src/main/resources/prefabs/dungeon_medium_5/blocks.cmp differ 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 0000000..bdbce68 Binary files /dev/null and b/gameserver/src/main/resources/prefabs/dungeon_medium_6/blocks.cmp differ 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 0000000..3135ffd Binary files /dev/null and b/gameserver/src/main/resources/prefabs/dungeon_medium_7/blocks.cmp differ 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 0000000..fc587a4 Binary files /dev/null and b/gameserver/src/main/resources/prefabs/dungeon_medium_8/blocks.cmp differ 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 0000000..b264dd5 Binary files /dev/null and b/gameserver/src/main/resources/prefabs/dungeon_medium_9/blocks.cmp differ 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 0000000..3f2a072 Binary files /dev/null and b/gameserver/src/main/resources/prefabs/dungeon_small_2/blocks.cmp differ diff --git a/gameserver/src/main/resources/prefabs/dungeon_small_2/config.json b/gameserver/src/main/resources/prefabs/dungeon_small_2/config.json new file mode 100644 index 0000000..4ae25c2 --- /dev/null +++ b/gameserver/src/main/resources/prefabs/dungeon_small_2/config.json @@ -0,0 +1,29 @@ +{ + "dungeon": true, + "loot": true, + "decay": true, + "mirrorable": true, + "metadata": { + "518": { + "cd": true, + "m": "", + ">": [[ 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 0000000..1eeeb9e Binary files /dev/null and b/gameserver/src/main/resources/prefabs/dungeon_small_3/blocks.cmp differ diff --git a/gameserver/src/main/resources/prefabs/dungeon_small_3/config.json b/gameserver/src/main/resources/prefabs/dungeon_small_3/config.json new file mode 100644 index 0000000..1ed7e76 --- /dev/null +++ b/gameserver/src/main/resources/prefabs/dungeon_small_3/config.json @@ -0,0 +1,6 @@ +{ + "dungeon": true, + "loot": true, + "decay": true, + "mirrorable": true +} \ No newline at end of file diff --git a/gameserver/src/main/resources/prefabs/dungeon_small_4/blocks.cmp b/gameserver/src/main/resources/prefabs/dungeon_small_4/blocks.cmp new file mode 100644 index 0000000..e7d5cff Binary files /dev/null and b/gameserver/src/main/resources/prefabs/dungeon_small_4/blocks.cmp differ diff --git a/gameserver/src/main/resources/prefabs/dungeon_small_4/config.json b/gameserver/src/main/resources/prefabs/dungeon_small_4/config.json new file mode 100644 index 0000000..1ed7e76 --- /dev/null +++ b/gameserver/src/main/resources/prefabs/dungeon_small_4/config.json @@ -0,0 +1,6 @@ +{ + "dungeon": true, + "loot": true, + "decay": true, + "mirrorable": true +} \ No newline at end of file diff --git a/gameserver/src/main/resources/prefabs/head_bunker/blocks.cmp b/gameserver/src/main/resources/prefabs/head_bunker/blocks.cmp new file mode 100644 index 0000000..be6afaf --- /dev/null +++ b/gameserver/src/main/resources/prefabs/head_bunker/blocks.cmp @@ -0,0 +1 @@ +xA ELsF4&&"Mxv)N gs sѣ}6:~R>X5Х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 0000000..67d39ec Binary files /dev/null and b/gameserver/src/main/resources/prefabs/paint_bunker/blocks.cmp differ diff --git a/gameserver/src/main/resources/prefabs/paint_bunker/config.json b/gameserver/src/main/resources/prefabs/paint_bunker/config.json new file mode 100644 index 0000000..fe981c6 --- /dev/null +++ b/gameserver/src/main/resources/prefabs/paint_bunker/config.json @@ -0,0 +1,31 @@ +{ + "decay": true, + "mirrorable": true, + "replace": { + "furniture/painting-une-pipe": { + "furniture/painting-notch": 1, + "furniture/painting-outling": 3, + "furniture/solar-system-diorama": 3, + "furniture/painting-surfer": 8, + "furniture/airship-in-bottle": 8, + "furniture/painting-mayflower": 10, + "furniture/painting-autumn": 10, + "furniture/painting-leapquest": 22, + "furniture/painting-digdug": 22, + "furniture/painting-alpaca": 30, + "furniture/globe": 30, + "furniture/painting-northerners": 48, + "furniture/painting-smasheroid": 48, + "furniture/painting-gashlycrumb": 67, + "furniture/painting-son-of-man": 104, + "furniture/painting-une-pipe": 600 + } + }, + "metadata": { + "84": { + "cd": true, + "m": "", + ">": [[ 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 0000000..9bd1816 Binary files /dev/null and b/gameserver/src/main/resources/prefabs/plain_spawn_tower_1/blocks.cmp differ diff --git a/gameserver/src/main/resources/prefabs/plain_spawn_tower_1/config.json b/gameserver/src/main/resources/prefabs/plain_spawn_tower_1/config.json new file mode 100644 index 0000000..7a3d2d8 --- /dev/null +++ b/gameserver/src/main/resources/prefabs/plain_spawn_tower_1/config.json @@ -0,0 +1,38 @@ +{ + "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" + ], + "building/ladder-brass": [ + "building/ladder-wood", + "building/ladder-brass", + "building/ladder-rope" + ], + "building/roof-brown": [ + "building/roof", + "building/roof-brown" + ] + }, + "corresponding_replace": { + "building/roof-brown-edge": { + "key": "building/roof-brown", + "values": { + "building/roof": "building/roof-edge", + "building/roof-brown": "building/roof-brown-edge" + } + } + } +} \ No newline at end of file diff --git a/gameserver/src/main/resources/prefabs/plain_spawn_tower_2/blocks.cmp b/gameserver/src/main/resources/prefabs/plain_spawn_tower_2/blocks.cmp new file mode 100644 index 0000000..18930a4 Binary files /dev/null and b/gameserver/src/main/resources/prefabs/plain_spawn_tower_2/blocks.cmp differ 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 0000000..35763c8 Binary files /dev/null and b/gameserver/src/main/resources/prefabs/plain_spawn_tower_3/blocks.cmp differ diff --git a/gameserver/src/main/resources/prefabs/plain_spawn_tower_3/config.json b/gameserver/src/main/resources/prefabs/plain_spawn_tower_3/config.json new file mode 100644 index 0000000..be778c4 --- /dev/null +++ b/gameserver/src/main/resources/prefabs/plain_spawn_tower_3/config.json @@ -0,0 +1,46 @@ +{ + "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" + ], + "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_4/blocks.cmp b/gameserver/src/main/resources/prefabs/plain_spawn_tower_4/blocks.cmp new file mode 100644 index 0000000..27c7f38 Binary files /dev/null and b/gameserver/src/main/resources/prefabs/plain_spawn_tower_4/blocks.cmp differ 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