add: long night event (#4)

add(mixin): PlayerEntityMixin#onSleep
This commit is contained in:
iceBear67 committed 2024-07-10 01:12:23 +08:00
1 parent 9066295d75
commit 8fa47f9251
10 files changed
+130 -15

No files matched your search

+12 -1
View File
@@ -1,11 +1,14 @@
package io.ib67.sfcraft;
import com.maxmind.geoip2.exception.GeoIp2Exception;
import com.mojang.datafixers.util.Either;
import io.ib67.sfcraft.event.longnight.LongNightEvent;
import lombok.SneakyThrows;
import net.fabricmc.fabric.api.networking.v1.PacketSender;
import net.minecraft.component.DataComponentTypes;
import net.minecraft.component.type.WrittenBookContentComponent;
import net.minecraft.entity.damage.DamageSource;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.network.ClientConnection;
@@ -15,10 +18,11 @@ import net.minecraft.server.network.ServerPlayNetworkHandler;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.RawFilteredPair;
import net.minecraft.text.Text;
import net.minecraft.util.Unit;
import net.minecraft.util.Uuids;
import net.minecraft.util.math.BlockPos;
import java.net.InetSocketAddress;
import java.nio.file.Files;
import java.time.Clock;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
@@ -133,4 +137,11 @@ public class Listener {
return originalMetadata;
}
}
public Either<PlayerEntity.SleepFailureReason, Unit> onPlayerSleep(BlockPos pos) {
if (LongNightEvent.isRunning()) {
return Either.left(PlayerEntity.SleepFailureReason.NOT_POSSIBLE_HERE);
}
return Either.right(Unit.INSTANCE);
}
}
+1 -1
View File
@@ -8,7 +8,7 @@ import com.mojang.brigadier.builder.RequiredArgumentBuilder;
import io.ib67.sfcraft.config.SFConfig;
import io.ib67.sfcraft.geoip.GeoIPService;
import io.ib67.sfcraft.registry.event.RandomEventRegistry;
import io.ib67.sfcraft.registry.event.SFRandomEventRegistry;
import io.ib67.sfcraft.event.SFRandomEventRegistry;
import lombok.Getter;
import lombok.SneakyThrows;
import net.fabricmc.api.ModInitializer;
@@ -5,7 +5,7 @@ import net.minecraft.world.World;
public abstract class RandomEvent {
/**
* @return duration
* @return duration, -1 for no-update and {@link #end()} will not be called.
*/
public abstract int start();
@@ -0,0 +1,13 @@
package io.ib67.sfcraft.event;
import io.ib67.sfcraft.event.longnight.DawnAfterLongNightEvent;
import io.ib67.sfcraft.event.longnight.LongNightEvent;
import io.ib67.sfcraft.registry.event.SimpleRandomEventRegistry;
import net.minecraft.world.World;
public class SFRandomEventRegistry extends SimpleRandomEventRegistry {
public SFRandomEventRegistry() {
registerEvent(LongNightEvent::new, World.OVERWORLD, world -> world.getTimeOfDay() % 18000 == 0); // At midnight
registerEvent(DawnAfterLongNightEvent::new, World.OVERWORLD, world -> world.getTimeOfDay() % 22200 == 0); // At dawn
}
}
@@ -0,0 +1,37 @@
package io.ib67.sfcraft.event.longnight;
import io.ib67.sfcraft.event.RandomEvent;
import lombok.RequiredArgsConstructor;
import net.minecraft.text.Text;
import net.minecraft.util.Colors;
import net.minecraft.world.World;
import java.awt.*;
@RequiredArgsConstructor
public class DawnAfterLongNightEvent extends RandomEvent {
private final World world;
@Override
public int start() {
if (LongNightEvent.justExpirencedLongNight) {
LongNightEvent.justExpirencedLongNight = false;
world.getServer().getPlayerManager().broadcast(
Text.literal("珍惜太阳正是永夜的意义。")
.withColor(new Color(235, 91, 0).getRGB())
.append(Text.literal("(永夜事件结束)").withColor(Colors.LIGHT_GRAY))
, false);
}
return -1;
}
@Override
public void onUpdate(int ticks) {
throw new UnsupportedOperationException();
}
@Override
public void end() {
throw new UnsupportedOperationException();
}
}
@@ -0,0 +1,43 @@
package io.ib67.sfcraft.event.longnight;
import io.ib67.sfcraft.SFCraft;
import io.ib67.sfcraft.event.RandomEvent;
import lombok.RequiredArgsConstructor;
import net.minecraft.text.Text;
import net.minecraft.util.Colors;
import net.minecraft.world.GameRules;
import net.minecraft.world.World;
@RequiredArgsConstructor
public class LongNightEvent extends RandomEvent {
static boolean justExpirencedLongNight;
private final World world;
private boolean doDaylightCycle;
private boolean doTraderSpawning;
@Override
public int start() {
world.getServer().getPlayerManager().broadcast(Text.literal("月亮停滞在空中...").withColor(Colors.BLUE), false);
this.doDaylightCycle = world.getGameRules().getBoolean(GameRules.DO_DAYLIGHT_CYCLE);
this.doTraderSpawning = world.getGameRules().getBoolean(GameRules.DO_TRADER_SPAWNING);
world.getGameRules().get(GameRules.DO_DAYLIGHT_CYCLE).set(false, world.getServer());
world.getGameRules().get(GameRules.DO_TRADER_SPAWNING).set(false, world.getServer());
return world.random.nextBetween(8400, 2 * 8400);
}
@Override
public void onUpdate(int ticks) {
}
@Override
public void end() {
justExpirencedLongNight = true;
world.getGameRules().get(GameRules.DO_DAYLIGHT_CYCLE).set(doDaylightCycle, world.getServer());
world.getGameRules().get(GameRules.DO_TRADER_SPAWNING).set(doTraderSpawning, world.getServer());
}
public static boolean isRunning() {
return LongNightEvent.justExpirencedLongNight || SFCraft.getInstance().getRandomEventRegistry()
.getActiveEvents().stream().anyMatch(it -> it.getEvent().getClass() == LongNightEvent.class); // faster than instanceof
}
}
@@ -1,13 +1,17 @@
package io.ib67.sfcraft.mixin.server;
import com.mojang.datafixers.util.Either;
import io.ib67.sfcraft.SFCraft;
import net.minecraft.entity.damage.DamageSource;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.util.Unit;
import net.minecraft.util.math.BlockPos;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(ServerPlayerEntity.class)
public class PlayerEntityMixin {
@@ -15,4 +19,9 @@ public class PlayerEntityMixin {
public void onDeath(DamageSource damageSource, CallbackInfo ci) {
SFCraft.getInstance().getListener().onPlayerDeath((ServerPlayerEntity) (Object) this, damageSource);
}
@Inject(method = "trySleep", at = @At("HEAD"), cancellable = true)
public void onSleep(BlockPos pos, CallbackInfoReturnable<Either<PlayerEntity.SleepFailureReason, Unit>> cir) {
if (cir.isCancellable()) cir.setReturnValue(SFCraft.getInstance().getListener().onPlayerSleep(pos));
}
}
@@ -1,6 +1,7 @@
package io.ib67.sfcraft.registry.event;
import io.ib67.sfcraft.event.RandomEvent;
import net.minecraft.registry.RegistryKey;
import net.minecraft.world.World;
import java.util.List;
@@ -9,5 +10,6 @@ import java.util.function.Predicate;
public interface RandomEventRegistry {
List<ActiveEvent> getActiveEvents();
void registerEvent(Function<World, RandomEvent> event, Predicate<World> worldTickPredicate);
void registerEvent(Function<World, RandomEvent> event, RegistryKey<World> world, Predicate<World> worldTickPredicate);
}
@@ -1,7 +0,0 @@
package io.ib67.sfcraft.registry.event;
public class SFRandomEventRegistry extends SimpleRandomEventRegistry {
public SFRandomEventRegistry() {
}
}
@@ -4,6 +4,8 @@ import io.ib67.sfcraft.event.RandomEvent;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents;
import net.minecraft.registry.RegistryKey;
import net.minecraft.registry.RegistryKeys;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.world.World;
@@ -22,9 +24,13 @@ public class SimpleRandomEventRegistry implements RandomEventRegistry {
private void afterWorldTick(ServerWorld serverWorld) {
for (RegisteredEntry entry : entries) {
if (!entry.started && entry.worldTickPredicate.test(serverWorld)) {
if (entry.world == serverWorld.getRegistryKey()
&& !entry.started && entry.worldTickPredicate.test(serverWorld)) {
var event = entry.event.apply(serverWorld);
activeEvents.add(new StartedEntry(event, () -> entry.started = false, event.start()));
var ticks = event.start();
if (ticks > 0) {
activeEvents.add(new StartedEntry(event, () -> entry.started = false, ticks));
}
}
}
var it = activeEvents.iterator();
@@ -46,8 +52,8 @@ public class SimpleRandomEventRegistry implements RandomEventRegistry {
}
@Override
public void registerEvent(Function<World, RandomEvent> event, Predicate<World> worldTickPredicate) {
entries.add(new RegisteredEntry(event, worldTickPredicate));
public void registerEvent(Function<World, RandomEvent> event, RegistryKey<World> world, Predicate<World> worldTickPredicate) {
entries.add(new RegisteredEntry(world, event, worldTickPredicate));
}
@RequiredArgsConstructor
@@ -66,6 +72,7 @@ public class SimpleRandomEventRegistry implements RandomEventRegistry {
@RequiredArgsConstructor
private static final class RegisteredEntry {
private final RegistryKey<World> world;
private final Function<World, RandomEvent> event;
private final Predicate<World> worldTickPredicate;
private boolean started;