Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/main/java/fermiummixins/config/VanillaConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -528,6 +528,12 @@ public class VanillaConfig {
@Config.RequiresMcRestart
@MixinConfig.MixinToggle(earlyMixin = "mixins.fermiummixins.early.vanilla.blockstorageoptifine.json", defaultValue = false)
public boolean blockStorageOptifineLagFix = false;

@Config.Comment("A modern version of \"fixWorldEntityCleanup\" by FoamFix. Made because the one by FoamFix was rarely creating ConcurrentModificationException crashes due to being older than the forge code it fixed.")
@Config.Name("Unload Entities on empty world (Vanilla)")
@Config.RequiresMcRestart
@MixinConfig.MixinToggle(earlyMixin = "mixins.fermiummixins.early.vanilla.unloadentities.json", defaultValue = false)
public boolean patchUpdateEntitiesPatch = false;

private Set<Potion> tippedArrowBlacklistedPotions = null;
private List<String> particleRetainCollisionClasses = null;
Expand Down
17 changes: 17 additions & 0 deletions src/main/java/fermiummixins/mixin/vanilla/WorldAccessor.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package fermiummixins.mixin.vanilla;

import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.World;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;

import java.util.List;

@Mixin(World.class)
public interface WorldAccessor {
@Accessor("processingLoadedTiles")
void setProcessingLoadedTiles(boolean newValue);

@Accessor("tileEntitiesToBeRemoved")
List<TileEntity> getTileEntitiesToBeRemoved();
}
Original file line number Diff line number Diff line change
@@ -1,28 +1,33 @@
package fermiummixins.mixin.vanilla;

import net.minecraft.util.math.MathHelper;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import com.llamalad7.mixinextras.sugar.Local;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.world.WorldEntitySpawner;
import net.minecraft.world.WorldServer;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;

import java.util.Set;

/**
* Fix by Nischhelm
*/
@Mixin(WorldEntitySpawner.class)
public abstract class WorldEntitySpawner_LazyChunksMixin {

@Redirect(
@WrapOperation(
method = "findChunksForSpawning",
at = @At(value="INVOKE",target = "Lnet/minecraft/world/WorldServer;isAnyPlayerWithinRangeAt(DDDD)Z")
at = @At(value="INVOKE",target = "Ljava/util/Set;add(Ljava/lang/Object;)Z")
)
private boolean fermiummixins_vanillaWorldEntitySpawner_findChunksForSpawning(WorldServer instance, double x, double y, double z, double range) {
int x1 = MathHelper.floor(x);
int z1 = MathHelper.floor(z);

if(!((IWorldInvoker)instance).invokeIsAreaLoaded(x1 - 32, 0, z1 - 32, x1 + 32, 0, z1 + 32, true)) return true;
private boolean fermiummixins_vanillaWorldEntitySpawner_findChunksForSpawning(Set<ChunkPos> instance, Object obj, Operation<Boolean> original, @Local(argsOnly = true) WorldServer world) {
ChunkPos cpos = (ChunkPos) obj;
int x1 = cpos.x << 4 + 8;
int z1 = cpos.z << 4 + 8;

return instance.isAnyPlayerWithinRangeAt(x, y, z, range);
if(!((IWorldInvoker)world).invokeIsAreaLoaded(x1 - 32, 0, z1 - 32, x1 + 32, 0, z1 + 32, true))
return false;
return original.call(instance, obj);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package fermiummixins.mixin.vanilla;

import net.minecraft.entity.Entity;
import net.minecraft.profiler.Profiler;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.World;
import net.minecraft.world.WorldProvider;
import net.minecraft.world.WorldServer;
import net.minecraft.world.storage.ISaveHandler;
import net.minecraft.world.storage.WorldInfo;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;

import java.util.Collections;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Set;

@Mixin(WorldServer.class)
public abstract class WorldServer_UnloadEntitiesInEmptyWorld extends World {
protected WorldServer_UnloadEntitiesInEmptyWorld(ISaveHandler saveHandlerIn, WorldInfo info, WorldProvider providerIn, Profiler profilerIn, boolean client) {
super(saveHandlerIn, info, providerIn, profilerIn, client);
}

//Copied from FoamFix (patch from 2017), modified to not create rare Concurrent Modification Exceptions
@Inject(
method = "updateEntities",
at = @At(value = "RETURN", ordinal = 0)
)
public void fermiumMixins_vanillaWorldServer_updateEntities(CallbackInfo ci) {
this.profiler.startSection("entities");
this.profiler.endStartSection("remove");
this.loadedEntityList.removeAll(this.unloadedEntityList);

for (Entity entityToUnload : this.unloadedEntityList)
if (entityToUnload.addedToChunk && this.isChunkLoaded(entityToUnload.chunkCoordX, entityToUnload.chunkCoordZ, true))
this.getChunk(entityToUnload.chunkCoordX, entityToUnload.chunkCoordZ).removeEntity(entityToUnload);

this.unloadedEntityList.forEach(this::onEntityRemoved);

this.unloadedEntityList.clear();

this.profiler.endStartSection("blockEntities");

((WorldAccessor) this).setProcessingLoadedTiles(true); //FML Move above remove to prevent CMEs

List<TileEntity> tileEntitiesToBeRemoved = ((WorldAccessor) this).getTileEntitiesToBeRemoved();

if (!tileEntitiesToBeRemoved.isEmpty()) {
tileEntitiesToBeRemoved.forEach(TileEntity::onChunkUnload);

// forge: faster "contains" makes this removal much more efficient
Set<TileEntity> remove = Collections.newSetFromMap(new IdentityHashMap<>());
remove.addAll(tileEntitiesToBeRemoved);

this.tickableTileEntities.removeAll(remove);
this.loadedTileEntityList.removeAll(remove);
tileEntitiesToBeRemoved.clear();
}

this.profiler.endSection();
this.profiler.endSection();
}
}
1 change: 1 addition & 0 deletions src/main/java/fermiummixins/util/ModLoadedUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ public abstract class ModLoadedUtil {
public static final String ElenaiDodge_MODID = "elenaidodge";
public static final String FancyMenu_MODID = "fancymenu";
public static final String FirstAid_MODID = "firstaid";
public static final String FoamFix_MODID = "foamfix";
public static final String FoodExpansion_MODID = "foodexpansion";
public static final String ForgottenItems_MODID = "forgottenitems";
public static final String InfernalMobs_MODID = "infernalmobs";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"required": true,
"package": "fermiummixins.mixin",
"refmap": "mixins.fermiummixins.refmap.json",
"compatibilityLevel": "JAVA_8",
"target": "@env(DEFAULT)",
"minVersion": "0.8",
"mixins": [
"vanilla.WorldAccessor",
"vanilla.WorldServer_UnloadEntitiesInEmptyWorld"
]
}