001    package cpw.mods.fml.client.modloader;
002    
003    import java.util.Collection;
004    import java.util.Collections;
005    import java.util.Map;
006    import java.util.Map.Entry;
007    import java.util.logging.Level;
008    
009    import net.minecraft.client.Minecraft;
010    import net.minecraft.network.INetworkManager;
011    import net.minecraft.network.packet.NetHandler;
012    import net.minecraft.network.packet.Packet250CustomPayload;
013    import net.minecraft.src.BaseMod;
014    import net.minecraft.client.*;
015    import net.minecraft.client.entity.EntityClientPlayerMP;
016    import net.minecraft.client.multiplayer.NetClientHandler;
017    import net.minecraft.client.renderer.entity.Render;
018    import net.minecraft.client.renderer.entity.RenderManager;
019    import net.minecraft.client.settings.KeyBinding;
020    import net.minecraft.entity.Entity;
021    import net.minecraft.entity.player.EntityPlayer;
022    
023    import com.google.common.base.Equivalences;
024    import com.google.common.base.Supplier;
025    import com.google.common.base.Suppliers;
026    import com.google.common.collect.Iterables;
027    import com.google.common.collect.Iterators;
028    import com.google.common.collect.MapDifference;
029    import com.google.common.collect.MapDifference.ValueDifference;
030    import com.google.common.collect.MapMaker;
031    import com.google.common.collect.Maps;
032    import com.google.common.collect.Multimap;
033    import com.google.common.collect.Multimaps;
034    
035    import cpw.mods.fml.client.FMLClientHandler;
036    import cpw.mods.fml.client.registry.KeyBindingRegistry;
037    import cpw.mods.fml.client.registry.RenderingRegistry;
038    import cpw.mods.fml.common.FMLLog;
039    import cpw.mods.fml.common.Loader;
040    import cpw.mods.fml.common.modloader.BaseModProxy;
041    import cpw.mods.fml.common.modloader.IModLoaderSidedHelper;
042    import cpw.mods.fml.common.modloader.ModLoaderHelper;
043    import cpw.mods.fml.common.modloader.ModLoaderModContainer;
044    import cpw.mods.fml.common.network.EntitySpawnPacket;
045    import cpw.mods.fml.common.registry.EntityRegistry.EntityRegistration;
046    
047    public class ModLoaderClientHelper implements IModLoaderSidedHelper
048    {
049        public static int obtainBlockModelIdFor(BaseMod mod, boolean inventoryRenderer)
050        {
051            int renderId=RenderingRegistry.getNextAvailableRenderId();
052            ModLoaderBlockRendererHandler bri=new ModLoaderBlockRendererHandler(renderId, inventoryRenderer, mod);
053            RenderingRegistry.registerBlockHandler(bri);
054            return renderId;
055        }
056    
057    
058        public static void handleFinishLoadingFor(ModLoaderModContainer mc, Minecraft game)
059        {
060            FMLLog.finer("Handling post startup activities for ModLoader mod %s", mc.getModId());
061            BaseMod mod = (BaseMod) mc.getMod();
062    
063            Map<Class<? extends Entity>, Render> renderers = Maps.newHashMap(RenderManager.instance.entityRenderMap);
064    
065            try
066            {
067                FMLLog.finest("Requesting renderers from basemod %s", mc.getModId());
068                mod.addRenderer(renderers);
069                FMLLog.finest("Received %d renderers from basemod %s", renderers.size(), mc.getModId());
070            }
071            catch (Exception e)
072            {
073                FMLLog.log(Level.SEVERE, e, "A severe problem was detected with the mod %s during the addRenderer call. Continuing, but expect odd results", mc.getModId());
074            }
075    
076            MapDifference<Class<? extends Entity>, Render> difference = Maps.difference(RenderManager.instance.entityRenderMap, renderers, Equivalences.identity());
077    
078            for ( Entry<Class<? extends Entity>, Render> e : difference.entriesOnlyOnLeft().entrySet())
079            {
080                FMLLog.warning("The mod %s attempted to remove an entity renderer %s from the entity map. This will be ignored.", mc.getModId(), e.getKey().getName());
081            }
082    
083            for (Entry<Class<? extends Entity>, Render> e : difference.entriesOnlyOnRight().entrySet())
084            {
085                FMLLog.finest("Registering ModLoader entity renderer %s as instance of %s", e.getKey().getName(), e.getValue().getClass().getName());
086                RenderingRegistry.registerEntityRenderingHandler(e.getKey(), e.getValue());
087            }
088    
089            for (Entry<Class<? extends Entity>, ValueDifference<Render>> e : difference.entriesDiffering().entrySet())
090            {
091                FMLLog.finest("Registering ModLoader entity rendering override for %s as instance of %s", e.getKey().getName(), e.getValue().rightValue().getClass().getName());
092                RenderingRegistry.registerEntityRenderingHandler(e.getKey(), e.getValue().rightValue());
093            }
094    
095            try
096            {
097                mod.registerAnimation(game);
098            }
099            catch (Exception e)
100            {
101                FMLLog.log(Level.SEVERE, e, "A severe problem was detected with the mod %s during the registerAnimation call. Continuing, but expect odd results", mc.getModId());
102            }
103        }
104    
105        public ModLoaderClientHelper(Minecraft client)
106        {
107            this.client = client;
108            ModLoaderHelper.sidedHelper = this;
109            keyBindingContainers = Multimaps.newMultimap(Maps.<ModLoaderModContainer, Collection<ModLoaderKeyBindingHandler>>newHashMap(), new Supplier<Collection<ModLoaderKeyBindingHandler>>()
110            {
111                @Override
112                public Collection<ModLoaderKeyBindingHandler> get()
113                {
114                    return Collections.singleton(new ModLoaderKeyBindingHandler());
115                }
116            });
117        }
118    
119        private Minecraft client;
120        private static Multimap<ModLoaderModContainer, ModLoaderKeyBindingHandler> keyBindingContainers;
121    
122        @Override
123        public void finishModLoading(ModLoaderModContainer mc)
124        {
125            handleFinishLoadingFor(mc, client);
126        }
127    
128    
129        public static void registerKeyBinding(BaseModProxy mod, KeyBinding keyHandler, boolean allowRepeat)
130        {
131            ModLoaderModContainer mlmc = (ModLoaderModContainer) Loader.instance().activeModContainer();
132            ModLoaderKeyBindingHandler handler = Iterables.getOnlyElement(keyBindingContainers.get(mlmc));
133            handler.setModContainer(mlmc);
134            handler.addKeyBinding(keyHandler, allowRepeat);
135            KeyBindingRegistry.registerKeyBinding(handler);
136        }
137    
138    
139        @Override
140        public Object getClientGui(BaseModProxy mod, EntityPlayer player, int ID, int x, int y, int z)
141        {
142            return ((net.minecraft.src.BaseMod)mod).getContainerGUI((EntityClientPlayerMP) player, ID, x, y, z);
143        }
144    
145    
146        @Override
147        public Entity spawnEntity(BaseModProxy mod, EntitySpawnPacket input, EntityRegistration er)
148        {
149            return ((net.minecraft.src.BaseMod)mod).spawnEntity(er.getModEntityId(), client.theWorld, input.scaledX, input.scaledY, input.scaledZ);
150        }
151    
152    
153        @Override
154        public void sendClientPacket(BaseModProxy mod, Packet250CustomPayload packet)
155        {
156            ((net.minecraft.src.BaseMod)mod).clientCustomPayload(client.thePlayer.sendQueue, packet);
157        }
158    
159        private Map<INetworkManager,NetHandler> managerLookups = new MapMaker().weakKeys().weakValues().makeMap();
160        @Override
161        public void clientConnectionOpened(NetHandler netClientHandler, INetworkManager manager, BaseModProxy mod)
162        {
163            managerLookups.put(manager, netClientHandler);
164            ((BaseMod)mod).clientConnect((NetClientHandler)netClientHandler);
165        }
166    
167    
168        @Override
169        public boolean clientConnectionClosed(INetworkManager manager, BaseModProxy mod)
170        {
171            if (managerLookups.containsKey(manager))
172            {
173                ((BaseMod)mod).clientDisconnect((NetClientHandler) managerLookups.get(manager));
174                return true;
175            }
176            return false;
177        }
178    }