    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}