Improved transporter beacon usability
- add transporter room state to beacon - resume transport when conflicting beacons are removed - explicitly load chunks on beacon transport so players don't need their own - support transport inside non-celestial object dimension (wip)
This commit is contained in:
parent
a0b2c005d1
commit
f04782dd72
4 changed files with 146 additions and 76 deletions
|
@ -22,6 +22,7 @@ import net.minecraft.util.EnumFacing;
|
|||
import net.minecraft.util.EnumHand;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.text.TextComponentString;
|
||||
import net.minecraft.util.text.TextComponentTranslation;
|
||||
import net.minecraft.world.IBlockAccess;
|
||||
import net.minecraft.world.World;
|
||||
|
@ -168,22 +169,27 @@ public class BlockTransporterBeacon extends BlockAbstractContainer {
|
|||
}
|
||||
final TileEntityTransporterBeacon tileEntityTransporterBeacon = (TileEntityTransporterBeacon) tileEntity;
|
||||
|
||||
// sneaking with an empty hand
|
||||
if ( itemStackHeld.isEmpty()
|
||||
&& entityPlayer.isSneaking() ) {
|
||||
final boolean isEnabledOld = tileEntityTransporterBeacon.getIsEnabled();
|
||||
tileEntityTransporterBeacon.setIsEnabled(!isEnabledOld);
|
||||
final boolean isEnabledNew = tileEntityTransporterBeacon.getIsEnabled();
|
||||
if (isEnabledOld != isEnabledNew) {
|
||||
if (isEnabledNew) {
|
||||
Commons.addChatMessage(entityPlayer, Commons.getChatPrefix(this)
|
||||
.appendSibling(new TextComponentTranslation("warpdrive.is_enabled.set.enabled")));
|
||||
} else {
|
||||
Commons.addChatMessage(entityPlayer, Commons.getChatPrefix(this)
|
||||
.appendSibling(new TextComponentTranslation("warpdrive.is_enabled.set.disabled")));
|
||||
if (itemStackHeld.isEmpty()) {
|
||||
if (!entityPlayer.isSneaking()) {// non-sneaking with an empty hand
|
||||
Commons.addChatMessage(entityPlayer, Commons.getChatPrefix(this)
|
||||
.appendSibling(new TextComponentString(tileEntityTransporterBeacon.stateTransporter)));
|
||||
return true;
|
||||
|
||||
} else {// sneaking with an empty hand
|
||||
final boolean isEnabledOld = tileEntityTransporterBeacon.getIsEnabled();
|
||||
tileEntityTransporterBeacon.setIsEnabled(!isEnabledOld);
|
||||
final boolean isEnabledNew = tileEntityTransporterBeacon.getIsEnabled();
|
||||
if (isEnabledOld != isEnabledNew) {
|
||||
if (isEnabledNew) {
|
||||
Commons.addChatMessage(entityPlayer, Commons.getChatPrefix(this)
|
||||
.appendSibling(new TextComponentTranslation("warpdrive.is_enabled.set.enabled")));
|
||||
} else {
|
||||
Commons.addChatMessage(entityPlayer, Commons.getChatPrefix(this)
|
||||
.appendSibling(new TextComponentTranslation("warpdrive.is_enabled.set.disabled")));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return super.onBlockActivated(world, blockPos, blockState, entityPlayer, enumHand, enumFacing, hitX, hitY, hitZ);
|
||||
|
|
|
@ -206,37 +206,6 @@ public class ItemBlockTransporterBeacon extends ItemBlockAbstractBase implements
|
|||
super.onUpdate(itemStack, world, entity, indexSlot, isHeld);
|
||||
}
|
||||
|
||||
/* @TODO 1.10 is the upstream 1.7.10 bug fixed?
|
||||
@Override
|
||||
public boolean onItemUseFirst(final ItemStack itemStack, final EntityPlayer entityPlayer,
|
||||
final World world, final int x, final int y, final int z,
|
||||
final int side, final float hitX, final float hitY, final float hitZ) {
|
||||
// itemStack is constantly updated for energy updates
|
||||
// in net.minecraft.network.NetHandlerPlayServer.processPlayerBlockPlacement(NetHandlerPlayServer.java:657), a NPE appears randomly due to bad multithreading in upstream
|
||||
// consequently, we prevent to use the item on any tile entity other than a TransporterCore
|
||||
|
||||
// allows block placement while sneaking
|
||||
if (entityPlayer.isSneaking()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// allows non-tile entities or transporter core
|
||||
final TileEntity tileEntity = world.getTileEntity(x, y, z);
|
||||
if ( tileEntity == null
|
||||
|| tileEntity instanceof ITransporterCore ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// allow if beacon is disabled
|
||||
if (!isActive(itemStack)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// forbid everything else
|
||||
return true;
|
||||
}
|
||||
/**/
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public EnumActionResult onItemUse(@Nonnull final EntityPlayer entityPlayer,
|
||||
|
|
|
@ -36,8 +36,9 @@ public class TileEntityTransporterBeacon extends TileEntityAbstractEnergyConsume
|
|||
private UUID uuidTransporterCore;
|
||||
private int tickDeploying = 0;
|
||||
|
||||
// computer properties
|
||||
// computed properties
|
||||
private boolean isActive = false;
|
||||
protected String stateTransporter = "";
|
||||
|
||||
public TileEntityTransporterBeacon() {
|
||||
super();
|
||||
|
@ -128,7 +129,11 @@ public class TileEntityTransporterBeacon extends TileEntityAbstractEnergyConsume
|
|||
}
|
||||
|
||||
final TileEntityTransporterCore tileEntityTransporterCore = (TileEntityTransporterCore) tileEntity;
|
||||
return tileEntityTransporterCore.updateBeacon(this, uuidTransporterCore);
|
||||
final boolean isActive = tileEntityTransporterCore.updateBeacon(this, uuidTransporterCore);
|
||||
final Object[] state = tileEntityTransporterCore.state();
|
||||
stateTransporter = (String) state[1];
|
||||
|
||||
return isActive;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -144,6 +149,8 @@ public class TileEntityTransporterBeacon extends TileEntityAbstractEnergyConsume
|
|||
if (isEnabled) {
|
||||
tickDeploying = 0;
|
||||
}
|
||||
// always clear status
|
||||
stateTransporter = "";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -49,7 +49,6 @@ import net.minecraft.block.Block;
|
|||
import net.minecraft.block.BlockLiquid;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityList;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
|
@ -68,10 +67,14 @@ import net.minecraft.util.EnumHand;
|
|||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.BlockPos.MutableBlockPos;
|
||||
import net.minecraft.util.math.ChunkPos;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.WorldServer;
|
||||
|
||||
import net.minecraftforge.common.DimensionManager;
|
||||
import net.minecraftforge.common.ForgeChunkManager;
|
||||
import net.minecraftforge.common.ForgeChunkManager.Ticket;
|
||||
import net.minecraftforge.common.ForgeChunkManager.Type;
|
||||
import net.minecraftforge.common.util.Constants;
|
||||
import net.minecraftforge.fml.common.Optional;
|
||||
|
||||
|
@ -98,6 +101,7 @@ public class TileEntityTransporterCore extends TileEntityAbstractEnergyConsumer
|
|||
private int tickComputerPulse = 0;
|
||||
private boolean isConnected = false;
|
||||
private GlobalPosition globalPositionBeacon = null;
|
||||
private Ticket ticketChunkloading;
|
||||
private double energyCostForAcquiring = 0.0D;
|
||||
private double energyCostForEnergizing = 0.0D;
|
||||
private double lockStrengthOptimal = -1.0D;
|
||||
|
@ -258,6 +262,7 @@ public class TileEntityTransporterCore extends TileEntityAbstractEnergyConsumer
|
|||
// execute state transitions
|
||||
switch (transporterState) {
|
||||
case DISABLED:
|
||||
releaseChunks();
|
||||
isLockRequested = false;
|
||||
isEnergizeRequested = false;
|
||||
lockStrengthActual = 0.0D;
|
||||
|
@ -272,6 +277,8 @@ public class TileEntityTransporterCore extends TileEntityAbstractEnergyConsumer
|
|||
// force parameters validation for next tick
|
||||
tickUpdateParameters = 0;
|
||||
transporterState = EnumTransporterState.ACQUIRING;
|
||||
} else {
|
||||
releaseChunks();
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -321,6 +328,13 @@ public class TileEntityTransporterCore extends TileEntityAbstractEnergyConsumer
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChunkUnload() {
|
||||
releaseChunks();
|
||||
|
||||
super.onChunkUnload();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidate() {
|
||||
if (!world.isRemote) {
|
||||
|
@ -340,6 +354,7 @@ public class TileEntityTransporterCore extends TileEntityAbstractEnergyConsumer
|
|||
}
|
||||
}
|
||||
}
|
||||
releaseChunks();
|
||||
}
|
||||
|
||||
private void state_energizing() {
|
||||
|
@ -667,6 +682,30 @@ public class TileEntityTransporterCore extends TileEntityAbstractEnergyConsumer
|
|||
long mass;
|
||||
}
|
||||
|
||||
private void checkBeaconObsolescence() {
|
||||
if (globalPositionBeacon != null) {
|
||||
final WorldServer worldBeacon = globalPositionBeacon.getWorldServerIfLoaded();
|
||||
if (worldBeacon == null) {
|
||||
globalPositionBeacon = null;
|
||||
isLockRequested = false;
|
||||
isEnergizeRequested = false;
|
||||
isJammed = false;
|
||||
reasonJammed = "";
|
||||
|
||||
} else {
|
||||
final TileEntity tileEntity = worldBeacon.getTileEntity(new BlockPos(globalPositionBeacon.x, globalPositionBeacon.y, globalPositionBeacon.z));
|
||||
if ( !(tileEntity instanceof ITransporterBeacon)
|
||||
|| !((ITransporterBeacon) tileEntity).isActive() ) {
|
||||
globalPositionBeacon = null;
|
||||
isLockRequested = false;
|
||||
isEnergizeRequested = false;
|
||||
isJammed = false;
|
||||
reasonJammed = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateParameters() {
|
||||
isJammed = false;
|
||||
reasonJammed = "";
|
||||
|
@ -688,23 +727,8 @@ public class TileEntityTransporterCore extends TileEntityAbstractEnergyConsumer
|
|||
final CelestialObject celestialObjectLocal = CelestialObjectManager.get(world, pos.getX(), pos.getZ());
|
||||
final Vector3 v3Local_universal = StarMapRegistry.getUniversalCoordinates(celestialObjectLocal, globalPositionLocal.x, globalPositionLocal.y, globalPositionLocal.z);
|
||||
|
||||
// check beacon obsolescence
|
||||
if (globalPositionBeacon != null) {
|
||||
final WorldServer worldBeacon = globalPositionBeacon.getWorldServerIfLoaded();
|
||||
if (worldBeacon == null) {
|
||||
globalPositionBeacon = null;
|
||||
isLockRequested = false;
|
||||
isEnergizeRequested = false;
|
||||
} else {
|
||||
final TileEntity tileEntity = worldBeacon.getTileEntity(new BlockPos(globalPositionBeacon.x, globalPositionBeacon.y, globalPositionBeacon.z));
|
||||
if ( !(tileEntity instanceof ITransporterBeacon)
|
||||
|| !((ITransporterBeacon) tileEntity).isActive() ) {
|
||||
globalPositionBeacon = null;
|
||||
isLockRequested = false;
|
||||
isEnergizeRequested = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
// validate context
|
||||
checkBeaconObsolescence();
|
||||
|
||||
// compute remote global position
|
||||
GlobalPosition globalPositionRemoteNew = null;
|
||||
|
@ -722,8 +746,12 @@ public class TileEntityTransporterCore extends TileEntityAbstractEnergyConsumer
|
|||
globalPositionRemoteNew = new GlobalPosition(celestialObjectChild.dimensionId, vRequest.x, (vRequest.y + 1024) % 256, vRequest.z);
|
||||
}
|
||||
} else if (vRequest.y > 256) {
|
||||
vRequest.translateBack(celestialObjectLocal.getEntryOffset());
|
||||
globalPositionRemoteNew = new GlobalPosition(celestialObjectLocal.parent.dimensionId, vRequest.x, vRequest.y % 256, vRequest.z);
|
||||
if (celestialObjectLocal == null) {
|
||||
reasonJammed = "Unknown dimension, no reachable orbit";
|
||||
} else {
|
||||
vRequest.translateBack(celestialObjectLocal.getEntryOffset());
|
||||
globalPositionRemoteNew = new GlobalPosition(celestialObjectLocal.parent.dimensionId, vRequest.x, vRequest.y % 256, vRequest.z);
|
||||
}
|
||||
|
||||
} else {
|
||||
globalPositionRemoteNew = new GlobalPosition(world.provider.getDimension(), vRequest.x, vRequest.y, vRequest.z);
|
||||
|
@ -783,7 +811,8 @@ public class TileEntityTransporterCore extends TileEntityAbstractEnergyConsumer
|
|||
|
||||
// validate cross dimension transport rules
|
||||
if (celestialObjectLocal != celestialObjectRemote) {
|
||||
if ( celestialObjectLocal.isHyperspace()
|
||||
if ( ( celestialObjectLocal != null
|
||||
&& celestialObjectLocal.isHyperspace() )
|
||||
|| celestialObjectRemote.isHyperspace() ) {
|
||||
isJammed = true;
|
||||
reasonJammed = "Blocked by warp field barrier";
|
||||
|
@ -920,15 +949,19 @@ public class TileEntityTransporterCore extends TileEntityAbstractEnergyConsumer
|
|||
if (globalPositionBeacon.distance2To(tileEntity) <= radius2) {// it's a beacon party! we're happy with it...
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!isJammed && WarpDriveConfig.LOGGING_TRANSPORTER) {// only log first jamming occurrence
|
||||
WarpDrive.logger.info(String.format("%s Conflicting beacon requests received %s is not %s",
|
||||
this, tileEntity, uuid));
|
||||
|
||||
// always validate context
|
||||
checkBeaconObsolescence();
|
||||
if (globalPositionBeacon != null) {
|
||||
if (!isJammed && WarpDriveConfig.LOGGING_TRANSPORTER) {// only log first jamming occurrence
|
||||
WarpDrive.logger.info(String.format("%s Conflicting beacon requests received %s is not %s",
|
||||
this, tileEntity, uuid));
|
||||
}
|
||||
isJammed = true;
|
||||
reasonJammed = "Conflicting beacon requests received";
|
||||
tickCooldown = Math.max(tickCooldown, WarpDriveConfig.TRANSPORTER_JAMMED_COOLDOWN_TICKS);
|
||||
return false;
|
||||
}
|
||||
isJammed = true;
|
||||
reasonJammed = "Conflicting beacon requests received";
|
||||
tickCooldown = Math.max(tickCooldown, WarpDriveConfig.TRANSPORTER_JAMMED_COOLDOWN_TICKS);
|
||||
return false;
|
||||
}
|
||||
|
||||
// check for new beacon
|
||||
|
@ -938,6 +971,7 @@ public class TileEntityTransporterCore extends TileEntityAbstractEnergyConsumer
|
|||
isJammed = true;
|
||||
reasonJammed = "Beacon request received";
|
||||
lockStrengthActual = 0.0D;
|
||||
forceChunks();
|
||||
if (transporterState == EnumTransporterState.ENERGIZING) {
|
||||
transporterState = EnumTransporterState.ACQUIRING;
|
||||
}
|
||||
|
@ -947,6 +981,60 @@ public class TileEntityTransporterCore extends TileEntityAbstractEnergyConsumer
|
|||
return true;
|
||||
}
|
||||
|
||||
private void forceChunks() {
|
||||
if (ticketChunkloading != null) {
|
||||
WarpDrive.logger.warn(String.format("%s Already chunkloading...",
|
||||
this));
|
||||
return;
|
||||
}
|
||||
|
||||
if (WarpDriveConfig.LOGGING_TRANSPORTER) {
|
||||
WarpDrive.logger.info(String.format("%s Forcing chunks",
|
||||
this));
|
||||
}
|
||||
ticketChunkloading = ForgeChunkManager.requestTicket(WarpDrive.instance, world, Type.NORMAL);
|
||||
if (ticketChunkloading == null) {
|
||||
WarpDrive.logger.error(String.format("%s Chunkloading rejected",
|
||||
this));
|
||||
return;
|
||||
}
|
||||
final AxisAlignedBB aabbArea = getStarMapArea();
|
||||
final int minX = (int) aabbArea.minX >> 4;
|
||||
final int maxX = (int) aabbArea.maxX >> 4;
|
||||
final int minZ = (int) aabbArea.minZ >> 4;
|
||||
final int maxZ = (int) aabbArea.maxZ >> 4;
|
||||
int chunkCount = 0;
|
||||
for (int x = minX; x <= maxX; x++) {
|
||||
for (int z = minZ; z <= maxZ; z++) {
|
||||
chunkCount++;
|
||||
if (chunkCount > ticketChunkloading.getMaxChunkListDepth()) {
|
||||
WarpDrive.logger.error(String.format("%s Too many chunks to load: %d > %d",
|
||||
this,
|
||||
(maxX - minX + 1) * (maxZ - minZ + 1),
|
||||
ticketChunkloading.getMaxChunkListDepth() ));
|
||||
return;
|
||||
}
|
||||
ForgeChunkManager.forceChunk(ticketChunkloading, new ChunkPos(x, z));
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
private void releaseChunks() {
|
||||
if (ticketChunkloading == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (WarpDriveConfig.LOGGING_TRANSPORTER) {
|
||||
WarpDrive.logger.info(this + " Releasing chunks");
|
||||
}
|
||||
|
||||
if (ticketChunkloading != null) {
|
||||
ForgeChunkManager.releaseTicket(ticketChunkloading);
|
||||
ticketChunkloading = null;
|
||||
}
|
||||
}
|
||||
|
||||
private static FocusValues getFocusValueAtCoordinates(final World world, final VectorI vLocation, final int radius) {
|
||||
// return default values if world isn't loaded
|
||||
if (world == null) {
|
||||
|
|
Loading…
Reference in a new issue