Skip to content

Commit

Permalink
Moving Tile Ticks on 1.18 (#637)
Browse files Browse the repository at this point in the history
* Fix everything

Added support for 1.18 moving tile ticks (redstone, fire etc.)

* Remove Debug Message

* Fix tile entity deletion

* debug

* Debug deleted ticks

* Process Ticks and tiles seperately

* Piston bug quick fix

Prevents a bug that caused pistons to delete themselves or lock up if they moved during a craft jump.

---------

Co-authored-by: TylerS1066 <[email protected]>
  • Loading branch information
drfiveminusmint and TylerS1066 authored Jun 2, 2024
1 parent 125f9a7 commit d18fee3
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 39 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,15 @@ protected void execute() {
MovecraftLocation newLocation = MathUtils.rotateVec(rotation,originalLocation.subtract(originPoint)).add(originPoint);
newHitBox.add(newLocation);

//Prevent piston bug
if (originalLocation.toBukkit(getCraft().getWorld()).getBlock().getType().equals(Material.MOVING_PISTON)) {
failed = true;
failMessage = (String.format(I18nSupport.getInternationalisedString("Translation - Failed Craft is obstructed")
+ " @ %d,%d,%d,%s", originalLocation.getX(), originalLocation.getY(), originalLocation.getZ(),
originalLocation.toBukkit(craft.getWorld()).getBlock().getType()));
break;
}

Material oldMaterial = originalLocation.toBukkit(w).getBlock().getType();
//prevent chests collision
if (Tags.CHESTS.contains(oldMaterial) && !checkChests(oldMaterial, newLocation)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,12 @@ else if (world.equals(craft.getWorld())
newHitBox.add(newLocation);
continue;
}
//Prevent piston bug
if (oldLocation.toBukkit(world).getBlock().getType().equals(Material.MOVING_PISTON))
fail(String.format(I18nSupport.getInternationalisedString("Translation - Failed Craft is obstructed")
+ " @ %d,%d,%d,%s", oldLocation.getX(), oldLocation.getY(), oldLocation.getZ(),
oldLocation.toBukkit(craft.getWorld()).getBlock().getType()));

final Material testMaterial = newLocation.toBukkit(world).getBlock().getType();

if (Tags.CHESTS.contains(testMaterial) && checkChests(testMaterial, newLocation)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.level.chunk.LevelChunkSection;
import net.minecraft.world.ticks.LevelChunkTicks;
import net.minecraft.world.ticks.ScheduledTick;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.data.BlockData;
Expand All @@ -37,6 +39,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Predicate;

@SuppressWarnings("unused")
public class IWorldHandler extends WorldHandler {
Expand Down Expand Up @@ -72,15 +75,21 @@ public void rotateCraft(@NotNull Craft craft, @NotNull MovecraftLocation originP
//*******************************************
ServerLevel nativeWorld = ((CraftWorld) craft.getWorld()).getHandle();
List<TileHolder> tiles = new ArrayList<>();
List<TickHolder> ticks = new ArrayList<>();
//get the tiles
for (BlockPos position : rotatedPositions.keySet()) {
//BlockEntity tile = nativeWorld.removeBlockEntity(position);

BlockEntity tile = removeBlockEntity(nativeWorld, position);
if (tile == null)
continue;
// tile.a(ROTATION[rotation.ordinal()]);
if (tile != null)
tiles.add(new TileHolder(tile, position));

//get the nextTick to move with the tile
tiles.add(new TileHolder(tile, tickProvider.getNextTick(nativeWorld, position), position));
ScheduledTick tickHere = tickProvider.getNextTick(nativeWorld, position);
if (tickHere != null) {
((LevelChunkTicks) nativeWorld.getChunkAt(position).getBlockTicks()).removeIf(
(Predicate<ScheduledTick>) scheduledTick -> scheduledTick.equals(tickHere));
ticks.add(new TickHolder(tickHere, position));
}
}

//*******************************************
Expand All @@ -107,10 +116,10 @@ public void rotateCraft(@NotNull Craft craft, @NotNull MovecraftLocation originP
//TODO: go by chunks
for (TileHolder tileHolder : tiles) {
moveBlockEntity(nativeWorld, rotatedPositions.get(tileHolder.getTilePosition()), tileHolder.getTile());
if (tileHolder.getNextTick() == null)
continue;
}
for (TickHolder tickHolder : ticks) {
final long currentTime = nativeWorld.M.getGameTime();
nativeWorld.getBlockTicks().schedule(new ScheduledTick<>((Block) tileHolder.getNextTick().type(), rotatedPositions.get(tileHolder.getNextTick().pos()), tileHolder.getNextTick().triggerTick() - currentTime, tileHolder.getNextTick().priority(), tileHolder.getNextTick().subTickOrder()));
nativeWorld.getBlockTicks().schedule(new ScheduledTick<>((Block) tickHolder.getTick().type(), rotatedPositions.get(tickHolder.getTick().pos()), tickHolder.getTick().triggerTick() - currentTime, tickHolder.getTick().priority(), tickHolder.getTick().subTickOrder()));
}

//*******************************************
Expand Down Expand Up @@ -139,20 +148,24 @@ public void translateCraft(@NotNull Craft craft, @NotNull MovecraftLocation disp
//* Step two: Get the tiles *
//*******************************************
List<TileHolder> tiles = new ArrayList<>();
List<TickHolder> ticks = new ArrayList<>();
//get the tiles
for (int i = 0, positionsSize = positions.size(); i < positionsSize; i++) {
BlockPos position = positions.get(i);
if (oldNativeWorld.getBlockState(position) == Blocks.AIR.defaultBlockState())
continue;
//BlockEntity tile = nativeWorld.removeBlockEntity(position);
BlockEntity tile = removeBlockEntity(oldNativeWorld, position);
if (tile == null)
continue;
//get the nextTick to move with the tile
if (tile != null)
tiles.add(new TileHolder(tile, position));

//nativeWorld.capturedTileEntities.remove(position);
//nativeWorld.getChunkAtWorldCoords(position).getTileEntities().remove(position);
tiles.add(new TileHolder(tile, tickProvider.getNextTick(oldNativeWorld, position), position));
//get the nextTick to move with the tile
ScheduledTick tickHere = tickProvider.getNextTick(oldNativeWorld, position);
if (tickHere != null) {
((LevelChunkTicks) nativeWorld.getChunkAt(position).getBlockTicks()).removeIf(
(Predicate<ScheduledTick>) scheduledTick -> scheduledTick.equals(tickHere));
ticks.add(new TickHolder(tickHere, position));
}

}
//*******************************************
Expand Down Expand Up @@ -181,10 +194,11 @@ public void translateCraft(@NotNull Craft craft, @NotNull MovecraftLocation disp
for (int i = 0, tilesSize = tiles.size(); i < tilesSize; i++) {
TileHolder tileHolder = tiles.get(i);
moveBlockEntity(nativeWorld, tileHolder.getTilePosition().offset(translateVector), tileHolder.getTile());
if (tileHolder.getNextTick() == null)
continue;
}
for (int i = 0, tickSize = ticks.size(); i < tickSize; i++) {
TickHolder tickHolder = ticks.get(i);
final long currentTime = nativeWorld.getGameTime();
nativeWorld.getBlockTicks().schedule(new ScheduledTick<>((Block) tileHolder.getNextTick().type(), tileHolder.getTilePosition().offset(translateVector), tileHolder.getNextTick().triggerTick() - currentTime, tileHolder.getNextTick().priority(), tileHolder.getNextTick().subTickOrder()));
nativeWorld.getBlockTicks().schedule(new ScheduledTick<>((Block) tickHolder.getTick().type(), tickHolder.getTickPosition().offset(translateVector), tickHolder.getTick().triggerTick() - currentTime, tickHolder.getTick().priority(), tickHolder.getTick().subTickOrder()));
}
//*******************************************
//* Step five: Destroy the leftovers *
Expand Down Expand Up @@ -301,14 +315,11 @@ private void moveBlockEntity(@NotNull Level nativeWorld, @NotNull BlockPos newPo
private static class TileHolder {
@NotNull
private final BlockEntity tile;
@Nullable
private final ScheduledTick<?> nextTick;
@NotNull
private final BlockPos tilePosition;

public TileHolder(@NotNull BlockEntity tile, @Nullable ScheduledTick<?> nextTick, @NotNull BlockPos tilePosition) {
public TileHolder(@NotNull BlockEntity tile, @NotNull BlockPos tilePosition) {
this.tile = tile;
this.nextTick = nextTick;
this.tilePosition = tilePosition;
}

Expand All @@ -318,14 +329,32 @@ public BlockEntity getTile() {
return tile;
}

@Nullable
public ScheduledTick<?> getNextTick() {
return nextTick;
}

@NotNull
public BlockPos getTilePosition() {
return tilePosition;
}
}

private static class TickHolder {
@NotNull
private final ScheduledTick tick;
@NotNull
private final BlockPos tickPosition;

public TickHolder(@NotNull ScheduledTick tick, @NotNull BlockPos tilePosition) {
this.tick = tick;
this.tickPosition = tilePosition;
}


@NotNull
public ScheduledTick getTick() {
return tick;
}

@NotNull
public BlockPos getTickPosition() {
return tickPosition;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,39 +4,39 @@
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.levelgen.structure.BoundingBox;
import net.minecraft.world.ticks.LevelChunkTicks;
import net.minecraft.world.ticks.LevelTicks;
import net.minecraft.world.ticks.ScheduledTick;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.lang.reflect.Field;
import java.util.List;
import java.util.Queue;
import java.util.stream.Stream;

public class NextTickProvider {

@Nullable
public ScheduledTick<?> getNextTick(@NotNull ServerLevel world, @NotNull BlockPos position){
LevelTicks<Block> tickList = world.getBlockTicks();
LevelChunkTicks<Block> tickList = (LevelChunkTicks<Block>) world
.getChunk(position)
.getBlockTicks();

var box = BoundingBox.encapsulatingPositions(List.of(position));
if(box.isEmpty()){
return null;
}
Queue<ScheduledTick<?>> toRunThisTick;
try {
Field toRunThisTickField = LevelTicks.class.getDeclaredField("g");
toRunThisTickField.setAccessible(true);
toRunThisTick = (Queue<ScheduledTick<?>>) toRunThisTickField.get(tickList);
} catch (NoSuchFieldException | IllegalAccessException e) {
e.printStackTrace();
if(box.isEmpty()) {
return null;
}
for (var iter = toRunThisTick.iterator(); iter.hasNext(); ) {

Stream<ScheduledTick<Block>> ticks = tickList.getAll();

for (var iter = ticks.iterator(); iter.hasNext(); ) {
var next = iter.next();
if (!next.pos().equals(position)) {
continue;
}
iter.remove();
return next;
}
return null;
Expand Down

0 comments on commit d18fee3

Please sign in to comment.