001package cpw.mods.fml.client.modloader;
002
003import java.util.Collection;
004import java.util.Collections;
005import java.util.Map;
006import java.util.Map.Entry;
007import java.util.logging.Level;
008
009import net.minecraft.client.Minecraft;
010import net.minecraft.network.INetworkManager;
011import net.minecraft.network.packet.NetHandler;
012import net.minecraft.network.packet.Packet250CustomPayload;
013import net.minecraft.src.BaseMod;
014import net.minecraft.client.*;
015import net.minecraft.client.entity.EntityClientPlayerMP;
016import net.minecraft.client.multiplayer.NetClientHandler;
017import net.minecraft.client.renderer.entity.Render;
018import net.minecraft.client.renderer.entity.RenderManager;
019import net.minecraft.client.settings.KeyBinding;
020import net.minecraft.entity.Entity;
021import net.minecraft.entity.player.EntityPlayer;
022
023import com.google.common.base.Equivalences;
024import com.google.common.base.Supplier;
025import com.google.common.base.Suppliers;
026import com.google.common.collect.Iterables;
027import com.google.common.collect.Iterators;
028import com.google.common.collect.MapDifference;
029import com.google.common.collect.MapDifference.ValueDifference;
030import com.google.common.collect.MapMaker;
031import com.google.common.collect.Maps;
032import com.google.common.collect.Multimap;
033import com.google.common.collect.Multimaps;
034
035import cpw.mods.fml.client.FMLClientHandler;
036import cpw.mods.fml.client.registry.KeyBindingRegistry;
037import cpw.mods.fml.client.registry.RenderingRegistry;
038import cpw.mods.fml.common.FMLLog;
039import cpw.mods.fml.common.Loader;
040import cpw.mods.fml.common.modloader.BaseModProxy;
041import cpw.mods.fml.common.modloader.IModLoaderSidedHelper;
042import cpw.mods.fml.common.modloader.ModLoaderHelper;
043import cpw.mods.fml.common.modloader.ModLoaderModContainer;
044import cpw.mods.fml.common.network.EntitySpawnPacket;
045import cpw.mods.fml.common.registry.EntityRegistry.EntityRegistration;
046
047public 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.log(mc.getModId(), Level.FINE, "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.log(mc.getModId(), Level.FINEST, "Requesting renderers from basemod %s", mc.getModId());
068            mod.addRenderer(renderers);
069            FMLLog.log(mc.getModId(), Level.FINEST, "Received %d renderers from basemod %s", renderers.size(), mc.getModId());
070        }
071        catch (Exception e)
072        {
073            FMLLog.log(mc.getModId(), 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.log(mc.getModId(), Level.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.log(mc.getModId(), Level.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.log(mc.getModId(), Level.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(mc.getModId(), 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}