mirror of
https://github.com/Ellpeck/ActuallyAdditions.git
synced 2024-11-16 21:13:11 +01:00
beef72d35d
I am not sure if this is faster or slower than the old tile entity, but it certainly is more performant. Numbers may be adjusted to try and fix what the old speed was (every 50 ticks)
377 lines
No EOL
14 KiB
Java
377 lines
No EOL
14 KiB
Java
/*
|
|
* This file ("TileEntityBase.java") is part of the Actually Additions mod for Minecraft.
|
|
* It is created and owned by Ellpeck and distributed
|
|
* under the Actually Additions License to be found at
|
|
* http://ellpeck.de/actaddlicense
|
|
* View the source code at https://github.com/Ellpeck/ActuallyAdditions
|
|
*
|
|
* © 2015-2017 Ellpeck
|
|
*/
|
|
|
|
package de.ellpeck.actuallyadditions.mod.tile;
|
|
|
|
import de.ellpeck.actuallyadditions.mod.config.values.ConfigIntValues;
|
|
import de.ellpeck.actuallyadditions.mod.network.PacketHandler;
|
|
import de.ellpeck.actuallyadditions.mod.network.PacketServerToClient;
|
|
import de.ellpeck.actuallyadditions.mod.util.ModUtil;
|
|
import de.ellpeck.actuallyadditions.mod.util.WorldUtil;
|
|
import net.minecraft.block.state.IBlockState;
|
|
import net.minecraft.entity.player.EntityPlayer;
|
|
import net.minecraft.nbt.NBTTagCompound;
|
|
import net.minecraft.network.NetworkManager;
|
|
import net.minecraft.network.play.server.SPacketUpdateTileEntity;
|
|
import net.minecraft.tileentity.TileEntity;
|
|
import net.minecraft.util.EnumFacing;
|
|
import net.minecraft.util.ITickable;
|
|
import net.minecraft.util.math.BlockPos;
|
|
import net.minecraft.util.text.ITextComponent;
|
|
import net.minecraft.util.text.TextComponentTranslation;
|
|
import net.minecraft.world.World;
|
|
import net.minecraftforge.common.capabilities.Capability;
|
|
import net.minecraftforge.energy.CapabilityEnergy;
|
|
import net.minecraftforge.energy.IEnergyStorage;
|
|
import net.minecraftforge.fluids.capability.CapabilityFluidHandler;
|
|
import net.minecraftforge.fluids.capability.IFluidHandler;
|
|
import net.minecraftforge.fml.common.network.NetworkRegistry;
|
|
import net.minecraftforge.fml.common.registry.GameRegistry;
|
|
import net.minecraftforge.items.CapabilityItemHandler;
|
|
import net.minecraftforge.items.IItemHandler;
|
|
|
|
public abstract class TileEntityBase extends TileEntity implements ITickable{
|
|
|
|
public final String name;
|
|
public boolean isRedstonePowered;
|
|
public boolean isPulseMode;
|
|
public boolean stopFromDropping;
|
|
protected int ticksElapsed;
|
|
protected TileEntity[] tilesAround = new TileEntity[6];
|
|
protected boolean hasSavedDataOnChangeOrWorldStart;
|
|
|
|
public TileEntityBase(String name){
|
|
this.name = name;
|
|
}
|
|
|
|
public static void init(){
|
|
ModUtil.LOGGER.info("Registering TileEntities...");
|
|
|
|
register(TileEntityCompost.class);
|
|
register(TileEntityFeeder.class);
|
|
register(TileEntityGiantChest.class);
|
|
register(TileEntityGiantChestMedium.class);
|
|
register(TileEntityGiantChestLarge.class);
|
|
register(TileEntityGrinder.class);
|
|
register(TileEntityFurnaceDouble.class);
|
|
register(TileEntityInputter.class);
|
|
register(TileEntityFishingNet.class);
|
|
register(TileEntityFurnaceSolar.class);
|
|
register(TileEntityHeatCollector.class);
|
|
register(TileEntityItemRepairer.class);
|
|
register(TileEntityBreaker.class);
|
|
register(TileEntityDropper.class);
|
|
register(TileEntityInputterAdvanced.class);
|
|
register(TileEntityPlacer.class);
|
|
register(TileEntityGrinderDouble.class);
|
|
register(TileEntityCanolaPress.class);
|
|
register(TileEntityFermentingBarrel.class);
|
|
register(TileEntityOilGenerator.class);
|
|
register(TileEntityCoalGenerator.class);
|
|
register(TileEntityPhantomItemface.class);
|
|
register(TileEntityPhantomLiquiface.class);
|
|
register(TileEntityPhantomEnergyface.class);
|
|
register(TileEntityPlayerInterface.class);
|
|
register(TileEntityPhantomPlacer.class);
|
|
register(TileEntityPhantomBreaker.class);
|
|
register(TileEntityFluidCollector.class);
|
|
register(TileEntityFluidPlacer.class);
|
|
register(TileEntityLavaFactoryController.class);
|
|
register(TileEntityCoffeeMachine.class);
|
|
register(TileEntityPhantomBooster.class);
|
|
register(TileEntityEnergizer.class);
|
|
register(TileEntityEnervator.class);
|
|
register(TileEntityXPSolidifier.class);
|
|
register(TileEntitySmileyCloud.class);
|
|
register(TileEntityLeafGenerator.class);
|
|
register(TileEntityDirectionalBreaker.class);
|
|
register(TileEntityRangedCollector.class);
|
|
register(TileEntityAtomicReconstructor.class);
|
|
register(TileEntityMiner.class);
|
|
register(TileEntityFireworkBox.class);
|
|
register(TileEntityPhantomRedstoneface.class);
|
|
register(TileEntityLaserRelayItem.class);
|
|
register(TileEntityLaserRelayEnergy.class);
|
|
register(TileEntityLaserRelayEnergyAdvanced.class);
|
|
register(TileEntityLaserRelayEnergyExtreme.class);
|
|
register(TileEntityLaserRelayItemWhitelist.class);
|
|
register(TileEntityItemViewer.class);
|
|
register(TileEntityDisplayStand.class);
|
|
register(TileEntityShockSuppressor.class);
|
|
register(TileEntityEmpowerer.class);
|
|
register(TileEntityLaserRelayFluids.class);
|
|
register(TileEntityBioReactor.class);
|
|
register(TileEntityFarmer.class);
|
|
register(TileEntityItemViewerHopping.class);
|
|
register(TileEntityBatteryBox.class);
|
|
}
|
|
|
|
private static void register(Class<? extends TileEntityBase> tileClass){
|
|
try{
|
|
//This is hacky and dirty but it works so whatever
|
|
String name = ModUtil.MOD_ID+":"+tileClass.newInstance().name;
|
|
GameRegistry.registerTileEntity(tileClass, name);
|
|
}
|
|
catch(Exception e){
|
|
ModUtil.LOGGER.fatal("Registering a TileEntity failed!", e);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public final NBTTagCompound writeToNBT(NBTTagCompound compound){
|
|
this.writeSyncableNBT(compound, NBTType.SAVE_TILE);
|
|
return compound;
|
|
}
|
|
|
|
@Override
|
|
public final void readFromNBT(NBTTagCompound compound){
|
|
this.readSyncableNBT(compound, NBTType.SAVE_TILE);
|
|
}
|
|
|
|
@Override
|
|
public final SPacketUpdateTileEntity getUpdatePacket(){
|
|
NBTTagCompound compound = new NBTTagCompound();
|
|
this.writeSyncableNBT(compound, NBTType.SYNC);
|
|
return new SPacketUpdateTileEntity(this.pos, -1, compound);
|
|
}
|
|
|
|
@Override
|
|
public final void onDataPacket(NetworkManager net, SPacketUpdateTileEntity pkt){
|
|
this.readSyncableNBT(pkt.getNbtCompound(), NBTType.SYNC);
|
|
}
|
|
|
|
@Override
|
|
public final NBTTagCompound getUpdateTag(){
|
|
NBTTagCompound compound = new NBTTagCompound();
|
|
this.writeSyncableNBT(compound, NBTType.SYNC);
|
|
return compound;
|
|
}
|
|
|
|
@Override
|
|
public final void handleUpdateTag(NBTTagCompound compound){
|
|
this.readSyncableNBT(compound, NBTType.SYNC);
|
|
}
|
|
|
|
public final void sendUpdate(){
|
|
if(this.world != null && !this.world.isRemote){
|
|
NBTTagCompound compound = new NBTTagCompound();
|
|
this.writeSyncableNBT(compound, NBTType.SYNC);
|
|
|
|
NBTTagCompound data = new NBTTagCompound();
|
|
data.setTag("Data", compound);
|
|
data.setInteger("X", this.pos.getX());
|
|
data.setInteger("Y", this.pos.getY());
|
|
data.setInteger("Z", this.pos.getZ());
|
|
PacketHandler.theNetwork.sendToAllAround(new PacketServerToClient(data, PacketHandler.TILE_ENTITY_HANDLER), new NetworkRegistry.TargetPoint(this.world.provider.getDimension(), this.getPos().getX(), this.getPos().getY(), this.getPos().getZ(), 64));
|
|
}
|
|
}
|
|
|
|
public void writeSyncableNBT(NBTTagCompound compound, NBTType type){
|
|
if(type != NBTType.SAVE_BLOCK){
|
|
super.writeToNBT(compound);
|
|
}
|
|
|
|
if(type == NBTType.SAVE_TILE){
|
|
compound.setBoolean("Redstone", this.isRedstonePowered);
|
|
compound.setInteger("TicksElapsed", this.ticksElapsed);
|
|
compound.setBoolean("StopDrop", this.stopFromDropping);
|
|
}
|
|
if(this.isRedstoneToggle() && (type != NBTType.SAVE_BLOCK || this.isPulseMode)){
|
|
compound.setBoolean("IsPulseMode", this.isPulseMode);
|
|
}
|
|
}
|
|
|
|
public void readSyncableNBT(NBTTagCompound compound, NBTType type){
|
|
if(type != NBTType.SAVE_BLOCK){
|
|
super.readFromNBT(compound);
|
|
}
|
|
|
|
if(type == NBTType.SAVE_TILE){
|
|
this.isRedstonePowered = compound.getBoolean("Redstone");
|
|
this.ticksElapsed = compound.getInteger("TicksElapsed");
|
|
this.stopFromDropping = compound.getBoolean("StopDrop");
|
|
}
|
|
if(this.isRedstoneToggle()){
|
|
this.isPulseMode = compound.getBoolean("IsPulseMode");
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public boolean shouldRefresh(World world, BlockPos pos, IBlockState oldState, IBlockState newState){
|
|
return !oldState.getBlock().isAssociatedBlock(newState.getBlock());
|
|
}
|
|
|
|
public String getNameForTranslation(){
|
|
return "container."+ModUtil.MOD_ID+"."+this.name+".name";
|
|
}
|
|
|
|
@Override
|
|
public ITextComponent getDisplayName(){
|
|
return new TextComponentTranslation(this.getNameForTranslation());
|
|
}
|
|
|
|
@Override
|
|
public final void update(){
|
|
this.updateEntity();
|
|
}
|
|
|
|
public int getComparatorStrength(){
|
|
return 0;
|
|
}
|
|
|
|
public void updateEntity(){
|
|
this.ticksElapsed++;
|
|
|
|
if(!this.world.isRemote){
|
|
if(this instanceof ISharingEnergyProvider){
|
|
ISharingEnergyProvider provider = (ISharingEnergyProvider)this;
|
|
if(provider.doesShareEnergy()){
|
|
int total = provider.getEnergyToSplitShare();
|
|
if(total > 0){
|
|
EnumFacing[] sides = provider.getEnergyShareSides();
|
|
|
|
int amount = total/sides.length;
|
|
if(amount <= 0){
|
|
amount = total;
|
|
}
|
|
|
|
for(EnumFacing side : sides){
|
|
TileEntity tile = this.tilesAround[side.ordinal()];
|
|
if(tile != null && provider.canShareTo(tile)){
|
|
WorldUtil.doEnergyInteraction(this, tile, side, amount);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if(this instanceof ISharingFluidHandler){
|
|
ISharingFluidHandler handler = (ISharingFluidHandler)this;
|
|
if(handler.doesShareFluid()){
|
|
int total = handler.getMaxFluidAmountToSplitShare();
|
|
if(total > 0){
|
|
EnumFacing[] sides = handler.getFluidShareSides();
|
|
|
|
int amount = total/sides.length;
|
|
if(amount <= 0){
|
|
amount = total;
|
|
}
|
|
|
|
for(EnumFacing side : sides){
|
|
TileEntity tile = this.tilesAround[side.ordinal()];
|
|
if(tile != null){
|
|
WorldUtil.doFluidInteraction(this, tile, side, amount);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if(!this.hasSavedDataOnChangeOrWorldStart){
|
|
if(this.shouldSaveDataOnChangeOrWorldStart()){
|
|
this.saveDataOnChangeOrWorldStart();
|
|
}
|
|
|
|
this.hasSavedDataOnChangeOrWorldStart = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
public void saveDataOnChangeOrWorldStart(){
|
|
for(EnumFacing side : EnumFacing.values()){
|
|
BlockPos pos = this.pos.offset(side);
|
|
if(this.world.isBlockLoaded(pos)){
|
|
this.tilesAround[side.ordinal()] = this.world.getTileEntity(pos);
|
|
}
|
|
}
|
|
}
|
|
|
|
public boolean shouldSaveDataOnChangeOrWorldStart(){
|
|
return this instanceof ISharingEnergyProvider || this instanceof ISharingFluidHandler;
|
|
}
|
|
|
|
public void setRedstonePowered(boolean powered){
|
|
this.isRedstonePowered = powered;
|
|
this.markDirty();
|
|
}
|
|
|
|
public boolean canPlayerUse(EntityPlayer player){
|
|
return player.getDistanceSq(this.getPos().getX()+0.5D, this.pos.getY()+0.5D, this.pos.getZ()+0.5D) <= 64 && !this.isInvalid() && this.world.getTileEntity(this.pos) == this;
|
|
}
|
|
|
|
protected boolean sendUpdateWithInterval(){
|
|
if(this.ticksElapsed%ConfigIntValues.TILE_ENTITY_UPDATE_INTERVAL.getValue() == 0){
|
|
this.sendUpdate();
|
|
return true;
|
|
}
|
|
else{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public boolean hasCapability(Capability<?> capability, EnumFacing facing){
|
|
return this.getCapability(capability, facing) != null;
|
|
}
|
|
|
|
@SuppressWarnings("unchecked")
|
|
@Override
|
|
public <T> T getCapability(Capability<T> capability, EnumFacing facing){
|
|
if(capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY){
|
|
IItemHandler handler = this.getItemHandler(facing);
|
|
if(handler != null){
|
|
return (T)handler;
|
|
}
|
|
}
|
|
else if(capability == CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY){
|
|
IFluidHandler tank = this.getFluidHandler(facing);
|
|
if(tank != null){
|
|
return (T)tank;
|
|
}
|
|
}
|
|
else if(capability == CapabilityEnergy.ENERGY){
|
|
IEnergyStorage storage = this.getEnergyStorage(facing);
|
|
if(storage != null){
|
|
return (T)storage;
|
|
}
|
|
}
|
|
return super.getCapability(capability, facing);
|
|
}
|
|
|
|
public IFluidHandler getFluidHandler(EnumFacing facing){
|
|
return null;
|
|
}
|
|
|
|
public IEnergyStorage getEnergyStorage(EnumFacing facing){
|
|
return null;
|
|
}
|
|
|
|
public IItemHandler getItemHandler(EnumFacing facing){
|
|
return null;
|
|
}
|
|
|
|
public boolean isRedstoneToggle(){
|
|
return false;
|
|
}
|
|
|
|
public void activateOnPulse(){
|
|
|
|
}
|
|
|
|
public boolean respondsToPulses(){
|
|
return this.isRedstoneToggle() && this.isPulseMode;
|
|
}
|
|
|
|
public enum NBTType{
|
|
SAVE_TILE,
|
|
SYNC,
|
|
SAVE_BLOCK
|
|
}
|
|
} |