Integrated tile entity initialisation

This commit is contained in:
Unknown 2018-07-28 16:54:51 +02:00 committed by unknown
parent 9d8e6ea7fe
commit 1b7eda2ce8
3 changed files with 190 additions and 3 deletions

View file

@ -0,0 +1,162 @@
@startuml
actor "Forge or\na Mod" as anyMod
participant Forge #cyan
participant World #cyan
participant Chunk #cyan
participant Entity #cyan
participant TileEntity #cyan
'participant WarpDrive
anyMod -> World: addTileEntity(tileEntity)
activate World
World -[#blue]> TileEntity: setWorld
World <-[#blue]- TileEntity
alt processingLoadedTiles
World -[#blue]> World: addedTileEntityList.add()
else
World -[#blue]> World: loadedTileEntityList.add()
alt instanceof ITickable
World -[#blue]> World: tickableTileEntities.add()
end
World -[#blue]> TileEntity: onLoad
World <-[#blue]- TileEntity
alt isRemote
World -[#blue]> World: notifyBlockUpdate
end
end
anyMod <-- World
deactivate World
anyMod -> World: addTileEntities(tileEntities)
activate World
alt processingLoadedTiles
loop tileEntities with no world set
World -[#blue]> TileEntity: setWorld
World <-[#blue]- TileEntity
end
World -[#blue]> World: addedTileEntityList.addAll
else
loop tileEntities
World -[#blue]> World: <b>addTileEntity(tileEntity)
end
end
anyMod <-- World
deactivate World
anyMod -> World: setTileEntity(pos, tileEntity)
activate World
alt processingLoadedTiles
World -[#blue]> TileEntity: setPos
World <-[#blue]- TileEntity
World -[#blue]> TileEntity: setWorld
World <-[#blue]- TileEntity
loop addedTileEntityList with same position
World -[#blue]> TileEntity: invalidate
World <-[#blue]- TileEntity
World -[#blue]> World: remove
end
World -[#blue]> World: addedTileEntityList.add
else
World -[#blue]> Chunk: <b>addTileEntity(pos, tileEntity)
activate Chunk
alt tileEntity.world == null
Chunk -[#blue]> TileEntity: setWorld(...)
Chunk <-[#blue]- TileEntity
end
Chunk -[#blue]> TileEntity: setPos(...)
Chunk <-[#blue]- TileEntity
alt block.hasTileEntity(blockState)
alt tileEntities.contains(tileEntity)
Chunk -[#blue]> TileEntity: invalidate()
Chunk <-[#blue]- TileEntity
end
Chunk -[#blue]> TileEntity: validate()
Chunk <-[#blue]- TileEntity
Chunk -[#blue]> Chunk: tileEntities.put
end
World <-[#blue]- Chunk
deactivate Chunk
end
anyMod <-- World
deactivate World
anyMod -> Chunk: addTileEntity(tileEntity)
activate Chunk
Chunk -[#blue]> Chunk: addTileEntity(getPos, tileEntity)
alt loaded
Chunk -[#blue]> World: <b>addTileEntity(tileEntity)
Chunk <-[#blue]- World
end
anyMod <-- Chunk
deactivate Chunk
Forge -[#blue]> World: updateEntities()
activate World
loop weather entities, not blocked
World -[#blue]> Entity: ticksExisted++
World -[#blue]> Entity: onUpdate()
World <-[#blue]- Entity
alt entity.isDead
World -[#blue]> World: remove
end
end
World -[#blue]> World: <I>remove unloaded entities
World -[#blue]> World: tickPlayers()
loop entities
World -[#blue]> World: <I>dismount dead riders
World -[#blue]> World: updateEntity(entity)
activate World
World -[#blue]> World: updateEntityWithOptionalForce()
activate World
...canEntityUpdate(entity)...
World -> Entity: updateRidden() or onUpdate()
World <-- Entity
...update holding chunk, etc....
World <-- World
deactivate World
World <-- World
deactivate World
World -[#blue]> World: <I>remove dead entity
end
World -[#blue]> World: processingLoadedTiles = true
loop tileEntitiesToBeRemoved
World -[#blue]> TileEntity: onChunkUnload()
World <-[#blue]- TileEntity
end
loop tickableTileEntities
alt ! tileEntity.isInvalid()
World -[#blue]> TileEntity: update()
World <-[#blue]- TileEntity
end
alt tileEntity.isInvalid()
World -[#blue]> World: loadedTileEntityList.remove
alt isBlockLoaded, ...
World -[#blue]> Chunk: removeTileEntity(pos)
World <-[#blue]- Chunk
end
end
end
World -[#blue]> World: processingLoadedTiles = false
loop addedTileEntityList
alt ! tileEntity.isInvalid()
alt ! loadedTileEntityList.contains(tileEntity)
World -[#blue]> World: <b>addTileEntity(tileEntity)
end
alt isBlockLoaded
World -[#blue]> Chunk: <b>addTileEntity(pos, tileEntity)
World <-[#blue]- Chunk
World -[#blue]> World: notifyBlockUpdate(...)
end
end
end
World -[#blue]> Chunk: addedTileEntityList.clear
Forge <-[#blue]- World
deactivate World
@enduml

View file

@ -45,6 +45,7 @@ public abstract class TileEntityAbstractBase extends TileEntity implements IBloc
// (none)
// computed properties
private boolean isConstructed = false;
private boolean isFirstTick = true;
private boolean isDirty = false;
@ -57,6 +58,16 @@ public abstract class TileEntityAbstractBase extends TileEntity implements IBloc
@Override
public void onLoad() {
super.onLoad();
assert hasWorld() && pos != BlockPos.ORIGIN;
if (!isConstructed) {
onConstructed();
}
}
protected void onConstructed() {
// warning: we can't use Block.CreateNewTileEntity() as world loading calls the TileEntity constructor directly
// warning: we can't use setPos(), setWorld() or validate() as getBlockType() will cause a stack overflow
// warning: we can't use onLoad() to trigger this method as onLoad() isn't always called, see https://github.com/MinecraftForge/MinecraftForge/issues/5061
// immediately retrieve tier, we need it to connect energy conduits and save the world before the first tick
final Block block = getBlockType();
@ -67,10 +78,13 @@ public abstract class TileEntityAbstractBase extends TileEntity implements IBloc
this, Commons.format(world, pos), block));
enumTier = EnumTier.BASIC;
}
isConstructed = true;
}
protected void onFirstUpdateTick() {
// No operation
assert isConstructed;
assert enumTier != null;
}
@ -93,6 +107,9 @@ public abstract class TileEntityAbstractBase extends TileEntity implements IBloc
@Override
public void onBlockUpdateDetected() {
assert Commons.isSafeThread();
if (!isConstructed) {
onConstructed();
}
}
protected <T extends Comparable<T>, V extends T> void updateBlockState(final IBlockState blockState_in, final IProperty<T> property, final V value) {

View file

@ -67,8 +67,8 @@ public class TileEntityEnanReactorCore extends TileEntityEnanReactorController {
}
@Override
public void onLoad() {
super.onLoad();
public void onConstructed() {
super.onConstructed();
energyStored_max = WarpDriveConfig.ENAN_REACTOR_MAX_ENERGY_STORED_BY_TIER[enumTier.getIndex()];
generation_offset = WarpDriveConfig.ENAN_REACTOR_GENERATION_MIN_RF_BY_TIER[enumTier.getIndex()];
@ -538,7 +538,7 @@ public class TileEntityEnanReactorCore extends TileEntityEnanReactorController {
@Override
public int energy_getMaxStorage() {
return (int) convertRFtoInternal_floor(WarpDriveConfig.ENAN_REACTOR_MAX_ENERGY_STORED_BY_TIER[enumTier.getIndex()]);
return (int) convertRFtoInternal_floor(energyStored_max);
}
// Forge overrides
@ -565,7 +565,15 @@ public class TileEntityEnanReactorCore extends TileEntityEnanReactorController {
public void readFromNBT(final NBTTagCompound tagCompound) {
super.readFromNBT(tagCompound);
// skip empty NBT on placement to use defaults values
if (!tagCompound.hasKey("outputMode")) {
return;
}
enumReactorOutputMode = EnumReactorOutputMode.byName(tagCompound.getString("outputMode"));
if (enumReactorOutputMode == null) {
enumReactorOutputMode = EnumReactorOutputMode.OFF;
}
outputThreshold = tagCompound.getInteger("outputThreshold");
instabilityTarget = tagCompound.getDouble("instabilityTarget");
stabilizerEnergy = tagCompound.getInteger("stabilizerEnergy");