/** * Copyright (c) Lambda Innovation, 2013-2015 * 本作品版权由Lambda Innovation所有。 * http://www.li-dev.cn/ * * This project is open-source, and it is distributed under * the terms of GNU General Public License. You can modify * and distribute freely as long as you follow the license. * 本项目是一个开源项目,且遵循GNU通用公共授权协议。 * 在遵照该协议的情况下,您可以自由传播和修改。 * http://www.gnu.org/licenses/gpl.html */ package cn.weaponry.api; import java.util.Map; import java.util.WeakHashMap; import net.minecraft.client.Minecraft; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; import net.minecraft.server.MinecraftServer; import net.minecraftforge.event.world.WorldEvent; import cn.annoreg.core.Registrant; import cn.annoreg.mc.RegEventHandler; import cn.annoreg.mc.RegEventHandler.Bus; import cpw.mods.fml.common.FMLCommonHandler; import cpw.mods.fml.common.eventhandler.SubscribeEvent; import cpw.mods.fml.common.gameevent.TickEvent.ClientTickEvent; import cpw.mods.fml.common.gameevent.TickEvent.Phase; import cpw.mods.fml.common.gameevent.TickEvent.RenderTickEvent; import cpw.mods.fml.common.gameevent.TickEvent.ServerTickEvent; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; /** * The class handling ItemInfo loading. * @author WeAthFolD */ @Registrant public class ItemInfoProxy { private static Proxy proxy; private interface Proxy { ItemInfo getInfo(EntityPlayer player); void tick(boolean isRemote); void clear(); } private static class SimpleProxy implements Proxy { ItemInfo client, server; @Override public ItemInfo getInfo(EntityPlayer player) { ItemInfo playerInfo = player.worldObj.isRemote ? client : server; if(playerInfo != null) { playerInfo.checkStack(); if(playerInfo.disposed || playerInfo.player != player) { playerInfo.onDisposed(); playerInfo = null; } } if(playerInfo == null) { ItemStack stack = player.getCurrentEquippedItem(); if(stack != null && stack.getItem() instanceof IItemInfoProvider) { //Type safe is guaranteed. playerInfo = new ItemInfo(player); } } //Update instance if(player.worldObj.isRemote) { client = playerInfo; } else { server = playerInfo; } // if(playerInfo != null) // playerInfo.player = player; return playerInfo; } @Override public void tick(boolean isRemote) { ItemInfo targ = isRemote ? client : server; if(targ != null) targ.tick(); } @Override public void clear() { client = server = null; } } private static class ServerProxy implements Proxy { Map<EntityPlayer, SimpleProxy> proxies = new WeakHashMap(); @Override public ItemInfo getInfo(EntityPlayer player) { SimpleProxy proxy = proxies.get(player); if(proxy == null) { proxy = new SimpleProxy(); proxies.put(player, proxy); } return proxy.getInfo(player); } @Override public void tick(boolean isRemote) { for(SimpleProxy sp : proxies.values()) { sp.tick(isRemote); } } @Override public void clear() { proxies.clear(); } } /** * Get the <code>ItemInfo</code> instance for current player. You will get different instance at client and server. * It is guaranteed the info corresponds to the current holding itemStack. * @param player * @return The ItemInfo if current stack is of item type IItemInfoProvider, or null */ public static ItemInfo getInfo(EntityPlayer player) { return getProxy().getInfo(player); } private static Proxy getProxy() { if(proxy == null) { if(FMLCommonHandler.instance().getSide() == Side.CLIENT) { proxy = new SimpleProxy(); } else { proxy = new ServerProxy(); } } return proxy; } @RegEventHandler(Bus.FML) public static class Ticker { @SubscribeEvent @SideOnly(Side.CLIENT) public void onClientTick(ClientTickEvent event) { if(event.phase == Phase.END) return; if(Minecraft.getMinecraft().thePlayer == null) return; getProxy().getInfo(Minecraft.getMinecraft().thePlayer); getProxy().tick(true); } @SubscribeEvent public void onServerTick(ServerTickEvent event) { if(event.phase == Phase.END) return; for(Object p : MinecraftServer.getServer().getConfigurationManager().playerEntityList) { EntityPlayer player = (EntityPlayer) p; getProxy().getInfo(player); } getProxy().tick(false); } @SubscribeEvent @SideOnly(Side.CLIENT) public void onRenderTick(RenderTickEvent event) { if(Minecraft.getMinecraft().thePlayer == null || event.phase == Phase.END) return; ItemInfo info = getProxy().getInfo(Minecraft.getMinecraft().thePlayer); if(info != null) { info.renderTick(); } } // Clear all the previously exist info instances to prevent collision @SubscribeEvent public void onWorldLoad(WorldEvent.Load event) { getProxy().clear(); } } }