diff --git a/src/main/java/io/github/restioson/siege/game/active/SiegeActive.java b/src/main/java/io/github/restioson/siege/game/active/SiegeActive.java index dbbc08f..5388afc 100644 --- a/src/main/java/io/github/restioson/siege/game/active/SiegeActive.java +++ b/src/main/java/io/github/restioson/siege/game/active/SiegeActive.java @@ -2,6 +2,7 @@ import com.google.common.collect.Multimap; import eu.pb4.sgui.api.gui.SimpleGui; +import io.github.restioson.siege.Siege; import io.github.restioson.siege.game.SiegeConfig; import io.github.restioson.siege.game.SiegeKit; import io.github.restioson.siege.game.SiegeSpawnLogic; @@ -21,6 +22,7 @@ import net.minecraft.entity.projectile.ProjectileEntity; import net.minecraft.item.*; import net.minecraft.registry.tag.DamageTypeTags; +import net.minecraft.resource.LifecycledResourceManager; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.world.ServerWorld; import net.minecraft.sound.SoundCategory; @@ -129,6 +131,7 @@ public static void open(ServerWorld world, GameSpace gameSpace, SiegeMap map, Si activity.allow(GameRuleType.PLACE_BLOCKS); activity.allow(GameRuleType.UNSTABLE_TNT); + activity.listen(GameActivityEvents.RELOAD, active::onReload); activity.listen(GameActivityEvents.ENABLE, active::onOpen); activity.listen(GameActivityEvents.DISABLE, active::onClose); activity.listen(ItemThrowEvent.EVENT, active::onDropItem); @@ -154,6 +157,14 @@ public static void open(ServerWorld world, GameSpace gameSpace, SiegeMap map, Si }); } + private void onReload(LifecycledResourceManager resourceManager, boolean success) { + if (success) { + this.map.reload(this); + } else { + Siege.LOGGER.warn("Failed to reload datapacks and resources; not reloading map..."); + } + } + private void onExplosion(Explosion explosion, boolean particles) { gate: for (SiegeGate gate : this.map.gates) { diff --git a/src/main/java/io/github/restioson/siege/game/map/SiegeMap.java b/src/main/java/io/github/restioson/siege/game/map/SiegeMap.java index 1849191..49b0921 100644 --- a/src/main/java/io/github/restioson/siege/game/map/SiegeMap.java +++ b/src/main/java/io/github/restioson/siege/game/map/SiegeMap.java @@ -39,6 +39,86 @@ public SiegeMap(SiegeMapConfig config, MapTemplate template) { this.time = 1000; } + private static SiegeMap merge(SiegeActive active, SiegeMap oldMap, SiegeMap newMap) { + var world = active.world; + var gameSpace = active.gameSpace; + + for (var newFlag : newMap.flags) { + oldMap.flags.stream().filter(f -> f.id.equals(newFlag.id)).findFirst() + .ifPresent(oldFlag -> { + newFlag.captureProgressTicks = oldFlag.captureProgressTicks; + newFlag.team = oldFlag.team; + newFlag.setTeamBlocks(world, newFlag.team); + }); + } + + for (var oldFlag : oldMap.flags) { + oldFlag.captureBar.clearPlayers(); + } + + for (var newGate : newMap.gates) { + oldMap.gates.stream().filter(g -> g.id.equals(newGate.id)).findFirst() + .ifPresent(oldGate -> { + newGate.bashedOpen = oldGate.bashedOpen; + newGate.health = oldGate.health; + newGate.openSlide = oldGate.openSlide; + + if (newGate.bashedOpen) { + newGate.slider.setOpen(world); + } else { + newGate.slider.set(world, newGate.openSlide); + } + }); + } + + newMap.spawnKitStands(active); + + for (var player : gameSpace.getPlayers()) { + if (!newMap.template.getBounds().contains(player.getBlockPos()) || player.isInsideWall()) { + SiegeSpawnLogic.spawnPlayer(player, newMap.waitingSpawn, world); + } + } + + gameSpace.getPlayers().sendMessage(Text.literal("[Siege] Map reloaded!")); + return newMap; + } + + public void reload(SiegeActive active) { + var world = active.world; + var gameSpace = active.gameSpace; + + var server = world.getServer(); + + long time = System.currentTimeMillis(); + var newMap = SiegeMapLoader.load(server, this.config); + System.out.printf("Loading took %sms%n", System.currentTimeMillis() - time); + + time = System.currentTimeMillis(); + var diff = newMap.template.diff(this.template); + System.out.printf("Diffing took %sms%n", System.currentTimeMillis() - time); + + Siege.LOGGER.info("Loaded new template with diff {}", diff); + + if (diff.needsRegeneration()) { + Siege.LOGGER.info("Regenerating world"); + gameSpace.getWorlds().regenerate(world, newMap.asGenerator(server), newMap.template.getBounds().union(this.template.getBounds())); + } else { + Siege.LOGGER.debug("Diff does not warrant regeneration"); + } + + if (newMap.time != this.time) { + Siege.LOGGER.info("Changing time from {} to {}", this.time, newMap.time); + world.setTimeOfDay(newMap.time); + } else { + Siege.LOGGER.debug("Skipping changing time, as they are the same"); + } + + var merged = merge(active, this, newMap); + Siege.LOGGER.info("Done reloading map!"); + + active.map = merged; + } + public SiegeSpawn getFirstSpawn(GameTeam team) { if (team == SiegeTeams.ATTACKERS) { return this.attackerFirstSpawn;