Skip to content

Commit

Permalink
fix memory leak (trueagi-io#28)
Browse files Browse the repository at this point in the history
  • Loading branch information
noskill authored Dec 14, 2022
1 parent b1c74ae commit fecd3c0
Show file tree
Hide file tree
Showing 6 changed files with 150 additions and 9 deletions.
19 changes: 11 additions & 8 deletions src/main/java/io/singularitynet/Server/ServerStateMachine.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@

import io.singularitynet.*;
import io.singularitynet.MissionHandlers.MissionBehaviour;
import io.singularitynet.events.ServerEntityEventsVereya;
import io.singularitynet.projectmalmo.*;
import io.singularitynet.utils.SchemaHelper;
import io.singularitynet.utils.ScreenHelper;
import jakarta.xml.bind.JAXBElement;
import jakarta.xml.bind.JAXBException;

import net.fabricmc.fabric.api.event.lifecycle.v1.ServerEntityEvents;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents;
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;
Expand All @@ -40,6 +40,7 @@
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.ActionResult;
import net.minecraft.world.GameMode;
import net.minecraft.world.GameRules;
import net.minecraft.world.World;
Expand Down Expand Up @@ -84,11 +85,11 @@ public ServerStateMachine(ServerState initialState, MissionInit minit, Minecraft
// Register ourself on the event busses, so we can harness the server tick:
ServerTickEvents.END_SERVER_TICK.register(s -> this.onServerTick(s));
ServerLifecycleEvents.SERVER_STOPPED.register(s -> this.onServerStopped(s));
ServerEntityEvents.ENTITY_LOAD.register((e, w) -> this.onGetPotentialSpawns(e, w));
ServerEntityEventsVereya.BEFORE_ENTITY_ADD.register((e, w) -> this.onGetPotentialSpawns(e, w));
}

/** Used to prevent spawning in our world.*/
public void onGetPotentialSpawns(Entity entity, ServerWorld world)
public ActionResult onGetPotentialSpawns(Entity entity, ServerWorld world)
{
// Decide whether or not to allow spawning.
// We shouldn't allow spawning unless it has been specifically turned on - whether
Expand All @@ -114,24 +115,26 @@ public void onGetPotentialSpawns(Entity entity, ServerWorld world)
if (mob.value().toLowerCase().equals(mobName.toLowerCase())) { allowed = true; }
}
if (!allowed) {
if (entity.isPlayer()) return;
if (!entity.isLiving()) return;
if (entity.isPlayer()) return ActionResult.PASS;
if (!entity.isLiving()) return ActionResult.PASS;
LOGGER.trace("removing mob " + mobName + ": it's disabled");
entity.remove(Entity.RemovalReason.DISCARDED);
return;
return ActionResult.FAIL;
}
}
}
// Cancel spawn event:
if (!allowSpawning) {
if (!entity.isLiving()) return;
if (!entity.isLiving()) return ActionResult.PASS;
LOGGER.trace("removing mob " + mobName + " : spawning is disabled");
if (entity.isPlayer()) {
LOGGER.info("not removing player " + ((ServerPlayerEntity)entity).getName().getString());
return;
return ActionResult.PASS;
}
entity.remove(Entity.RemovalReason.DISCARDED);
return ActionResult.FAIL;
}
return ActionResult.PASS;
}

