mirror of
https://github.com/GTNewHorizons/ThaumicEnergistics.git
synced 2026-10-26 14:33:46 +00:00
Cleaned up some ASM transformation code. Renamed model and texture of golem Addon to golem Backpack Fixed bug where storage bus did not work when placed after jar was placed. Added wifi backpack for Essentia core. Fixed GUI based dupe bug. Fixed multiple issues with the Arcane assembler: GUI desync, invalid network state. Golem backpack pearl now responds to out-of-range and if golem is disabled(Fetter). Fixed issue where the last pattern on a knowledge core could not be erased.
627 lines
15 KiB
Java
627 lines
15 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 int DATAWATCHER_ID = -1;
|
|
|
|
/**
|
|
* 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();
|
|
|
|
// Has the ID been set?
|
|
if( DATAWATCHER_ID == -1 )
|
|
{
|
|
// Set the ID to the next available
|
|
for( int i = 4; i < 31; ++i )
|
|
{
|
|
try
|
|
{
|
|
// Add the object
|
|
watcher.addObject( DATAWATCHER_ID, localRegistry.mappingsToString() );
|
|
|
|
// Object was added
|
|
DATAWATCHER_ID = i;
|
|
return;
|
|
}
|
|
catch( IllegalArgumentException e )
|
|
{
|
|
}
|
|
}
|
|
|
|
// If execution makes it this far, there were no available ID's :(
|
|
DATAWATCHER_ID = -2;
|
|
ThELog.warning( "Golem Hook API is unable to register channel for sync data." );
|
|
return;
|
|
}
|
|
else if( DATAWATCHER_ID > 0 )
|
|
{
|
|
// 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() )
|
|
{
|
|
if( DATAWATCHER_ID > 0 )
|
|
{
|
|
golem.getDataWatcher().updateObject( DATAWATCHER_ID, syncRegistry.mappingsToString() );
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
if( DATAWATCHER_ID < 0 )
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Update sync ticks
|
|
++syncRegistry.clientSyncTicks;
|
|
|
|
// Have 20 ticks passed? (Roughly a full second if the game is not lagging)
|
|
if( syncRegistry.clientSyncTicks >= 30.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;
|
|
}
|
|
|
|
}
|