Files
ThaumicEnergistics/src/main/java/thaumicenergistics/common/integration/tc/GolemHooks.java
T
Chris 373415c4c5 Backpacks & Integration
Added wifi backpack for Gather, Decanting, and Fill cores.
Fixes #265: Restored API call and marked as deprecated.
Fixed broken integration core.
2016-01-19 11:11:13 -05:00

590 lines
14 KiB
Java

package thaumicenergistics.common.integration.tc;
import java.util.HashMap;
import java.util.HashSet;
import net.minecraft.entity.DataWatcher;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import thaumcraft.common.entities.golems.EntityGolemBase;
import thaumicenergistics.api.entities.IGolemHookHandler;
import thaumicenergistics.api.entities.IGolemHookSyncRegistry;
import thaumicenergistics.common.utils.EffectiveSide;
import thaumicenergistics.common.utils.ThELog;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
public class GolemHooks
{
private static class DummyHookHandler
implements IGolemHookHandler
{
public DummyHookHandler()
{
}
@Override
public void addDefaultSyncEntries( final IGolemHookSyncRegistry syncRegistry )
{
}
@Override
public void bellLeftClicked( final EntityGolemBase golem, final Object handlerData, final ItemStack itemGolemPlacer,
final EntityPlayer player, final boolean dismantled,
final Side side )
{
}
@Override
public boolean canHandleInteraction( final EntityGolemBase golem, final Object handlerData, final EntityPlayer player, final Side side )
{
return false;
}
@Override
public Object customInteraction( final EntityGolemBase golem, final Object handlerData, final EntityPlayer player, final Side side )
{
return null;
}
@Override
public void golemTick( final EntityGolemBase golem, final Object serverHandlerData, final IGolemHookSyncRegistry syncData )
{
}
@Override
public boolean needsDynamicUpdates()
{
return false;
}
@Override
public boolean needsRenderer()
{
return false;
}
@Override
public Object readEntityFromNBT( final EntityGolemBase golem, final NBTTagCompound nbtTag )
{
return null;
}
@Override
public void renderGolem( final EntityGolemBase golem, final Object clientHandlerData, final double x, final double y, final double z,
final float partialElaspsedTick )
{
}
@Override
public Object setupGolem( final EntityGolemBase golem, final Object handlerData, final IGolemHookSyncRegistry syncData, final Side side )
{
return null;
}
@Override
public Object spawnGolemFromItemStack( final EntityGolemBase golem, final ItemStack itemGolemPlacer, final Side side )
{
return null;
}
@Override
public Object syncDataChanged( final IGolemHookSyncRegistry syncData, final Object clientHandlerData )
{
return null;
}
@Override
public void writeEntityNBT( final EntityGolemBase golem, final Object serverHandlerData, final NBTTagCompound nbtTag )
{
}
}
/**
* ID of the datawatcher field.
*/
private static final int DATAWATCHER_ID = 4;
/**
* Default sync values.
*/
private static final GolemSyncRegistry defaultSyncRegistry = new GolemSyncRegistry();
/**
* Internal handler used to track sync data.
*/
private static final DummyHookHandler internalHandler = new DummyHookHandler();
/**
* All hook handlers
*/
protected static final HashSet<IGolemHookHandler> registeredHandlers = new HashSet<IGolemHookHandler>();
/**
* Handlers that need to be called during tick event.
*/
protected static final HashSet<IGolemHookHandler> dynamicHandlers = new HashSet<IGolemHookHandler>();
/**
* Handlers that need to be called during render.
*/
protected static final HashSet<IGolemHookHandler> renderHandlers = new HashSet<IGolemHookHandler>();
/**
* Logs an exception when it occurs.
*
* @param hook
* @param handler
* @param e
*/
private static void logCaughtException( final String hook, final IGolemHookHandler handler, final Exception e )
{
if( handler != null )
{
if( e != null )
{
ThELog.warning( "Caught Exception During call to '" + hook + "' for handler '%s':", handler.getClass().getCanonicalName() );
ThELog.warning( e.toString() );
}
else
{
ThELog.warning( "Caught Unknown Exception During call to '" + hook + "' for handler '%s'", handler.getClass().getCanonicalName() );
}
}
else if( e != null )
{
ThELog.warning( "Caught Exception During call to null handler '" + hook + "':" );
ThELog.warning( e.toString() );
}
else
{
ThELog.warning( "Caught Unknown Exception During call to null handler '" + hook + "'" );
}
}
/**
* Hook for ItemGolemBell.onLeftClickEntity
*
* @param golem
* @param dropped
* @param player
* @param golemHandlerData
*/
public static void hook_Bell_OnLeftClickGolem( final EntityGolemBase golem, final ItemStack dropped, final EntityPlayer player,
final HashMap<IGolemHookHandler, Object> golemHandlerData )
{
// Get the dismantled status
boolean dismantled = player.isSneaking();
Side side = EffectiveSide.side();
for( IGolemHookHandler handler : registeredHandlers )
{
try
{
// Get the current handler data
Object handlerData = golemHandlerData.getOrDefault( handler, null );
// Call handler
handler.bellLeftClicked( golem, handlerData, dropped, player, dismantled, side );
}
catch( Exception e )
{
logCaughtException( "onBellLeftClick", handler, e );
}
}
}
/**
* Hook for EntityGolemBase.customInteraction
*
* @param golem
* @param player
* @param golemHandlerData
* @return
*/
public static boolean hook_CustomInteraction( final EntityGolemBase golem, final EntityPlayer player,
final HashMap<IGolemHookHandler, Object> golemHandlerData )
{
boolean interactionHandled = false;
Side side = EffectiveSide.side();
for( IGolemHookHandler handler : registeredHandlers )
{
try
{
// Get the current handler data
Object handlerData = golemHandlerData.getOrDefault( handler, null );
boolean hadData = ( handlerData != null );
// Call handler
interactionHandled |= handler.canHandleInteraction( golem, handlerData, player, side );
if( interactionHandled )
{
try
{
handlerData = handler.customInteraction( golem, handlerData, player, side );
// Update golem
if( handlerData == null )
{
if( hadData )
{
golemHandlerData.remove( handler );
}
}
else
{
golemHandlerData.put( handler, handlerData );
}
}
catch( Exception e )
{
logCaughtException( "customInteraction", handler, e );
}
}
}
catch( Exception e )
{
logCaughtException( "canHandleInteraction", handler, e );
}
}
if( interactionHandled && side == Side.SERVER )
{
golem.setupGolem();
}
return interactionHandled;
}
/**
* Hook for EntityGolemBase.entityInit
*
* @param golem
* @param golemHandlerData
*/
public static void hook_EntityInit( final EntityGolemBase golem, final HashMap<IGolemHookHandler, Object> golemHandlerData )
{
// Create a new sync registry
GolemSyncRegistry localRegistry = new GolemSyncRegistry();
localRegistry.copyDefaults( defaultSyncRegistry );
// Add to the handlers
golemHandlerData.put( internalHandler, localRegistry );
// Get the datawatcher
DataWatcher watcher = golem.getDataWatcher();
// Add datawatcher field.
watcher.addObject( DATAWATCHER_ID, localRegistry.mappingsToString() );
}
/**
* Hook for EntityGolemBase.onEntityUpdate.
* Keeps client handlers updated.
*
* @param golem
* @param golemHandlerData
*/
public static void hook_onEntityUpdate( final EntityGolemBase golem, final HashMap<IGolemHookHandler, Object> golemHandlerData )
{
// Get the sync registry
GolemSyncRegistry syncRegistry = (GolemSyncRegistry)golemHandlerData.get( internalHandler );
if( EffectiveSide.isServerSide() )
{
// Update handlers
for( IGolemHookHandler handler : dynamicHandlers )
{
handler.golemTick( golem, golemHandlerData.get( handler ), syncRegistry );
}
// Update data watcher
if( syncRegistry.hasChanged() )
{
golem.getDataWatcher().updateObject( DATAWATCHER_ID, syncRegistry.mappingsToString() );
}
return;
}
// Update sync ticks
++syncRegistry.clientSyncTicks;
// Have 20 ticks passed? (Roughly a full second if the game is not lagging)
if( syncRegistry.clientSyncTicks >= 20.0f )
{
// Reset the counter
syncRegistry.clientSyncTicks = 0.0f;
// Is the data out of sync?
String watcherString = golem.getDataWatcher().getWatchableObjectString( DATAWATCHER_ID );
if( !syncRegistry.hasChanged() && ( watcherString == syncRegistry.lastUpdatedFrom ) )
{
// Data is in sync
return;
}
// Read the sync data, and get the list of handlers to update
HashSet<IGolemHookHandler> handlersToUpdate = syncRegistry.readFromString( watcherString );
if( handlersToUpdate == null )
{
// No handlers to update
return;
}
// Inform each handler
for( IGolemHookHandler handler : handlersToUpdate )
{
try
{
// Get the current handler data
Object handlerData = golemHandlerData.getOrDefault( handler, null );
boolean hadData = ( handlerData != null );
// Call handler
handlerData = handler.syncDataChanged( syncRegistry, handlerData );
// Update golem
if( handlerData == null )
{
if( hadData )
{
golemHandlerData.remove( handler );
}
}
else
{
golemHandlerData.put( handler, handlerData );
}
}
catch( Exception e )
{
logCaughtException( "onSyncDataChanged", handler, e );
}
}
}
}
/**
* Hook for ItemGolemPlacer.spawnCreature
*
* @param golem
* @param itemGolemPlacer
* @param golemHandlerData
*/
public static void hook_Placer_SpawnGolem( final EntityGolemBase golem, final ItemStack itemGolemPlacer,
final HashMap<IGolemHookHandler, Object> golemHandlerData )
{
// Ensure the stack has an NBT tag
if( !itemGolemPlacer.hasTagCompound() )
{
return;
}
Side side = EffectiveSide.side();
// Inform each handler
for( IGolemHookHandler handler : registeredHandlers )
{
try
{
// Call handler
Object handlerData = handler.spawnGolemFromItemStack( golem, itemGolemPlacer, side );
// Update golem
if( handlerData != null )
{
golemHandlerData.put( handler, handlerData );
}
}
catch( Exception e )
{
logCaughtException( "spawnGolemFromItemStack", handler, e );
}
}
}
/**
* Hook for EntityGolemBase.readEntityFromNBT
*
* @param golem
* @param golemHandlerData
* @param nbt
*/
public static void hook_ReadEntityFromNBT( final EntityGolemBase golem, final HashMap<IGolemHookHandler, Object> golemHandlerData,
final NBTTagCompound nbt )
{
// Inform each handler
for( IGolemHookHandler handler : registeredHandlers )
{
try
{
// Get the current handler data
Object handlerData = golemHandlerData.getOrDefault( handler, null );
// Call handler
handlerData = handler.readEntityFromNBT( golem, nbt );
// Update golem
if( handlerData == null )
{
golemHandlerData.remove( handler );
}
else
{
golemHandlerData.put( handler, handlerData );
}
}
catch( Exception e )
{
logCaughtException( "readEntityFromNBT", handler, e );
}
}
}
/**
* Hook for RenderGolemBase.render
*
* @param golem
* @param x
* @param y
* @param z
* @param partialElaspsedTick
*/
@SideOnly(Side.CLIENT)
public static void hook_RenderGolem( final EntityGolemBase golem, final HashMap<IGolemHookHandler, Object> golemHandlerData, final double x,
final double y, final double z, final float partialElaspsedTick )
{
// Call each render handler
for( IGolemHookHandler handler : renderHandlers )
{
try
{
handler.renderGolem( golem, golemHandlerData.get( handler ), x, y, z, partialElaspsedTick );
}
catch( Exception e )
{
logCaughtException( "renderGolem", handler, e );
}
}
}
/**
* Hook for EntityGolemBase.setupGolem
*
* @param golem
* @param golemHandlerData
*/
public static void hook_SetupGolem( final EntityGolemBase golem, final HashMap<IGolemHookHandler, Object> golemHandlerData )
{
// Get the sync data
GolemSyncRegistry localRegistry = (GolemSyncRegistry)golemHandlerData.get( internalHandler );
Side side = EffectiveSide.side();
// Inform each handler
for( IGolemHookHandler handler : registeredHandlers )
{
try
{
// Get the current handler data
Object handlerData = golemHandlerData.getOrDefault( handler, null );
boolean hadData = ( handlerData != null );
// Call handler
handlerData = handler.setupGolem( golem, handlerData, localRegistry, side );
// Update golem
if( handlerData == null )
{
if( hadData )
{
golemHandlerData.remove( handler );
}
}
else
{
golemHandlerData.put( handler, handlerData );
}
}
catch( Exception e )
{
logCaughtException( "setupGolem", handler, e );
}
}
// Update data watcher
if( localRegistry.hasChanged() && side == Side.SERVER )
{
golem.getDataWatcher().updateObject( DATAWATCHER_ID, localRegistry.mappingsToString() );
}
}
/**
* Hook for EntityGolemBase.writeEntityToNBT
*
* @param golem
* @param golemHandlerData
* @param nbt
*/
public static void hook_WriteEntityToNBT( final EntityGolemBase golem, final HashMap<IGolemHookHandler, Object> golemHandlerData,
final NBTTagCompound nbt )
{
// Inform each handler
for( IGolemHookHandler handler : registeredHandlers )
{
try
{
// Get the current handler data
Object handlerData = golemHandlerData.getOrDefault( handler, null );
// Call handler
handler.writeEntityNBT( golem, handlerData, nbt );
}
catch( Exception e )
{
logCaughtException( "writeEntityNBT", handler, e );
}
}
}
/**
* Registers a handler.
*
* @param handler
*/
public static void registerHandler( final IGolemHookHandler handler )
{
// Add the handler
registeredHandlers.add( handler );
// Needs render?
if( handler.needsRenderer() )
{
renderHandlers.add( handler );
}
// Needs tick?
if( handler.needsDynamicUpdates() )
{
dynamicHandlers.add( handler );
}
// Register sync data
defaultSyncRegistry.canRegister = true;
handler.addDefaultSyncEntries( defaultSyncRegistry );
defaultSyncRegistry.canRegister = false;
}
}