-
Notifications
You must be signed in to change notification settings - Fork 38
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #496 from jchung01/memory-leaks
Fix OpenComputers/CodeChickenLib network leaks & EnderStorage frequency tracking
- Loading branch information
Showing
14 changed files
with
314 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
25 changes: 25 additions & 0 deletions
25
...ava/mod/acgaming/universaltweaks/mods/codechickenlib/mixin/UTPacketCustomClientMixin.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
package mod.acgaming.universaltweaks.mods.codechickenlib.mixin; | ||
|
||
import codechicken.lib.packet.PacketCustom; | ||
import net.minecraft.network.INetHandler; | ||
import org.apache.commons.lang3.Validate; | ||
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; | ||
|
||
// Courtesy of jchung01 | ||
@Mixin(value = PacketCustom.ClientInboundHandler.class, remap = false) | ||
public class UTPacketCustomClientMixin | ||
{ | ||
/** | ||
* This releases the COPIED ByteBuf that was created and assigned to PacketCustom.buf in the ctor. | ||
* @reason Release wrapped ByteBuf after whatever mod has handled the packet. | ||
*/ | ||
@Inject(method = "handle", at = @At(value = "INVOKE", target = "Lcodechicken/lib/packet/ICustomPacketHandler$IClientPacketHandler;handlePacket(Lcodechicken/lib/packet/PacketCustom;Lnet/minecraft/client/Minecraft;Lnet/minecraft/network/play/INetHandlerPlayClient;)V", shift = At.Shift.AFTER)) | ||
private void utReleaseClientBuf(INetHandler netHandler, String channel, PacketCustom packet, CallbackInfo ci) | ||
{ | ||
Validate.isTrue(packet.refCnt() == 1); | ||
packet.release(); | ||
} | ||
} |
26 changes: 26 additions & 0 deletions
26
...va/mod/acgaming/universaltweaks/mods/codechickenlib/mixin/UTPacketCustomReleaseMixin.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package mod.acgaming.universaltweaks.mods.codechickenlib.mixin; | ||
|
||
import codechicken.lib.packet.PacketCustom; | ||
import io.netty.channel.ChannelHandlerContext; | ||
import net.minecraftforge.fml.common.network.internal.FMLProxyPacket; | ||
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; | ||
|
||
// Courtesy of jchung01 | ||
@Mixin(value = PacketCustom.CustomInboundHandler.class, remap = false) | ||
public class UTPacketCustomReleaseMixin | ||
{ | ||
/** | ||
* This releases the ORIGINAL FMLProxyPacket payload that was passed into and copied by PacketCustom's constructor. | ||
* <p> | ||
* For S->C packets, some are reused and sent to multiple clients, so those packets are retained in {@link UTPacketCustomRetainMixin}. | ||
* @reason Release the message's payload after everything has been handled. | ||
*/ | ||
@Inject(method = "channelRead0(Lio/netty/channel/ChannelHandlerContext;Lnet/minecraftforge/fml/common/network/internal/FMLProxyPacket;)V", at = @At(value = "TAIL")) | ||
private void utReleasePayload(ChannelHandlerContext ctx, FMLProxyPacket msg, CallbackInfo ci) | ||
{ | ||
msg.payload().release(); | ||
} | ||
} |
98 changes: 98 additions & 0 deletions
98
...ava/mod/acgaming/universaltweaks/mods/codechickenlib/mixin/UTPacketCustomRetainMixin.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
package mod.acgaming.universaltweaks.mods.codechickenlib.mixin; | ||
|
||
import java.util.List; | ||
import java.util.function.Predicate; | ||
import codechicken.lib.packet.PacketCustom; | ||
import net.minecraft.entity.player.EntityPlayerMP; | ||
import net.minecraft.network.INetHandler; | ||
import net.minecraft.network.Packet; | ||
import net.minecraft.server.management.PlayerChunkMapEntry; | ||
import net.minecraft.world.World; | ||
import net.minecraft.world.WorldServer; | ||
import net.minecraftforge.fml.common.FMLCommonHandler; | ||
import net.minecraftforge.fml.common.network.handshake.NetworkDispatcher; | ||
import net.minecraftforge.fml.common.network.internal.FMLProxyPacket; | ||
import org.spongepowered.asm.mixin.Mixin; | ||
import org.spongepowered.asm.mixin.Shadow; | ||
import org.spongepowered.asm.mixin.Unique; | ||
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; | ||
|
||
/** | ||
* This mixin retains PacketCustom payloads, increasing the ref count by the number of players | ||
* that are to receive the packet. This is necessary as the payload is shared between all receivers | ||
* and each receiver releases the payload in {@link UTPacketCustomReleaseMixin}. | ||
* <p> | ||
* CCL doesn't fully utilize Forge's built-in networking, so this mixin adds the missing behavior that | ||
* {@link net.minecraftforge.fml.common.network.FMLOutboundHandler.OutboundTarget#selectNetworks} and | ||
* {@link net.minecraftforge.fml.common.network.FMLOutboundHandler#write} | ||
* would normally do to clean up packets. | ||
* @author jchung01 | ||
*/ | ||
@Mixin(value = PacketCustom.class, remap = false) | ||
public abstract class UTPacketCustomRetainMixin | ||
{ | ||
@Shadow | ||
public abstract boolean release(); | ||
|
||
@Inject(method = "sendToClients(Lnet/minecraft/network/Packet;)V", at = @At(value = "HEAD")) | ||
private static void utRetainForAllClients(Packet<INetHandler> packet, CallbackInfo ci) | ||
{ | ||
ut$retainForPlayers(packet, player -> true); | ||
} | ||
|
||
@Inject(method = "sendToAllAround", at = @At(value = "HEAD")) | ||
private static void utRetainForAllAround(Packet<INetHandler> packet, double x, double y, double z, double range, int dim, CallbackInfo ci) | ||
{ | ||
ut$retainForPlayers(packet, player -> { | ||
if (player.dimension != dim) return false; | ||
double dx = player.posX - x; | ||
double dy = player.posY - y; | ||
double dz = player.posZ - z; | ||
return dx * dx + dy * dy + dz * dz < range * range; | ||
}); | ||
} | ||
|
||
@Inject(method = "sendToDimension(Lnet/minecraft/network/Packet;I)V", at = @At(value = "HEAD")) | ||
private static void utRetainForAllInDimension(Packet<INetHandler> packet, int dim, CallbackInfo ci) | ||
{ | ||
ut$retainForPlayers(packet, player -> player.dimension == dim); | ||
} | ||
|
||
@Inject(method = "sendToChunk(Lnet/minecraft/network/Packet;Lnet/minecraft/world/World;II)V", at = @At(value = "HEAD")) | ||
private static void utRetainForAllInChunk(Packet<INetHandler> packet, World world, int chunkX, int chunkZ, CallbackInfo ci) | ||
{ | ||
PlayerChunkMapEntry playersInChunk = ((WorldServer) world).getPlayerChunkMap().getEntry(chunkX, chunkZ); | ||
if (playersInChunk != null) ut$retainForPlayers(packet, playersInChunk::containsPlayer); | ||
} | ||
|
||
@Inject(method = "sendToOps(Lnet/minecraft/network/Packet;)V", at = @At(value = "HEAD")) | ||
private static void utRetainForOps(Packet<INetHandler> packet, CallbackInfo ci) | ||
{ | ||
ut$retainForPlayers(packet, player -> FMLCommonHandler.instance().getMinecraftServerInstance().getPlayerList().canSendCommands(player.getGameProfile())); | ||
} | ||
|
||
/** | ||
* Release this buf after copying it, just to be safe. | ||
*/ | ||
@Inject(method = "toPacket", at = @At(value = "RETURN")) | ||
private void utReleaseOriginal(CallbackInfoReturnable<FMLProxyPacket> cir) | ||
{ | ||
this.release(); | ||
} | ||
|
||
@Unique | ||
private static void ut$retainForPlayers(Packet<INetHandler> packet, Predicate<EntityPlayerMP> condition) | ||
{ | ||
if (packet instanceof FMLProxyPacket) | ||
{ | ||
List<EntityPlayerMP> playerList = FMLCommonHandler.instance().getMinecraftServerInstance().getPlayerList().getPlayers(); | ||
// Check for null dispatchers like Forge's FMLOutboundHandler.OutboundTarget#selectNetworks does. | ||
Predicate<EntityPlayerMP> hasNetworkDispatcher = player -> player.connection.netManager.channel().attr(NetworkDispatcher.FML_DISPATCHER).get() != null; | ||
int retainCount = (int) (playerList.stream().filter(condition.and(hasNetworkDispatcher)).count() - 1); | ||
if (retainCount > 0) ((FMLProxyPacket) packet).payload().retain(retainCount); | ||
} | ||
} | ||
} |
25 changes: 25 additions & 0 deletions
25
...ava/mod/acgaming/universaltweaks/mods/codechickenlib/mixin/UTPacketCustomServerMixin.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
package mod.acgaming.universaltweaks.mods.codechickenlib.mixin; | ||
|
||
import codechicken.lib.packet.PacketCustom; | ||
import net.minecraft.network.INetHandler; | ||
import org.apache.commons.lang3.Validate; | ||
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; | ||
|
||
// Courtesy of jchung01 | ||
@Mixin(value = PacketCustom.ServerInboundHandler.class, remap = false) | ||
public class UTPacketCustomServerMixin | ||
{ | ||
/** | ||
* This releases the COPIED ByteBuf that was created and assigned to PacketCustom.buf in the ctor. | ||
* @reason Release wrapped ByteBuf after whatever mod has handled the packet. | ||
*/ | ||
@Inject(method = "handle", at = @At(value = "INVOKE", target = "Lcodechicken/lib/packet/ICustomPacketHandler$IServerPacketHandler;handlePacket(Lcodechicken/lib/packet/PacketCustom;Lnet/minecraft/entity/player/EntityPlayerMP;Lnet/minecraft/network/play/INetHandlerPlayServer;)V", shift = At.Shift.AFTER)) | ||
private void utReleaseServerBuf(INetHandler netHandler, String channel, PacketCustom packet, CallbackInfo ci) | ||
{ | ||
Validate.isTrue(packet.refCnt() == 1); | ||
packet.release(); | ||
} | ||
} |
45 changes: 45 additions & 0 deletions
45
src/main/java/mod/acgaming/universaltweaks/mods/enderstorage/mixin/UTFrequencyMixin.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
package mod.acgaming.universaltweaks.mods.enderstorage.mixin; | ||
|
||
import java.util.Objects; | ||
import codechicken.enderstorage.api.Frequency; | ||
import codechicken.lib.colour.EnumColour; | ||
import org.spongepowered.asm.mixin.Mixin; | ||
import org.spongepowered.asm.mixin.Overwrite; | ||
import org.spongepowered.asm.mixin.Shadow; | ||
|
||
// Courtesy of jchung01 | ||
@Mixin(value = Frequency.class, remap = false) | ||
public class UTFrequencyMixin | ||
{ | ||
@Shadow | ||
public EnumColour left; | ||
@Shadow | ||
public EnumColour middle; | ||
@Shadow | ||
public EnumColour right; | ||
@Shadow | ||
public String owner; | ||
|
||
/** | ||
* Add equals() override to fulfill Object equality contract. | ||
*/ | ||
@Override | ||
public boolean equals(Object o) | ||
{ | ||
if (this == o) return true; | ||
if (o == null || getClass() != o.getClass()) return false; | ||
Frequency that = (Frequency) o; | ||
return left == that.left && middle == that.middle && right == that.right && Objects.equals(owner, that.owner); | ||
} | ||
|
||
/** | ||
* @author jchung01 | ||
* @reason Use a more proper hashCode method. | ||
*/ | ||
@Override | ||
@Overwrite | ||
public int hashCode() | ||
{ | ||
return Objects.hash(left, middle, right, owner); | ||
} | ||
} |
Oops, something went wrong.