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}