1
0
mirror of https://github.com/SquidDev-CC/CC-Tweaked synced 2025-01-28 18:04:47 +00:00

Use a separate object for tracking TickScheduler state

This allows us to use non-TileGeneric block entities. This is a clever
trick which will help us later!
This commit is contained in:
Jonathan Coates 2022-10-28 23:40:55 +01:00
parent 562f224c01
commit 1f910ee2ba
No known key found for this signature in database
GPG Key ID: B9E431FF07C98D06
7 changed files with 47 additions and 31 deletions

View File

@ -19,17 +19,9 @@ import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraftforge.common.util.Constants; import net.minecraftforge.common.util.Constants;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import java.util.concurrent.atomic.AtomicBoolean;
public abstract class TileGeneric extends TileEntity public abstract class TileGeneric extends TileEntity
{ {
/**
* Is this block enqueued to be updated next tick? This should only be read/written by the tick scheduler.
*
* @see dan200.computercraft.shared.util.TickScheduler
*/
public final AtomicBoolean scheduled = new AtomicBoolean();
public TileGeneric( TileEntityType<? extends TileGeneric> type ) public TileGeneric( TileEntityType<? extends TileGeneric> type )
{ {
super( type ); super( type );

View File

@ -89,8 +89,9 @@ public class TileCable extends TileGeneric
private final WiredModemElement cable = new CableElement(); private final WiredModemElement cable = new CableElement();
private LazyOptional<IWiredElement> elementCap; private LazyOptional<IWiredElement> elementCap;
private final IWiredNode node = cable.getNode(); private final IWiredNode node = cable.getNode();
private final TickScheduler.Token tickToken = new TickScheduler.Token( this );
private final WiredModemPeripheral modem = new WiredModemPeripheral( private final WiredModemPeripheral modem = new WiredModemPeripheral(
new ModemState( () -> TickScheduler.schedule( this ) ), new ModemState( () -> TickScheduler.schedule( tickToken ) ),
cable cable
) )
{ {
@ -170,7 +171,7 @@ public class TileCable extends TileGeneric
public void onLoad() public void onLoad()
{ {
super.onLoad(); super.onLoad();
TickScheduler.schedule( this ); TickScheduler.schedule( tickToken );
} }
@Override @Override
@ -246,7 +247,7 @@ public class TileCable extends TileGeneric
{ {
if( invalidPeripheral ) return; if( invalidPeripheral ) return;
invalidPeripheral = true; invalidPeripheral = true;
TickScheduler.schedule( this ); TickScheduler.schedule( tickToken );
} }
private void refreshPeripheral() private void refreshPeripheral()

View File

@ -100,7 +100,8 @@ public class TileWiredModemFull extends TileGeneric
private boolean destroyed = false; private boolean destroyed = false;
private boolean connectionsFormed = false; private boolean connectionsFormed = false;
private final ModemState modemState = new ModemState( () -> TickScheduler.schedule( this ) ); private final TickScheduler.Token tickToken = new TickScheduler.Token( this );
private final ModemState modemState = new ModemState( () -> TickScheduler.schedule( tickToken ) );
private final WiredModemElement element = new FullElement( this ); private final WiredModemElement element = new FullElement( this );
private LazyOptional<IWiredElement> elementCap; private LazyOptional<IWiredElement> elementCap;
private final IWiredNode node = element.getNode(); private final IWiredNode node = element.getNode();
@ -181,7 +182,7 @@ public class TileWiredModemFull extends TileGeneric
private void queueRefreshPeripheral( @Nonnull Direction facing ) private void queueRefreshPeripheral( @Nonnull Direction facing )
{ {
if( invalidSides == 0 ) TickScheduler.schedule( this ); if( invalidSides == 0 ) TickScheduler.schedule( tickToken );
invalidSides |= 1 << facing.ordinal(); invalidSides |= 1 << facing.ordinal();
} }
@ -263,7 +264,7 @@ public class TileWiredModemFull extends TileGeneric
public void onLoad() public void onLoad()
{ {
super.onLoad(); super.onLoad();
TickScheduler.schedule( this ); TickScheduler.schedule( tickToken );
} }
@Override @Override

View File

@ -32,7 +32,7 @@ public class TileWirelessModem extends TileGeneric
Peripheral( TileWirelessModem entity ) Peripheral( TileWirelessModem entity )
{ {
super( new ModemState( () -> TickScheduler.schedule( entity ) ), entity.advanced ); super( new ModemState( () -> TickScheduler.schedule( entity.tickToken ) ), entity.advanced );
this.entity = entity; this.entity = entity;
} }
@ -71,6 +71,7 @@ public class TileWirelessModem extends TileGeneric
private final ModemPeripheral modem; private final ModemPeripheral modem;
private boolean destroyed = false; private boolean destroyed = false;
private LazyOptional<IPeripheral> modemCap; private LazyOptional<IPeripheral> modemCap;
private final TickScheduler.Token tickToken = new TickScheduler.Token( this );
public TileWirelessModem( TileEntityType<? extends TileWirelessModem> type, boolean advanced ) public TileWirelessModem( TileEntityType<? extends TileWirelessModem> type, boolean advanced )
{ {
@ -83,7 +84,7 @@ public class TileWirelessModem extends TileGeneric
public void onLoad() public void onLoad()
{ {
super.onLoad(); super.onLoad();
TickScheduler.schedule( this ); TickScheduler.schedule( tickToken );
} }
@Override @Override

View File

@ -64,7 +64,7 @@ public class ServerMonitor
private void markChanged() private void markChanged()
{ {
if( !changed.getAndSet( true ) ) TickScheduler.schedule( origin ); if( !changed.getAndSet( true ) ) TickScheduler.schedule( origin.tickToken );
} }
int getTextScale() int getTextScale()

View File

@ -75,6 +75,8 @@ public class TileMonitor extends TileGeneric
private int bbX, bbY, bbWidth, bbHeight; private int bbX, bbY, bbWidth, bbHeight;
private AxisAlignedBB boundingBox; private AxisAlignedBB boundingBox;
TickScheduler.Token tickToken = new TickScheduler.Token( this );
public TileMonitor( TileEntityType<? extends TileMonitor> type, boolean advanced ) public TileMonitor( TileEntityType<? extends TileMonitor> type, boolean advanced )
{ {
super( type ); super( type );
@ -86,7 +88,7 @@ public class TileMonitor extends TileGeneric
{ {
super.onLoad(); super.onLoad();
needsValidating = true; // Same, tbh needsValidating = true; // Same, tbh
TickScheduler.schedule( this ); TickScheduler.schedule( tickToken );
} }
@Override @Override

View File

@ -6,7 +6,7 @@
package dan200.computercraft.shared.util; package dan200.computercraft.shared.util;
import dan200.computercraft.ComputerCraft; import dan200.computercraft.ComputerCraft;
import dan200.computercraft.shared.common.TileGeneric; import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.ITickList; import net.minecraft.world.ITickList;
import net.minecraft.world.World; import net.minecraft.world.World;
@ -16,6 +16,7 @@ import net.minecraftforge.fml.common.Mod;
import java.util.Queue; import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedDeque; import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.concurrent.atomic.AtomicBoolean;
/** /**
* A thread-safe version of {@link ITickList#scheduleTick(BlockPos, Object, int)}. * A thread-safe version of {@link ITickList#scheduleTick(BlockPos, Object, int)}.
@ -29,12 +30,12 @@ public final class TickScheduler
{ {
} }
private static final Queue<TileGeneric> toTick = new ConcurrentLinkedDeque<>(); private static final Queue<Token> toTick = new ConcurrentLinkedDeque<>();
public static void schedule( TileGeneric tile ) public static void schedule( Token token )
{ {
World world = tile.getLevel(); World world = token.owner.getLevel();
if( world != null && !world.isClientSide && !tile.scheduled.getAndSet( true ) ) toTick.add( tile ); if( world != null && !world.isClientSide && !token.scheduled.getAndSet( true ) ) toTick.add( token );
} }
@SubscribeEvent @SubscribeEvent
@ -42,19 +43,37 @@ public final class TickScheduler
{ {
if( event.phase != TickEvent.Phase.START ) return; if( event.phase != TickEvent.Phase.START ) return;
TileGeneric tile; Token token;
while( (tile = toTick.poll()) != null ) while( (token = toTick.poll()) != null )
{ {
tile.scheduled.set( false ); token.scheduled.set( false );
if( tile.isRemoved() ) continue; TileEntity blockEntity = token.owner;
if( blockEntity.isRemoved() ) continue;
World world = tile.getLevel(); World world = blockEntity.getLevel();
BlockPos pos = tile.getBlockPos(); BlockPos pos = blockEntity.getBlockPos();
if( world != null && pos != null && world.isAreaLoaded( pos, 0 ) && world.getBlockEntity( pos ) == tile ) if( world != null && world.isAreaLoaded( pos, 0 ) && world.getBlockEntity( pos ) == blockEntity )
{ {
world.getBlockTicks().scheduleTick( pos, tile.getBlockState().getBlock(), 0 ); world.getBlockTicks().scheduleTick( pos, blockEntity.getBlockState().getBlock(), 0 );
} }
} }
} }
/**
* An item which can be scheduled for future ticking.
* <p>
* This tracks whether the {@link TileEntity} is queued or not, as this is more efficient than maintaining a set.
* As such, it should be unique per {@link TileEntity} instance to avoid it being queued multiple times.
*/
public static class Token
{
final TileEntity owner;
final AtomicBoolean scheduled = new AtomicBoolean();
public Token( TileEntity owner )
{
this.owner = owner;
}
}
} }