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 }