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 }