Skip to content
This repository was archived by the owner on Jun 3, 2024. It is now read-only.

Commit b23d090

Browse files
committed
Implement WorldEvent.
This also includes the following nested derived events: - WorldEvent.Load - WorldEvent.Unload - WorldEvent.Save - WorldEvent.PotentialSpawns - WorldEvent.CreateSpawnPosition
1 parent f3794fe commit b23d090

10 files changed

Lines changed: 653 additions & 1 deletion

File tree

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/*
2+
* Minecraft Forge, Patchwork Project
3+
* Copyright (c) 2016-2019, 2019
4+
*
5+
* This library is free software; you can redistribute it and/or
6+
* modify it under the terms of the GNU Lesser General Public
7+
* License as published by the Free Software Foundation version 2.1
8+
* of the License.
9+
*
10+
* This library is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13+
* Lesser General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU Lesser General Public
16+
* License along with this library; if not, write to the Free Software
17+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18+
*/
19+
20+
package com.patchworkmc.impl.event.world;
21+
22+
import net.minecraft.world.IWorld;
23+
24+
public interface IGetWorldFromChunkGenerator {
25+
IWorld getWorld();
26+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
* Minecraft Forge, Patchwork Project
3+
* Copyright (c) 2016-2019, 2019
4+
*
5+
* This library is free software; you can redistribute it and/or
6+
* modify it under the terms of the GNU Lesser General Public
7+
* License as published by the Free Software Foundation version 2.1
8+
* of the License.
9+
*
10+
* This library is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13+
* Lesser General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU Lesser General Public
16+
* License along with this library; if not, write to the Free Software
17+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18+
*/
19+
20+
package com.patchworkmc.impl.event.world;
21+
22+
import java.util.Collections;
23+
import java.util.List;
24+
25+
import net.minecraftforge.common.MinecraftForge;
26+
import net.minecraftforge.event.world.WorldEvent;
27+
28+
import net.minecraft.entity.EntityCategory;
29+
import net.minecraft.util.math.BlockPos;
30+
import net.minecraft.world.IWorld;
31+
import net.minecraft.world.biome.Biome;
32+
import net.minecraft.world.level.LevelInfo;
33+
34+
public class WorldEvents {
35+
public static boolean onCreateWorldSpawn(IWorld world, LevelInfo settings) {
36+
return MinecraftForge.EVENT_BUS.post(new WorldEvent.CreateSpawnPosition(world, settings));
37+
}
38+
39+
public static List<Biome.SpawnEntry> getPotentialSpawns(IWorld world, EntityCategory type, BlockPos pos, List<Biome.SpawnEntry> oldSpawns) {
40+
WorldEvent.PotentialSpawns event = new WorldEvent.PotentialSpawns(world, type, pos, oldSpawns);
41+
42+
if (MinecraftForge.EVENT_BUS.post(event)) {
43+
return Collections.emptyList();
44+
}
45+
46+
return event.getList();
47+
}
48+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*
2+
* Minecraft Forge, Patchwork Project
3+
* Copyright (c) 2016-2019, 2019
4+
*
5+
* This library is free software; you can redistribute it and/or
6+
* modify it under the terms of the GNU Lesser General Public
7+
* License as published by the Free Software Foundation version 2.1
8+
* of the License.
9+
*
10+
* This library is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13+
* Lesser General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU Lesser General Public
16+
* License along with this library; if not, write to the Free Software
17+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18+
*/
19+
20+
package com.patchworkmc.mixin.event.world;
21+
22+
import org.spongepowered.asm.mixin.Mixin;
23+
import org.spongepowered.asm.mixin.Shadow;
24+
25+
import net.minecraft.world.IWorld;
26+
import net.minecraft.world.gen.chunk.ChunkGenerator;
27+
28+
import com.patchworkmc.impl.event.world.IGetWorldFromChunkGenerator;
29+
30+
@Mixin(ChunkGenerator.class)
31+
public class MixinChunkGenerator implements IGetWorldFromChunkGenerator {
32+
@Shadow
33+
protected IWorld world;
34+
35+
public IWorld getWorld() {
36+
return world;
37+
}
38+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*
2+
* Minecraft Forge, Patchwork Project
3+
* Copyright (c) 2016-2019, 2019
4+
*
5+
* This library is free software; you can redistribute it and/or
6+
* modify it under the terms of the GNU Lesser General Public
7+
* License as published by the Free Software Foundation version 2.1
8+
* of the License.
9+
*
10+
* This library is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13+
* Lesser General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU Lesser General Public
16+
* License along with this library; if not, write to the Free Software
17+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18+
*/
19+
20+
package com.patchworkmc.mixin.event.world;
21+
22+
import java.util.function.BiFunction;
23+
24+
import net.minecraftforge.common.MinecraftForge;
25+
import net.minecraftforge.event.world.WorldEvent;
26+
import org.spongepowered.asm.mixin.Mixin;
27+
import org.spongepowered.asm.mixin.injection.At;
28+
import org.spongepowered.asm.mixin.injection.Inject;
29+
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
30+
31+
import net.minecraft.util.profiler.Profiler;
32+
import net.minecraft.world.chunk.ChunkManager;
33+
import net.minecraft.world.dimension.Dimension;
34+
import net.minecraft.world.dimension.DimensionType;
35+
import net.minecraft.world.level.LevelProperties;
36+
import net.minecraft.world.World;
37+
import net.minecraft.client.world.ClientWorld;
38+
39+
@Mixin(ClientWorld.class)
40+
public abstract class MixinClientWorld extends World {
41+
protected MixinClientWorld(LevelProperties levelProperties, DimensionType dimensionType, BiFunction<World, Dimension, ChunkManager> chunkManagerProvider, Profiler profiler, boolean isClient) {
42+
super(levelProperties, dimensionType, chunkManagerProvider, profiler, isClient);
43+
}
44+
45+
@Inject(method = "<init>", at = @At(value = "TAIL"))
46+
private void hookConstructor(CallbackInfo info) {
47+
ClientWorld world = (ClientWorld) (Object) this;
48+
MinecraftForge.EVENT_BUS.post(new WorldEvent.Load(world));
49+
}
50+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* Minecraft Forge, Patchwork Project
3+
* Copyright (c) 2016-2019, 2019
4+
*
5+
* This library is free software; you can redistribute it and/or
6+
* modify it under the terms of the GNU Lesser General Public
7+
* License as published by the Free Software Foundation version 2.1
8+
* of the License.
9+
*
10+
* This library is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13+
* Lesser General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU Lesser General Public
16+
* License along with this library; if not, write to the Free Software
17+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18+
*/
19+
20+
package com.patchworkmc.mixin.event.world;
21+
22+
import net.minecraftforge.common.MinecraftForge;
23+
import net.minecraftforge.event.world.WorldEvent;
24+
import org.objectweb.asm.Opcodes;
25+
import org.spongepowered.asm.mixin.Mixin;
26+
import org.spongepowered.asm.mixin.Shadow;
27+
import org.spongepowered.asm.mixin.injection.At;
28+
import org.spongepowered.asm.mixin.injection.Inject;
29+
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
30+
31+
import net.minecraft.client.MinecraftClient;
32+
import net.minecraft.client.world.ClientWorld;
33+
34+
@Mixin(MinecraftClient.class)
35+
public class MixinMinecraftClient {
36+
@Shadow
37+
public ClientWorld world;
38+
39+
@Inject(method = "joinWorld", at = @At(value = "HEAD"))
40+
private void hookJoinWorld(CallbackInfo info) {
41+
if (this.world != null) {
42+
MinecraftForge.EVENT_BUS.post(new WorldEvent.Unload(this.world));
43+
}
44+
}
45+
46+
@Inject(method = "disconnect(Lnet/minecraft/client/gui/screen/Screen;)V", at = @At(value = "FIELD", opcode = Opcodes.GETFIELD, target = "net/minecraft/client/MinecraftClient.world : Lnet/minecraft/client/world/ClientWorld;"))
47+
private void hookDisconnect(CallbackInfo info) {
48+
if (this.world != null) {
49+
MinecraftForge.EVENT_BUS.post(new WorldEvent.Unload(this.world));
50+
}
51+
}
52+
}
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
/*
2+
* Minecraft Forge, Patchwork Project
3+
* Copyright (c) 2016-2019, 2019
4+
*
5+
* This library is free software; you can redistribute it and/or
6+
* modify it under the terms of the GNU Lesser General Public
7+
* License as published by the Free Software Foundation version 2.1
8+
* of the License.
9+
*
10+
* This library is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13+
* Lesser General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU Lesser General Public
16+
* License along with this library; if not, write to the Free Software
17+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18+
*/
19+
20+
package com.patchworkmc.mixin.event.world;
21+
22+
import java.io.IOException;
23+
import java.util.Iterator;
24+
import java.util.Map;
25+
26+
import net.minecraftforge.common.MinecraftForge;
27+
import net.minecraftforge.event.world.WorldEvent;
28+
import org.spongepowered.asm.mixin.Final;
29+
import org.spongepowered.asm.mixin.Mixin;
30+
import org.spongepowered.asm.mixin.Shadow;
31+
import org.spongepowered.asm.mixin.injection.At;
32+
import org.spongepowered.asm.mixin.injection.Redirect;
33+
34+
import net.minecraft.server.MinecraftServer;
35+
import net.minecraft.server.ServerTask;
36+
import net.minecraft.server.world.ServerWorld;
37+
import net.minecraft.util.NonBlockingThreadExecutor;
38+
import net.minecraft.world.dimension.DimensionType;
39+
40+
@Mixin(MinecraftServer.class)
41+
public abstract class MixinMinecraftServer extends NonBlockingThreadExecutor<ServerTask> {
42+
public MixinMinecraftServer(String name) {
43+
super(name);
44+
}
45+
46+
@Shadow
47+
@Final
48+
private Map<DimensionType, ServerWorld> worlds;
49+
50+
// Should get called once per loop, regardless of which if branch it takes.
51+
// @Inject(
52+
// method = "createWorlds",
53+
// slice = @Slice(
54+
// from = @At(value = "INVOKE", target = "java/util/Iterator.hasNext ()Z")
55+
// ),
56+
// at = @At(value = "JUMP", opcode = Opcodes.GOTO),
57+
// locals = LocalCapture.CAPTURE_FAILHARD
58+
// )
59+
// private void hookCreateWorlds(WorldSaveHandler worldSaveHandler, LevelProperties properties, LevelInfo levelInfo, WorldGenerationProgressListener worldGenerationProgressListener, CallbackInfo ci, ServerWorld serverWorld, ServerWorld serverWorld2, Iterator var7, DimensionType dimensionType) {
60+
// MinecraftForge.EVENT_BUS.post(new WorldEvent.Load(this.worlds.get(dimensionType)));
61+
// }
62+
63+
// Alternatively, mixin to the put call, and special case overworld.
64+
// Perhaps move the special case outside of the loop?
65+
@Redirect(method = "createWorlds", at = @At(value = "INVOKE", target = "java/util/Iterator.next ()Ljava/lang/Object;"))
66+
private Object proxyNextWorldToSpecialCaseOverworld(Iterator iterator) {
67+
DimensionType type = (DimensionType) iterator.next();
68+
69+
if (type == DimensionType.OVERWORLD) {
70+
MinecraftForge.EVENT_BUS.post(new WorldEvent.Load(this.worlds.get(type)));
71+
}
72+
73+
return type;
74+
}
75+
76+
@Redirect(method = "createWorlds", at = @At(value = "INVOKE", target = "java/util/Map.put (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", ordinal = 1))
77+
private Object proxyPutWorld(Map worlds, Object type, Object world) {
78+
worlds.put(type, world);
79+
MinecraftForge.EVENT_BUS.post(new WorldEvent.Load((ServerWorld) world));
80+
return world;
81+
}
82+
83+
// TODO: Should we Inject into ServerWorld.close instead? Currently, this follows Forge's patch location.
84+
@Redirect(method = "shutdown", at = @At(value = "INVOKE", target = "net/minecraft/server/world/ServerWorld.close ()V"))
85+
private void proxyClose(ServerWorld world) throws IOException {
86+
MinecraftForge.EVENT_BUS.post(new WorldEvent.Unload(world));
87+
world.close();
88+
}
89+
90+
@Shadow
91+
private int ticks;
92+
93+
// TODO: DimensionManager, and move this into a seperate module
94+
// @Inject(method = "createWorlds", at = @At(value = "HEAD"))
95+
// private void hookCreateWorldsForDimensionRegistration(CallbackInfo info) {
96+
// DimensionManager.fireRegister();
97+
// }
98+
99+
// @Redirect(method = "tickWorlds", at = @At(value = "INVOKE_STRING", target = "net/minecraft/util/profiler/DisableableProfiler.swap (Ljava/lang/String;)V", args = { "ldc=connection" }))
100+
// private void hookTickWorldsForDimensionUnload(DisableableProfiler profiler, String section) {
101+
// MinecraftServer server = (MinecraftServer) (Object) this;
102+
// profiler.swap("dim_unloading");
103+
// DimensionManager.unloadWorlds(server, this.ticks % 200);
104+
// profiler.swap(section);
105+
// }
106+
107+
// @Redirect(method = "getWorld", at = @At(value = "INVOKE", target = "java/util/Map.get (Ljava/lang/Object;)Ljava/lang/Object;"))
108+
// private Object hookGetWorld(Map worlds, Object type) {
109+
// MinecraftServer server = (MinecraftServer) (Object) this;
110+
// return DimensionManager.getWorld(server, type, true, true);
111+
// }
112+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/*
2+
* Minecraft Forge, Patchwork Project
3+
* Copyright (c) 2016-2019, 2019
4+
*
5+
* This library is free software; you can redistribute it and/or
6+
* modify it under the terms of the GNU Lesser General Public
7+
* License as published by the Free Software Foundation version 2.1
8+
* of the License.
9+
*
10+
* This library is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13+
* Lesser General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU Lesser General Public
16+
* License along with this library; if not, write to the Free Software
17+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18+
*/
19+
20+
package com.patchworkmc.mixin.event.world;
21+
22+
import java.util.function.BiFunction;
23+
24+
import net.minecraftforge.common.MinecraftForge;
25+
import net.minecraftforge.event.world.WorldEvent;
26+
import org.spongepowered.asm.mixin.Mixin;
27+
import org.spongepowered.asm.mixin.injection.At;
28+
import org.spongepowered.asm.mixin.injection.Inject;
29+
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
30+
31+
import net.minecraft.util.profiler.Profiler;
32+
import net.minecraft.world.chunk.ChunkManager;
33+
import net.minecraft.world.dimension.Dimension;
34+
import net.minecraft.world.dimension.DimensionType;
35+
import net.minecraft.world.level.LevelInfo;
36+
import net.minecraft.world.level.LevelProperties;
37+
import net.minecraft.world.World;
38+
import net.minecraft.server.world.ServerWorld;
39+
40+
import com.patchworkmc.impl.event.world.WorldEvents;
41+
42+
@Mixin(ServerWorld.class)
43+
public abstract class MixinServerWorld extends World {
44+
protected MixinServerWorld(LevelProperties levelProperties, DimensionType dimensionType, BiFunction<World, Dimension, ChunkManager> chunkManagerProvider, Profiler profiler, boolean isClient) {
45+
super(levelProperties, dimensionType, chunkManagerProvider, profiler, isClient);
46+
}
47+
48+
@Inject(method = "save", at = @At(value = "INVOKE", target = "net/minecraft/server/world/ServerChunkManager.save (Z)V"))
49+
private void hookSave(CallbackInfo info) {
50+
ServerWorld world = (ServerWorld) (Object) this;
51+
MinecraftForge.EVENT_BUS.post(new WorldEvent.Save(world));
52+
}
53+
54+
// TODO: consider adding a shift to before obtaining the ChunkManager to match forge more closely
55+
// I don't think it'll make much of a difference.
56+
@Inject(method = "init", cancellable = true, at = @At(value = "INVOKE", target = "net/minecraft/world/gen/chunk/ChunkGenerator.getBiomeSource ()Lnet/minecraft/world/biome/source/BiomeSource;"))
57+
private void hookInitForCreateWorldSpawn(LevelInfo levelInfo, CallbackInfo info) {
58+
ServerWorld world = (ServerWorld) (Object) this;
59+
60+
if (WorldEvents.onCreateWorldSpawn(world, levelInfo)) {
61+
info.cancel();
62+
}
63+
}
64+
}

0 commit comments

Comments
 (0)