Skip to content

Commit 1814bd3

Browse files
committed
Reduce overhead of the PotentialSpawns event
1 parent 070b7b6 commit 1814bd3

File tree

2 files changed

+93
-0
lines changed

2 files changed

+93
-0
lines changed
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package org.embeddedt.modernfix.forge.mixin.perf.potential_spawns_alloc;
2+
3+
import net.minecraft.core.BlockPos;
4+
import net.minecraft.util.random.WeightedRandomList;
5+
import net.minecraft.world.entity.MobCategory;
6+
import net.minecraft.world.level.LevelAccessor;
7+
import net.minecraft.world.level.biome.MobSpawnSettings;
8+
import net.minecraftforge.event.ForgeEventFactory;
9+
import org.spongepowered.asm.mixin.Mixin;
10+
import org.spongepowered.asm.mixin.injection.At;
11+
import org.spongepowered.asm.mixin.injection.Redirect;
12+
13+
import java.util.List;
14+
15+
@Mixin(ForgeEventFactory.class)
16+
public class ForgeEventFactoryMixin {
17+
@Redirect(method = "getPotentialSpawns", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/random/WeightedRandomList;create(Ljava/util/List;)Lnet/minecraft/util/random/WeightedRandomList;"))
18+
private static WeightedRandomList<MobSpawnSettings.SpawnerData> reuseOldList(List<MobSpawnSettings.SpawnerData> items, LevelAccessor level, MobCategory category, BlockPos pos, WeightedRandomList<MobSpawnSettings.SpawnerData> oldList) {
19+
// Our patched version of PotentialSpawns will return the same list as unwrap() if no one mutated the list
20+
if(items == oldList.unwrap()) {
21+
return oldList;
22+
}
23+
return WeightedRandomList.create(items);
24+
}
25+
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
package org.embeddedt.modernfix.forge.mixin.perf.potential_spawns_alloc;
2+
3+
import net.minecraft.core.BlockPos;
4+
import net.minecraft.util.random.WeightedRandomList;
5+
import net.minecraft.world.entity.MobCategory;
6+
import net.minecraft.world.level.LevelAccessor;
7+
import net.minecraft.world.level.biome.MobSpawnSettings;
8+
import net.minecraftforge.event.world.WorldEvent;
9+
import org.spongepowered.asm.mixin.Final;
10+
import org.spongepowered.asm.mixin.Mixin;
11+
import org.spongepowered.asm.mixin.Mutable;
12+
import org.spongepowered.asm.mixin.Shadow;
13+
import org.spongepowered.asm.mixin.injection.At;
14+
import org.spongepowered.asm.mixin.injection.Inject;
15+
import org.spongepowered.asm.mixin.injection.Redirect;
16+
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
17+
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
18+
19+
import java.util.ArrayList;
20+
import java.util.Collection;
21+
import java.util.Collections;
22+
import java.util.List;
23+
24+
@Mixin(WorldEvent.PotentialSpawns.class)
25+
public class PotentialSpawnsMixin {
26+
@Shadow(remap = false) @Final @Mutable private List<MobSpawnSettings.SpawnerData> view;
27+
@Shadow(remap = false) @Final @Mutable private List<MobSpawnSettings.SpawnerData> list;
28+
29+
private static final ArrayList<MobSpawnSettings.SpawnerData> SENTINEL = new ArrayList<>();
30+
31+
@Redirect(method = "<init>", at = @At(value = "NEW", target = "java/util/ArrayList", ordinal = 1))
32+
private ArrayList<?> avoidListAlloc1() {
33+
return SENTINEL;
34+
}
35+
36+
@Redirect(method = "<init>", at = @At(value = "NEW", target = "java/util/ArrayList", ordinal = 0))
37+
private ArrayList<?> avoidListAlloc2(Collection c) {
38+
return SENTINEL;
39+
}
40+
41+
@Redirect(method = "<init>", at = @At(value = "INVOKE", target = "Ljava/util/Collections;unmodifiableList(Ljava/util/List;)Ljava/util/List;"))
42+
private List<?> avoidListAlloc3(List<?> l) {
43+
return null;
44+
}
45+
46+
@Inject(method = "<init>", at = @At("RETURN"))
47+
private void initializeSmartLists(LevelAccessor level, MobCategory category, BlockPos pos, WeightedRandomList<MobSpawnSettings.SpawnerData> oldList, CallbackInfo ci) {
48+
this.view = oldList.unwrap();
49+
this.list = null;
50+
}
51+
52+
private void mfix$populateList() {
53+
if(this.list == null) {
54+
this.list = new ArrayList<>(this.view);
55+
this.view = Collections.unmodifiableList(this.list);
56+
}
57+
}
58+
59+
@Inject(method = {"addSpawnerData" }, at = @At("HEAD"), remap = false)
60+
private void populateList(MobSpawnSettings.SpawnerData data, CallbackInfo ci) {
61+
mfix$populateList();
62+
}
63+
64+
@Inject(method = {"removeSpawnerData" }, at = @At("HEAD"), remap = false)
65+
private void populateList(MobSpawnSettings.SpawnerData data, CallbackInfoReturnable<Boolean> cir) {
66+
mfix$populateList();
67+
}
68+
}

0 commit comments

Comments
 (0)