2017-05-29 09:10:40 +00:00
package net.minecraftforge.debug ;
2016-01-12 00:04:22 +00:00
2017-05-26 20:51:18 +00:00
import net.minecraft.entity.player.EntityPlayer ;
2016-02-15 22:30:24 +00:00
import net.minecraft.init.Blocks ;
2016-01-12 00:04:22 +00:00
import net.minecraft.init.Items ;
2017-02-24 01:09:02 +00:00
import net.minecraft.item.Item ;
import net.minecraft.item.ItemStack ;
2016-01-12 00:04:22 +00:00
import net.minecraft.nbt.NBTBase ;
2016-12-21 19:11:25 +00:00
import net.minecraft.nbt.NBTTagCompound ;
2016-01-12 00:04:22 +00:00
import net.minecraft.tileentity.TileEntity ;
import net.minecraft.util.EnumFacing ;
import net.minecraft.util.ResourceLocation ;
2017-05-26 20:51:18 +00:00
import net.minecraft.util.math.Vec3d ;
import net.minecraft.util.text.TextComponentString ;
import net.minecraft.util.text.TextFormatting ;
import net.minecraft.village.Village ;
2016-01-12 00:04:22 +00:00
import net.minecraftforge.common.MinecraftForge ;
import net.minecraftforge.common.capabilities.Capability ;
import net.minecraftforge.common.capabilities.Capability.IStorage ;
import net.minecraftforge.common.capabilities.CapabilityInject ;
import net.minecraftforge.common.capabilities.CapabilityManager ;
2016-12-21 19:11:25 +00:00
import net.minecraftforge.common.capabilities.ICapabilitySerializable ;
2016-01-12 00:04:22 +00:00
import net.minecraftforge.event.AttachCapabilitiesEvent ;
import net.minecraftforge.event.entity.player.PlayerInteractEvent ;
import net.minecraftforge.fml.common.Mod ;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent ;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent ;
2017-05-26 20:51:18 +00:00
import net.minecraftforge.fml.common.gameevent.TickEvent ;
2017-05-29 09:10:40 +00:00
import org.apache.logging.log4j.Logger ;
import javax.annotation.Nonnull ;
import javax.annotation.Nullable ;
import java.util.List ;
2016-11-17 18:44:31 +00:00
2016-11-22 20:12:13 +00:00
@Mod ( modid = " forge.testcapmod " , name = " Forge TestCapMod " , version = " 1.0 " , acceptableRemoteVersions = " * " )
2016-01-12 00:04:22 +00:00
public class TestCapabilityMod
{
// A Holder/Marker for if this capability is installed.
// MUST be Static final doesn't matter but is suggested to prevent
// you from overriding it elsewhere.
// As Annotations and generic's are erased/unload at runtime this
// does NOT create a hard dependency on the class.
@CapabilityInject ( IExampleCapability . class )
private static final Capability < IExampleCapability > TEST_CAP = null ;
2017-05-29 09:10:40 +00:00
private static Logger logger ;
2016-01-12 00:04:22 +00:00
@Mod.EventHandler
public void preinit ( FMLPreInitializationEvent evt )
{
2017-05-29 09:10:40 +00:00
logger = evt . getModLog ( ) ;
2016-01-12 00:04:22 +00:00
// If you are a API, provide register your capability ASAP.
// You MUST supply a default save handler and a default implementation
// If you are a CONSUMER of the capability DO NOT register it. Only APIs should.
2017-05-29 09:10:40 +00:00
CapabilityManager . INSTANCE . register ( IExampleCapability . class , new Storage ( ) , DefaultImpl . class ) ;
2016-01-12 00:04:22 +00:00
MinecraftForge . EVENT_BUS . register ( this ) ;
}
@SubscribeEvent
2016-04-05 00:58:46 +00:00
public void onInteract ( PlayerInteractEvent . LeftClickBlock event )
2016-01-12 00:04:22 +00:00
{
2017-05-29 09:10:40 +00:00
if ( event . getItemStack ( ) . getItem ( ) ! = Items . STICK )
{
return ;
}
2016-01-12 00:04:22 +00:00
// This is just a example of how to interact with the TE, note the strong type binding that getCapability has
2016-03-24 08:44:52 +00:00
TileEntity te = event . getWorld ( ) . getTileEntity ( event . getPos ( ) ) ;
if ( te ! = null & & te . hasCapability ( TEST_CAP , event . getFace ( ) ) )
2016-01-12 00:04:22 +00:00
{
event . setCanceled ( true ) ;
2016-03-24 08:44:52 +00:00
IExampleCapability inv = te . getCapability ( TEST_CAP , event . getFace ( ) ) ;
2017-05-29 09:10:40 +00:00
logger . info ( " Hi I'm a " + inv . getOwnerType ( ) ) ;
2016-01-12 00:04:22 +00:00
}
2016-12-21 19:11:25 +00:00
if ( event . getWorld ( ) . getBlockState ( event . getPos ( ) ) . getBlock ( ) = = Blocks . DIRT & & event . getItemStack ( ) . hasCapability ( TEST_CAP , null ) )
2016-02-15 22:30:24 +00:00
{
2016-12-21 19:11:25 +00:00
IExampleCapability cap = event . getItemStack ( ) . getCapability ( TEST_CAP , null ) ;
2016-12-21 23:52:30 +00:00
event . getEntityPlayer ( ) . sendMessage ( new TextComponentString ( ( cap . getVal ( ) ? TextFormatting . GREEN : TextFormatting . RED ) + " " + TextFormatting . ITALIC + " TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST " ) ) ;
2016-02-15 22:30:24 +00:00
event . setCanceled ( true ) ;
}
2016-01-12 00:04:22 +00:00
}
2016-12-21 19:11:25 +00:00
@SubscribeEvent
public void onInteractItem ( PlayerInteractEvent . RightClickItem event )
{
2017-05-29 09:10:40 +00:00
if ( ! event . getEntityPlayer ( ) . isSneaking ( ) )
{
return ;
}
2016-12-21 19:11:25 +00:00
if ( event . getItemStack ( ) . hasCapability ( TEST_CAP , null ) )
{
IExampleCapability cap = event . getItemStack ( ) . getCapability ( TEST_CAP , null ) ;
cap . toggleVal ( ) ;
2017-05-29 09:10:40 +00:00
logger . info ( " Test value is now: " + ( cap . getVal ( ) ? " TRUE " : " FALSE " ) ) ;
2016-12-21 19:11:25 +00:00
}
}
2016-01-12 00:04:22 +00:00
// Example of having this annotation on a method, this will be called when the capability is present.
// You could do something like register event handlers to attach these capabilities to objects, or
// setup your factory, who knows. Just figured i'd give you the power.
@CapabilityInject ( IExampleCapability . class )
private static void capRegistered ( Capability < IExampleCapability > cap )
{
2017-05-29 09:10:40 +00:00
logger . info ( " IExampleCapability was registered wheeeeee! " ) ;
2016-01-12 00:04:22 +00:00
}
2016-12-21 19:11:25 +00:00
// Having the Provider implement the cap is not recommended as this creates a hard dep on the cap interface.
// And does not allow for sidedness.
// But as this is a example and we do not care about that here we go.
class Provider < V > implements ICapabilitySerializable < NBTTagCompound > , IExampleCapability
{
private V obj ;
private boolean value ;
Provider ( V obj )
{
this . obj = obj ;
}
2017-05-29 09:10:40 +00:00
2016-12-21 19:11:25 +00:00
@Override
public boolean hasCapability ( @Nonnull Capability < ? > capability , @Nullable EnumFacing facing )
{
return TEST_CAP ! = null & & capability = = TEST_CAP ;
}
2017-05-29 09:10:40 +00:00
2016-12-21 19:11:25 +00:00
@Override
@Nullable
public < T > T getCapability ( @Nonnull Capability < T > capability , @Nullable EnumFacing facing )
{
2017-05-29 09:10:40 +00:00
if ( TEST_CAP ! = null & & capability = = TEST_CAP )
{
return TEST_CAP . cast ( this ) ;
}
2016-12-21 19:11:25 +00:00
return null ;
}
2017-05-29 09:10:40 +00:00
2016-12-21 19:11:25 +00:00
@Override
2017-05-29 09:10:40 +00:00
public NBTTagCompound serializeNBT ( )
{
2016-12-21 19:11:25 +00:00
NBTTagCompound tag = new NBTTagCompound ( ) ;
tag . setBoolean ( " CapTestVal " , this . value ) ;
return tag ;
}
2017-05-29 09:10:40 +00:00
2016-12-21 19:11:25 +00:00
@Override
2017-05-29 09:10:40 +00:00
public void deserializeNBT ( NBTTagCompound tag )
{
2016-12-21 19:11:25 +00:00
this . value = tag . getBoolean ( " CapTestVal " ) ;
}
2017-05-29 09:10:40 +00:00
2016-12-21 19:11:25 +00:00
@Override
2017-05-29 09:10:40 +00:00
public String getOwnerType ( )
{
2016-12-21 19:11:25 +00:00
return obj . getClass ( ) . getName ( ) ;
}
2017-05-29 09:10:40 +00:00
2016-12-21 19:11:25 +00:00
@Override
2017-05-29 09:10:40 +00:00
public boolean getVal ( )
{
2016-12-21 19:11:25 +00:00
return this . value ;
}
2017-05-29 09:10:40 +00:00
2016-12-21 19:11:25 +00:00
@Override
2017-05-29 09:10:40 +00:00
public void toggleVal ( )
{
2016-12-21 19:11:25 +00:00
this . value = ! this . value ;
}
}
2016-01-12 00:04:22 +00:00
// An example of how to attach a capability to an arbitrary Tile entity.
// Note: Doing this IS NOT recommended for normal implementations.
// If you control the TE it is HIGHLY recommend that you implement a fast
// version of the has/getCapability functions yourself. So you have control
// over everything yours being called first.
@SubscribeEvent
2017-02-24 01:09:02 +00:00
public void onTELoad ( AttachCapabilitiesEvent < TileEntity > event )
2016-01-12 00:04:22 +00:00
{
2016-12-21 19:11:25 +00:00
//Attach it! The resource location MUST be unique it's recommended that you tag it with your modid and what the cap is.
2017-02-24 01:09:02 +00:00
event . addCapability ( new ResourceLocation ( " forge.testcapmod:dummy_cap " ) , new Provider < TileEntity > ( event . getObject ( ) ) ) ;
}
@SubscribeEvent
public void onItemLoad ( AttachCapabilitiesEvent < ItemStack > event )
{
if ( event . getObject ( ) . getItem ( ) = = Items . STICK )
2017-05-29 09:10:40 +00:00
{
2017-02-24 01:09:02 +00:00
event . addCapability ( new ResourceLocation ( " forge.testcapmod:dummy_cap " ) , new Provider < ItemStack > ( event . getObject ( ) ) ) ;
2017-05-29 09:10:40 +00:00
}
2016-01-12 00:04:22 +00:00
}
2017-02-24 01:09:02 +00:00
// these can be removed if we remove these legacy events
2016-12-21 19:11:25 +00:00
@SubscribeEvent
2017-02-24 01:09:02 +00:00
public void onItemLoadLegacy ( AttachCapabilitiesEvent < Item > event )
2016-12-21 19:11:25 +00:00
{
2017-02-24 01:09:02 +00:00
if ( event . getObject ( ) = = Items . APPLE )
2017-05-29 09:10:40 +00:00
{
2017-02-24 01:09:02 +00:00
event . addCapability ( new ResourceLocation ( " forge.testcapmod:dummy_cap " ) , new Provider < Item > ( event . getObject ( ) ) ) ;
2017-05-29 09:10:40 +00:00
}
2016-12-21 19:11:25 +00:00
}
2017-02-24 01:09:02 +00:00
@SubscribeEvent
public void onItemLoadLegacy ( AttachCapabilitiesEvent . Item event )
{
if ( event . getObject ( ) = = Items . ARROW )
2017-05-29 09:10:40 +00:00
{
2017-02-24 01:09:02 +00:00
event . addCapability ( new ResourceLocation ( " forge.testcapmod:dummy_cap " ) , new Provider < Item > ( event . getObject ( ) ) ) ;
2017-05-29 09:10:40 +00:00
}
2017-02-24 01:09:02 +00:00
}
2016-09-17 22:08:23 +00:00
@SuppressWarnings ( " rawtypes " )
@SubscribeEvent
public void attachEvent ( AttachCapabilitiesEvent event ) //Test Raw type gets everything still.
{
System . currentTimeMillis ( ) ;
}
@SubscribeEvent
public void attachTileEntity ( AttachCapabilitiesEvent < TileEntity > event )
{
if ( ! ( event . getObject ( ) instanceof TileEntity ) )
2017-05-29 09:10:40 +00:00
{
2016-12-21 19:11:25 +00:00
throw new IllegalArgumentException ( " Generic event handler failed! Expected Tile Entity got " + event . getObject ( ) ) ;
2017-05-29 09:10:40 +00:00
}
2016-09-17 22:08:23 +00:00
}
2017-05-29 09:10:40 +00:00
2017-05-26 20:51:18 +00:00
@SubscribeEvent
public void attachVillage ( AttachCapabilitiesEvent < Village > event )
{
System . out . println ( event . getObject ( ) ) ;
event . addCapability ( new ResourceLocation ( " forge.testcapmod:dummy_cap " ) , new Provider ( event . getObject ( ) ) ) ;
}
2016-09-17 22:08:23 +00:00
2017-05-26 20:51:18 +00:00
//Detects if a player has entered the radius of a village
@SubscribeEvent
public void tick ( TickEvent . WorldTickEvent event )
{
2017-05-29 09:10:40 +00:00
if ( ! event . world . isRemote )
2017-05-26 20:51:18 +00:00
{
List < EntityPlayer > players = event . world . playerEntities ;
int i = 0 ;
2017-06-11 00:59:01 +00:00
for ( Village village : event . world . villageCollection . getVillageList ( ) )
2017-05-26 20:51:18 +00:00
{
2017-05-29 09:10:40 +00:00
if ( village . hasCapability ( TEST_CAP , null ) )
2017-05-26 20:51:18 +00:00
{
boolean playerInRadius = false ;
2017-05-29 09:10:40 +00:00
for ( EntityPlayer player : players )
2017-05-26 20:51:18 +00:00
{
2017-05-29 09:10:40 +00:00
if ( new Vec3d ( player . posX , 0 , player . posZ ) . squareDistanceTo ( new Vec3d ( village . getCenter ( ) . getX ( ) , 0 , village . getCenter ( ) . getZ ( ) ) ) < = village . getVillageRadius ( ) * village . getVillageRadius ( ) )
2017-05-26 20:51:18 +00:00
{
playerInRadius = playerInRadius | | true ;
}
}
//If the test cap is true but no players are in radius
2017-05-29 09:10:40 +00:00
if ( village . getCapability ( TEST_CAP , null ) . getVal ( ) & & ! playerInRadius )
2017-05-26 20:51:18 +00:00
{
2017-05-29 09:10:40 +00:00
village . getCapability ( TEST_CAP , null ) . toggleVal ( ) ;
for ( EntityPlayer player : players )
player . sendMessage ( new TextComponentString ( TextFormatting . RED + " All Players Have Exited Village " + i ) ) ;
2017-05-26 20:51:18 +00:00
}
//If the test cap is false but there are players in radius
2017-05-29 09:10:40 +00:00
else if ( ! village . getCapability ( TEST_CAP , null ) . getVal ( ) & & playerInRadius )
2017-05-26 20:51:18 +00:00
{
village . getCapability ( TEST_CAP , null ) . toggleVal ( ) ;
2017-05-29 09:10:40 +00:00
for ( EntityPlayer player : players )
player . sendMessage ( new TextComponentString ( TextFormatting . GREEN + " Some Players Have Entered Village " + i ) ) ;
2017-05-26 20:51:18 +00:00
}
}
i + + ;
}
}
}
2016-01-12 00:04:22 +00:00
// Capabilities SHOULD be interfaces, NOT concrete classes, this allows for
// the most flexibility for the implementors.
2017-05-29 09:10:40 +00:00
public interface IExampleCapability
2016-01-12 00:04:22 +00:00
{
String getOwnerType ( ) ;
2017-05-29 09:10:40 +00:00
2016-12-21 19:11:25 +00:00
boolean getVal ( ) ;
2017-05-29 09:10:40 +00:00
2016-12-21 19:11:25 +00:00
void toggleVal ( ) ;
2016-01-12 00:04:22 +00:00
}
// Storage implementations are required, tho there is some flexibility here.
// If you are the API provider you can also say that in order to use the default storage
// the consumer MUST use the default impl, to allow you to access innards.
// This is just a contract you will have to stipulate in the documentation of your cap.
public static class Storage implements IStorage < IExampleCapability >
{
@Override
2017-05-29 09:10:40 +00:00
public NBTBase writeNBT ( Capability < IExampleCapability > capability , IExampleCapability instance , EnumFacing side )
{
2016-01-12 00:04:22 +00:00
return null ;
}
@Override
2017-05-29 09:10:40 +00:00
public void readNBT ( Capability < IExampleCapability > capability , IExampleCapability instance , EnumFacing side , NBTBase nbt )
{
2016-01-12 00:04:22 +00:00
}
}
// You MUST also supply a default implementation.
// This is to make life easier on consumers.
2017-05-29 09:10:40 +00:00
public static class DefaultImpl implements IExampleCapability
{
2016-01-12 00:04:22 +00:00
@Override
2017-05-29 09:10:40 +00:00
public String getOwnerType ( )
{
2016-01-12 00:04:22 +00:00
return " Default Implementation! " ;
}
2017-05-29 09:10:40 +00:00
public boolean getVal ( )
{
2016-12-21 19:11:25 +00:00
return false ;
}
2017-05-29 09:10:40 +00:00
2016-12-21 19:11:25 +00:00
@Override
2017-05-29 09:10:40 +00:00
public void toggleVal ( )
{
}
2016-01-12 00:04:22 +00:00
}
2016-11-16 03:26:10 +00:00
}