private void onServerStopped(MinecraftServer s){
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package io.singularitynet.events;

import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.EventFactory;
import net.minecraft.entity.Entity;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.ActionResult;
import net.minecraft.util.profiler.Profiler;

public interface ServerEntityEventsVereya {

/**
* Called when an Entity is about to be loaded into a ServerWorld.
*
* <p>Can be used to cancel entity loading.
*/
public static final Event<ServerEntityEventsVereya> BEFORE_ENTITY_LOAD = EventFactory.createArrayBacked(ServerEntityEventsVereya.class, callbacks -> (entity, world) -> {
if (EventFactory.isProfilingEnabled()) {
final Profiler profiler = world.getProfiler();
profiler.push("fabricServerEntityLoadBefore");

for (ServerEntityEventsVereya callback : callbacks) {
profiler.push(EventFactory.getHandlerName(callback));
ActionResult result = callback.interact(entity, world);
profiler.pop();
if (result != ActionResult.PASS) {
return result;
}
}
profiler.pop();
} else {
for (ServerEntityEventsVereya callback : callbacks) {
ActionResult result = callback.interact(entity, world);
if (result != ActionResult.PASS) {
return result;
}
}
}
return ActionResult.PASS;
});

public static final Event<ServerEntityEventsVereya> BEFORE_ENTITY_ADD = EventFactory.createArrayBacked(ServerEntityEventsVereya.class, callbacks -> (entity, world) -> {
if (EventFactory.isProfilingEnabled()) {
final Profiler profiler = world.getProfiler();
profiler.push("fabricServerEntityAddBefore");

for (ServerEntityEventsVereya callback : callbacks) {
profiler.push(EventFactory.getHandlerName(callback));
ActionResult result = callback.interact(entity, world);
profiler.pop();
if (result != ActionResult.PASS) {
return result;
}
}
profiler.pop();
} else {
for (ServerEntityEventsVereya callback : callbacks) {
ActionResult result = callback.interact(entity, world);
if (result != ActionResult.PASS) {
return result;
}
}
}
return ActionResult.PASS;
});

ActionResult interact( Entity entity, ServerWorld world);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package io.singularitynet.mixin;

import net.minecraft.entity.Entity;
import net.minecraft.server.world.ServerEntityManager;
import net.minecraft.world.entity.EntityLike;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Invoker;

@Mixin(ServerEntityManager.class)
public interface ServerEntityManagerMixin<T extends EntityLike> {

@Invoker("stopTracking")
public void stopTracking(T entity);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package io.singularitynet.mixin;

import io.singularitynet.events.ServerEntityEventsVereya;
import net.minecraft.entity.Entity;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.ActionResult;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;

@Mixin(targets = "net/minecraft/server/world/ServerWorld$ServerEntityHandler")
abstract class ServerWorldEntityLoaderMixin {
// final synthetic Lnet/minecraft/server/world/ServerWorld; field_26936
@SuppressWarnings("ShadowTarget")
@Shadow
@Final
private ServerWorld field_26936;

@Inject(method = "startTracking(Lnet/minecraft/entity/Entity;)V", at = @At("HEAD"), cancellable = true)
private void invokeEntityLoadEvent(Entity entity, CallbackInfo ci) {
ActionResult result = ServerEntityEventsVereya.BEFORE_ENTITY_LOAD.invoker().interact(entity, this.field_26936);
if (result == ActionResult.FAIL) {
ci.cancel();
}
}
}
26 changes: 26 additions & 0 deletions src/main/java/io/singularitynet/mixin/ServerWorldMixin.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package io.singularitynet.mixin;

import io.singularitynet.events.ServerEntityEventsVereya;
import net.minecraft.entity.Entity;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.ActionResult;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;

@Mixin(ServerWorld.class)
class ServerWorldMixin {

@Inject(method = "Lnet/minecraft/server/world/ServerWorld;addEntity(Lnet/minecraft/entity/Entity;)Z", at = @At("HEAD"), cancellable = true)
void invokeEntityAddEvent(Entity entity, CallbackInfoReturnable<Boolean> cir) {
ActionResult result = ServerEntityEventsVereya.BEFORE_ENTITY_ADD.invoker().interact(entity, (ServerWorld)(Object)this);
if (result == ActionResult.FAIL) {
cir.cancel();
}
}
}

3 changes: 2 additions & 1 deletion src/main/resources/vereya.mixins.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
"mixins": [],
"client": [
"TitleScreenMixin", "SessionMixin", "MinecraftClientMixin", "GameOptionsMixin",
"KeyBindingMixin", "MouseMixin", "InGameHudMixin"
"KeyBindingMixin", "MouseMixin", "InGameHudMixin", "ServerWorldEntityLoaderMixin",
"ServerEntityManagerMixin", "ServerWorldMixin"
],
"server": [],
"injectors": {
Expand Down

0 comments on commit fecd3c0

Please sign in to comment.