Skip to content

Commit

Permalink
feat: hot reload map
Browse files Browse the repository at this point in the history
  • Loading branch information
Restioson committed Jun 16, 2024
1 parent a73894b commit 9f9e180
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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);
Expand All @@ -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) {
Expand Down
80 changes: 80 additions & 0 deletions src/main/java/io/github/restioson/siege/game/map/SiegeMap.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit 9f9e180

Please sign in to comment.