diff --git a/src/main/java/io/ib67/sfcraft/SFCraft.java b/src/main/java/io/ib67/sfcraft/SFCraft.java index 986f383..d50623b 100644 --- a/src/main/java/io/ib67/sfcraft/SFCraft.java +++ b/src/main/java/io/ib67/sfcraft/SFCraft.java @@ -7,6 +7,8 @@ import com.mojang.brigadier.builder.LiteralArgumentBuilder; 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 lombok.Getter; import lombok.SneakyThrows; import net.fabricmc.api.ModInitializer; @@ -38,6 +40,8 @@ public class SFCraft implements ModInitializer { private String motd; @Getter private String updateLog; + @Getter + private RandomEventRegistry randomEventRegistry; @Override @SneakyThrows @@ -52,12 +56,17 @@ public class SFCraft implements ModInitializer { motd = loadMotd(); updateLog = loadUpdateLog(); geoIPService = new GeoIPService(); + this.setupRandomEvents(); ServerPlayConnectionEvents.JOIN.register(listener::onPlayerJoin); CommandRegistrationCallback.EVENT.register(this::registerCommands); ServerLifecycleEvents.SERVER_STARTED.register(this::onServerStarted); } + private void setupRandomEvents() { + randomEventRegistry = new SFRandomEventRegistry(); + } + private void onServerStarted(MinecraftServer minecraftServer) { server = minecraftServer; server.setMotd(motd); diff --git a/src/main/java/io/ib67/sfcraft/event/RandomEvent.java b/src/main/java/io/ib67/sfcraft/event/RandomEvent.java new file mode 100644 index 0000000..e161da6 --- /dev/null +++ b/src/main/java/io/ib67/sfcraft/event/RandomEvent.java @@ -0,0 +1,15 @@ +package io.ib67.sfcraft.event; + +import net.minecraft.registry.RegistryKey; +import net.minecraft.world.World; + +public abstract class RandomEvent { + /** + * @return duration + */ + public abstract int start(); + + public abstract void onUpdate(int ticks); + + public abstract void end(); +} diff --git a/src/main/java/io/ib67/sfcraft/registry/event/ActiveEvent.java b/src/main/java/io/ib67/sfcraft/registry/event/ActiveEvent.java new file mode 100644 index 0000000..77594f2 --- /dev/null +++ b/src/main/java/io/ib67/sfcraft/registry/event/ActiveEvent.java @@ -0,0 +1,8 @@ +package io.ib67.sfcraft.registry.event; + +import io.ib67.sfcraft.event.RandomEvent; + +public interface ActiveEvent { + RandomEvent getEvent(); + int getRemainingTicks(); +} diff --git a/src/main/java/io/ib67/sfcraft/registry/event/RandomEventRegistry.java b/src/main/java/io/ib67/sfcraft/registry/event/RandomEventRegistry.java new file mode 100644 index 0000000..971b2e4 --- /dev/null +++ b/src/main/java/io/ib67/sfcraft/registry/event/RandomEventRegistry.java @@ -0,0 +1,13 @@ +package io.ib67.sfcraft.registry.event; + +import io.ib67.sfcraft.event.RandomEvent; +import net.minecraft.world.World; + +import java.util.List; +import java.util.function.Function; +import java.util.function.Predicate; + +public interface RandomEventRegistry { + List getActiveEvents(); + void registerEvent(Function event, Predicate worldTickPredicate); +} diff --git a/src/main/java/io/ib67/sfcraft/registry/event/SFRandomEventRegistry.java b/src/main/java/io/ib67/sfcraft/registry/event/SFRandomEventRegistry.java new file mode 100644 index 0000000..a7858d6 --- /dev/null +++ b/src/main/java/io/ib67/sfcraft/registry/event/SFRandomEventRegistry.java @@ -0,0 +1,7 @@ +package io.ib67.sfcraft.registry.event; + +public class SFRandomEventRegistry extends SimpleRandomEventRegistry { + public SFRandomEventRegistry() { + + } +} diff --git a/src/main/java/io/ib67/sfcraft/registry/event/SimpleRandomEventRegistry.java b/src/main/java/io/ib67/sfcraft/registry/event/SimpleRandomEventRegistry.java new file mode 100644 index 0000000..7916aec --- /dev/null +++ b/src/main/java/io/ib67/sfcraft/registry/event/SimpleRandomEventRegistry.java @@ -0,0 +1,73 @@ +package io.ib67.sfcraft.registry.event; + +import io.ib67.sfcraft.event.RandomEvent; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.world.World; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Function; +import java.util.function.Predicate; + +public class SimpleRandomEventRegistry implements RandomEventRegistry { + private final List entries = new ArrayList<>(); + private final List activeEvents = new ArrayList<>(); + + protected SimpleRandomEventRegistry() { + ServerTickEvents.END_WORLD_TICK.register(this::afterWorldTick); + } + + private void afterWorldTick(ServerWorld serverWorld) { + for (RegisteredEntry entry : entries) { + if (!entry.started && entry.worldTickPredicate.test(serverWorld)) { + var event = entry.event.apply(serverWorld); + activeEvents.add(new StartedEntry(event, () -> entry.started = false, event.start())); + } + } + var it = activeEvents.iterator(); + while (it.hasNext()) { + var entry = it.next(); + entry.event.onUpdate(++entry.ticks); + if (entry.ticks >= entry.maxTicks) { + it.remove(); + entry.event.end(); + entry.afterEvent.run(); + } + } + } + + @Override + @SuppressWarnings("unchecked") + public List getActiveEvents() { + return (List) (Object) activeEvents; + } + + @Override + public void registerEvent(Function event, Predicate worldTickPredicate) { + entries.add(new RegisteredEntry(event, worldTickPredicate)); + } + + @RequiredArgsConstructor + private static final class StartedEntry implements ActiveEvent { + @Getter + private final RandomEvent event; + private final Runnable afterEvent; + private final int maxTicks; + private int ticks; + + @Override + public int getRemainingTicks() { + return maxTicks - ticks; + } + } + + @RequiredArgsConstructor + private static final class RegisteredEntry { + private final Function event; + private final Predicate worldTickPredicate; + private boolean started; + } +}