Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package io.nihlen.scriptschunkloaders;

import net.fabricmc.fabric.api.gametest.v1.GameTest;

import net.minecraft.block.entity.SculkSensorBlockEntity;
import net.minecraft.component.DataComponentTypes;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
Expand All @@ -10,7 +10,6 @@
import net.minecraft.test.TestContext;
import net.minecraft.text.Text;
import net.minecraft.util.math.BlockPos;

import java.util.Objects;
import java.util.function.Function;

Expand Down Expand Up @@ -40,11 +39,18 @@
* - Minecart registers, unregisters and registers again
*
* - Minecart does not register with empty dispenser
*
* - Minecart registers with sculk sensor
*
* - Minecart unregisters with sculk sensor
* */

@SuppressWarnings("unused")
public class ScriptsChunkLoadersGameTest {
String defaultName = "Chunk Loader";
String customItemName = "My Custom Item";
Integer startLoaderFrequency = 6;
Integer stopLoaderFrequency = 5;

Function<Entity, String> getCustomName = entity -> {
var customName = entity.getCustomName();
Expand Down Expand Up @@ -351,4 +357,72 @@ public void doesNotRegisterWithEmptyDispenser(TestContext context) {
context.complete();
});
}

@GameTest(structure = "scl_tests:sculk_activate")
public void registerWithResonance(TestContext context) {
clearTest(context);

context.spawnEntity(EntityType.MINECART, 2, 1, 2);
context.removeBlock(new BlockPos(3, 1, 2));
context.putAndRemoveRedstoneBlock(new BlockPos(1, 1, 1), 1);

context.waitAndRun(15, () -> {
BlockPos pos = new BlockPos( 4, 1, 2);
SculkSensorBlockEntity sensor = context.getBlockEntity(pos, SculkSensorBlockEntity.class);

if (sensor.getLastVibrationFrequency() != startLoaderFrequency) {
throw context.createError(pos, String.format(
"Expected a vibration frequency of %s, instead got %s",
startLoaderFrequency,
sensor.getLastVibrationFrequency()
));
}

context.expectEntityWithData(
new BlockPos(2, 1, 2),
EntityType.MINECART,
getCustomName,
defaultName
);
context.complete();
});
}

@GameTest(structure = "scl_tests:sculk_activate")
public void unregisterWithResonance(TestContext context) {
clearTest(context);

context.spawnEntity(EntityType.MINECART, 2, 1, 2);
context.putAndRemoveRedstoneBlock(new BlockPos(1, 1, 1), 1);

context.waitAndRun(4, () -> {
context.expectEntityWithData(new BlockPos(2, 1, 2), EntityType.MINECART, getCustomName, defaultName);
context.removeBlock(new BlockPos(3, 1, 2));

context.waitAndRun(4, () -> {
context.putAndRemoveRedstoneBlock(new BlockPos(1, 1, 1), 1);

context.waitAndRun(8, () -> {
BlockPos pos = new BlockPos( 4, 1, 2);
SculkSensorBlockEntity sensor = context.getBlockEntity(pos, SculkSensorBlockEntity.class);

if (sensor.getLastVibrationFrequency() != stopLoaderFrequency) {
throw context.createError(pos, String.format(
"Expected a vibration frequency of %s, instead got %s",
stopLoaderFrequency,
sensor.getLastVibrationFrequency()
));
}

context.expectEntityWithData(
new BlockPos(2, 1, 2),
EntityType.MINECART,
getCustomName,
null
);
context.complete();
});
});
});
}
}
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@

