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 }