Skip to content

Commit 9f9e180

Browse files
committed
feat: hot reload map
1 parent a73894b commit 9f9e180

File tree

2 files changed

+91
-0
lines changed

2 files changed

+91
-0
lines changed

src/main/java/io/github/restioson/siege/game/active/SiegeActive.java

+11
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import com.google.common.collect.Multimap;
44
import eu.pb4.sgui.api.gui.SimpleGui;
5+
import io.github.restioson.siege.Siege;
56
import io.github.restioson.siege.game.SiegeConfig;
67
import io.github.restioson.siege.game.SiegeKit;
78
import io.github.restioson.siege.game.SiegeSpawnLogic;
@@ -21,6 +22,7 @@
2122
import net.minecraft.entity.projectile.ProjectileEntity;
2223
import net.minecraft.item.*;
2324
import net.minecraft.registry.tag.DamageTypeTags;
25+
import net.minecraft.resource.LifecycledResourceManager;
2426
import net.minecraft.server.network.ServerPlayerEntity;
2527
import net.minecraft.server.world.ServerWorld;
2628
import net.minecraft.sound.SoundCategory;
@@ -129,6 +131,7 @@ public static void open(ServerWorld world, GameSpace gameSpace, SiegeMap map, Si
129131
activity.allow(GameRuleType.PLACE_BLOCKS);
130132
activity.allow(GameRuleType.UNSTABLE_TNT);
131133

134+
activity.listen(GameActivityEvents.RELOAD, active::onReload);
132135
activity.listen(GameActivityEvents.ENABLE, active::onOpen);
133136
activity.listen(GameActivityEvents.DISABLE, active::onClose);
134137
activity.listen(ItemThrowEvent.EVENT, active::onDropItem);
@@ -154,6 +157,14 @@ public static void open(ServerWorld world, GameSpace gameSpace, SiegeMap map, Si
154157
});
155158
}
156159

160+
private void onReload(LifecycledResourceManager resourceManager, boolean success) {
161+
if (success) {
162+
this.map.reload(this);
163+
} else {
164+
Siege.LOGGER.warn("Failed to reload datapacks and resources; not reloading map...");
165+
}
166+
}
167+
157168
private void onExplosion(Explosion explosion, boolean particles) {
158169
gate:
159170
for (SiegeGate gate : this.map.gates) {

src/main/java/io/github/restioson/siege/game/map/SiegeMap.java

+80
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,86 @@ public SiegeMap(SiegeMapConfig config, MapTemplate template) {
3939
this.time = 1000;
4040
}
4141

42+
private static SiegeMap merge(SiegeActive active, SiegeMap oldMap, SiegeMap newMap) {
43+
var world = active.world;
44+
var gameSpace = active.gameSpace;
45+
46+
for (var newFlag : newMap.flags) {
47+
oldMap.flags.stream().filter(f -> f.id.equals(newFlag.id)).findFirst()
48+
.ifPresent(oldFlag -> {
49+
newFlag.captureProgressTicks = oldFlag.captureProgressTicks;
50+
newFlag.team = oldFlag.team;
51+
newFlag.setTeamBlocks(world, newFlag.team);
52+
});
53+
}
54+
55+
for (var oldFlag : oldMap.flags) {
56+
oldFlag.captureBar.clearPlayers();
57+
}
58+
59+
for (var newGate : newMap.gates) {
60+
oldMap.gates.stream().filter(g -> g.id.equals(newGate.id)).findFirst()
61+
.ifPresent(oldGate -> {
62+
newGate.bashedOpen = oldGate.bashedOpen;
63+
newGate.health = oldGate.health;
64+
newGate.openSlide = oldGate.openSlide;
65+
66+
if (newGate.bashedOpen) {
67+
newGate.slider.setOpen(world);
68+
} else {
69+
newGate.slider.set(world, newGate.openSlide);
70+
}
71+
});
72+
}
73+
74+
newMap.spawnKitStands(active);
75+
76+
for (var player : gameSpace.getPlayers()) {
77+
if (!newMap.template.getBounds().contains(player.getBlockPos()) || player.isInsideWall()) {
78+
SiegeSpawnLogic.spawnPlayer(player, newMap.waitingSpawn, world);
79+
}
80+
}
81+
82+
gameSpace.getPlayers().sendMessage(Text.literal("[Siege] Map reloaded!"));
83+
return newMap;
84+
}
85+
86+
public void reload(SiegeActive active) {
87+
var world = active.world;
88+
var gameSpace = active.gameSpace;
89+
90+
var server = world.getServer();
91+
92+
long time = System.currentTimeMillis();
93+
var newMap = SiegeMapLoader.load(server, this.config);
94+
System.out.printf("Loading took %sms%n", System.currentTimeMillis() - time);
95+
96+
time = System.currentTimeMillis();
97+
var diff = newMap.template.diff(this.template);
98+
System.out.printf("Diffing took %sms%n", System.currentTimeMillis() - time);
99+
100+
Siege.LOGGER.info("Loaded new template with diff {}", diff);
101+
102+
if (diff.needsRegeneration()) {
103+
Siege.LOGGER.info("Regenerating world");
104+
gameSpace.getWorlds().regenerate(world, newMap.asGenerator(server), newMap.template.getBounds().union(this.template.getBounds()));
105+
} else {
106+
Siege.LOGGER.debug("Diff does not warrant regeneration");
107+
}
108+
109+
if (newMap.time != this.time) {
110+
Siege.LOGGER.info("Changing time from {} to {}", this.time, newMap.time);
111+
world.setTimeOfDay(newMap.time);
112+
} else {
113+
Siege.LOGGER.debug("Skipping changing time, as they are the same");
114+
}
115+
116+
var merged = merge(active, this, newMap);
117+
Siege.LOGGER.info("Done reloading map!");
118+
119+
active.map = merged;
120+
}
121+
42122
public SiegeSpawn getFirstSpawn(GameTeam team) {
43123
if (team == SiegeTeams.ATTACKERS) {
44124
return this.attackerFirstSpawn;

0 commit comments

Comments
 (0)