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