Skip to content

Commit

Permalink
Add BM client cache bulk update packets.
Browse files Browse the repository at this point in the history
All Map's can now be encoded using the PacketCodec.
Also includes an improvement where the client-side cache will be reset
on each world load, just to make sure that values are not mixed up when
swapping servers on going to singleplayer.
  • Loading branch information
rubensworks committed Sep 29, 2014
1 parent 15e7e82 commit 32e299e
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 21 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package evilcraft.modcompat.bloodmagic;

import net.minecraftforge.common.MinecraftForge;
import cpw.mods.fml.common.FMLCommonHandler;
import evilcraft.Configs;
import evilcraft.IInitListener;
Expand All @@ -26,6 +27,7 @@ public void onInit(IInitListener.Step step) {
Configs.getInstance().configs.add(new BoundBloodDropConfig());
} else if(step == IInitListener.Step.INIT) {
FMLCommonHandler.instance().bus().register(ClientSoulNetworkHandler.getInstance());
MinecraftForge.EVENT_BUS.register(ClientSoulNetworkHandler.getInstance());
PacketHandler.register(UpdateSoulNetworkCachePacket.class);
PacketHandler.register(RequestSoulNetworkUpdatesPacket.class);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import java.util.Set;

import net.minecraft.server.MinecraftServer;
import net.minecraftforge.event.world.WorldEvent;
import WayofTime.alchemicalWizardry.api.soulNetwork.SoulNetworkHandler;

import com.google.common.collect.Maps;
Expand Down Expand Up @@ -35,7 +36,7 @@ private ClientSoulNetworkHandler() {
* Reset the instance.
*/
public static void reset() {
_instance = null;
getInstance().PLAYER_CACHE = Maps.newHashMap();
}

/**
Expand Down Expand Up @@ -108,10 +109,18 @@ public void onServerTick(ServerTickEvent event) {
}

private void sendUpdates(Map<String, Integer> toSend) {
// TODO: This can be made more efficient by grouping packets.
for(Map.Entry<String, Integer> entry : toSend.entrySet()) {
PacketHandler.sendToAll(new UpdateSoulNetworkCachePacket(entry.getKey(), entry.getValue()));
}
PacketHandler.sendToAll(new UpdateSoulNetworkCachePacket(toSend));
}

/**
* When a world is loaded.
* @param event the event.
*/
@SubscribeEvent(priority = EventPriority.NORMAL)
public void onWorldLoad(WorldEvent.Load event) {
if(event.world.isRemote) {
reset();
}
}

}
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
package evilcraft.modcompat.bloodmagic;

import java.util.Map;

import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.world.World;

import com.google.common.collect.Maps;

import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import evilcraft.network.CodecField;
Expand All @@ -16,10 +21,8 @@
*/
public class UpdateSoulNetworkCachePacket extends PacketCodec {

@CodecField
private String player;
@CodecField
private int essence;
@CodecField
private Map<String, Integer> playerEssences = Maps.newHashMap();

/**
* Creates a packet with no content
Expand All @@ -29,19 +32,19 @@ public UpdateSoulNetworkCachePacket() {
}

/**
* Creates a packet which contains the player name and amount of essence.
* @param player The data name.
* @param essence The amount of essence to update to.
* Creates a packet which contains the player names and amount of essence.
* @param playerEssences A map of players with their essence.
*/
public UpdateSoulNetworkCachePacket(String player, int essence) {
this.player = player;
this.essence = essence;
public UpdateSoulNetworkCachePacket(Map<String, Integer> playerEssences) {
this.playerEssences = playerEssences;
}

@Override
@SideOnly(Side.CLIENT)
public void actionClient(World world, EntityPlayer player) {
ClientSoulNetworkHandler.getInstance().setCurrentEssence(this.player, this.essence);
for(Map.Entry<String, Integer> entry : playerEssences.entrySet()) {
ClientSoulNetworkHandler.getInstance().setCurrentEssence(entry.getKey(), entry.getValue());
}
}

@Override
Expand Down
77 changes: 72 additions & 5 deletions src/main/java/evilcraft/network/PacketCodec.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
import java.util.Arrays;
import java.util.Comparator;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang3.ClassUtils;

import com.google.common.collect.Maps;
import com.google.common.io.ByteArrayDataInput;
Expand Down Expand Up @@ -82,6 +85,74 @@ public Object decode(ByteArrayDataInput input) {
return input.readFloat();
}
});

codecActions.put(Map.class, new ICodecAction() {

// Packet structure:
// Map length (int)
// --- end if length == 0
// Key class name (UTF)
// Value class name (UTF)
// for length
// key
// value

@SuppressWarnings({ "rawtypes", "unchecked" })
@Override
public void encode(Object object, ByteArrayDataOutput output) {
Map map = (Map) object;
output.writeInt(map.size());
Set<Map.Entry> entries = map.entrySet();
ICodecAction keyAction = null;
ICodecAction valueAction = null;
for(Map.Entry entry : entries) {
if(keyAction == null) {
keyAction = getAction(entry.getKey().getClass());
output.writeUTF(entry.getKey().getClass().getName());
}
if(valueAction == null) {
valueAction = getAction(entry.getValue().getClass());
output.writeUTF(entry.getValue().getClass().getName());
}
keyAction.encode(entry.getKey(), output);
valueAction.encode(entry.getValue(), output);
}
}

@SuppressWarnings({ "rawtypes", "unchecked" })
@Override
public Object decode(ByteArrayDataInput input) {
Map map = Maps.newHashMap();
int size = input.readInt();
if(size == 0) {
return map;
}
try {
ICodecAction keyAction = getAction(Class.forName(input.readUTF()));
ICodecAction valueAction = getAction(Class.forName(input.readUTF()));
for(int i = 0; i < size; i++) {
Object key = keyAction.decode(input);
Object value = valueAction.decode(input);
map.put(key, value);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return map;
}
});
}

protected static ICodecAction getAction(Class<?> clazz) {
if(ClassUtils.isPrimitiveWrapper(clazz)) {
clazz = ClassUtils.wrapperToPrimitive(clazz);
}
ICodecAction action = codecActions.get(clazz);
if(action == null) {
System.err.println("No ICodecAction was found for " + clazz
+ ". You should add one in PacketCodec.");
}
return action;
}

private void loopCodecFields(ICodecRunnable runnable) {
Expand All @@ -102,11 +173,7 @@ public int compare(Field o1, Field o2) {
for(final Field field : fields) {
if(field.isAnnotationPresent(CodecField.class)) {
Class<?> clazz = field.getType();
ICodecAction action = codecActions.get(clazz);
if(action == null) {
System.err.println("No ICodecAction was found for " + clazz
+ ". You should add one in PacketCodec.");
}
ICodecAction action = getAction(clazz);

// Make private fields temporarily accessible.
boolean accessible = field.isAccessible();
Expand Down

0 comments on commit 32e299e

Please sign in to comment.