import net.fabricmc.api.ModInitializer;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
import net.fabricmc.fabric.api.gamerule.v1.GameRuleFactory;
import net.fabricmc.fabric.api.gamerule.v1.GameRuleRegistry;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.world.BlockView;
import net.minecraft.world.ChunkRegion;
import net.minecraft.world.GameRules;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand All @@ -14,6 +21,8 @@ public class ScriptsChunkLoadersMod implements ModInitializer {
public static final Logger LOGGER = LoggerFactory.getLogger(MODID);
public static final ChunkLoaderManager CHUNK_LOADER_MANAGER = new ChunkLoaderManager();

public static final GameRules.Key<GameRules.BooleanRule> ALWAYS_SHOW_LOADER_NAME = GameRuleRegistry.register("alwaysShowLoaderName", GameRules.Category.MISC, GameRuleFactory.createBooleanRule(true));

@Override
public void onInitialize() {
// This code runs as soon as Minecraft is in a mod-load-ready state.
Expand All @@ -22,4 +31,25 @@ public void onInitialize() {

ServerLifecycleEvents.SERVER_STARTED.register(CHUNK_LOADER_MANAGER::initialize);
}

public static boolean isCustomNameVisible(BlockView world) {
GameRules rules = null;

if (world instanceof ServerWorld serverWorld)
rules = serverWorld.getGameRules();
else if (world instanceof ChunkRegion chunkRegion)
{
MinecraftServer server = chunkRegion.getServer();

if (server != null) {
rules = server.getGameRules();
}
}

if (rules != null) {
return rules.getBoolean(ALWAYS_SHOW_LOADER_NAME);
}

return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import net.minecraft.entity.vehicle.*;
import net.minecraft.world.TeleportTarget;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
Expand All @@ -28,9 +27,7 @@ public abstract class AbstractMinecartEntityMixin extends Entity implements Mine
private boolean isChunkLoader = false;
@Unique
private int particleTicker = 0;
@Unique
private final int particleInterval = 3;
@Unique
@Unique
private ChunkPos lastChunkPos = null;

public AbstractMinecartEntityMixin(EntityType<?> type, World world) {
Expand Down Expand Up @@ -62,7 +59,7 @@ private void injectConstructor(CallbackInfo callbackInfo) {
if (minecartType == EntityType.CHEST_MINECART) {
//noinspection DataFlowIssue - We're sure this is a chest because of the if statement.
var entity = (ChestMinecartEntity)(Object)this;
var firstSlot = entity.getInventory().get(0);
var firstSlot = entity.getInventory().getFirst();

var hasCustomName = firstSlot.get(DataComponentTypes.CUSTOM_NAME) != null;

Expand All @@ -71,21 +68,23 @@ private void injectConstructor(CallbackInfo callbackInfo) {
scripts_chunk_loaders$setChunkLoaderName(name);
return;
}
};
}

scripts_chunk_loaders$setChunkLoaderName("Chunk Loader");
scripts_chunk_loaders$setChunkLoaderName("Chunk Loader");
}

public void scripts_chunk_loaders$setChunkLoaderName(String name) {
var nameText = Text.literal(name);
this.setCustomName(nameText);
this.setCustomNameVisible(true);
this.setCustomNameVisible(ScriptsChunkLoadersMod.isCustomNameVisible(getWorld()));
}

public void scripts_chunk_loaders$stopChunkLoader() {
scripts_chunk_loaders$stopChunkLoader(false);
this.lastChunkPos = null;
}

@Unique
public void scripts_chunk_loaders$stopChunkLoader(Boolean keepName) {
this.isChunkLoader = false;

Expand Down Expand Up @@ -147,7 +146,7 @@ public Entity teleportTo(TeleportTarget teleportTarget) {
@Unique
private void tickParticles() {
this.particleTicker += 1;
if (this.particleTicker >= particleInterval) {
if (this.particleTicker >= 3) {
this.particleTicker = 0;
this.spawnParticles();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Box;
import net.minecraft.world.event.GameEvent;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
Expand Down Expand Up @@ -61,15 +62,30 @@ private void toggleMinecraftChunkLoader(ServerWorld world, BlockState state, Blo
BlockPos blockPos = pos.offset(state.get(DispenserBlock.FACING));
List<AbstractMinecartEntity> list = world.getEntitiesByClass(AbstractMinecartEntity.class, new Box(blockPos), EntityPredicates.VALID_ENTITY);

boolean stoppedLoader = false;
boolean startedLoader = false;

for (AbstractMinecartEntity entity : list) {
MinecartEntityExt cart = (MinecartEntityExt)entity;

if (cart.scripts_chunk_loaders$isChunkLoader()) {
cart.scripts_chunk_loaders$stopChunkLoader();

stoppedLoader = true;
} else {
cart.scripts_chunk_loaders$startChunkLoader();
cart.scripts_chunk_loaders$setChunkLoaderNameFromInventory();

startedLoader = true;
}
}

if (startedLoader) {
world.emitGameEvent(GameEvent.RESONATE_6, pos, GameEvent.Emitter.of(state));
}

if (stoppedLoader) {
world.emitGameEvent(GameEvent.RESONATE_5, pos, GameEvent.Emitter.of(state));
}
}
}