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