Skip to content

Commit

Permalink
lifecycle-events 85%
Browse files Browse the repository at this point in the history
  • Loading branch information
TexBlock committed Aug 4, 2024
1 parent 6d0fa7a commit 3c462a3
Show file tree
Hide file tree
Showing 26 changed files with 814 additions and 128 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

import net.minecraft.registry.DynamicRegistryManager;

public final class LifecycleEvents {
public class LifecycleEvent {

/**
* Called when tags are loaded or updated.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package band.kessoku.lib.events.lifecycle.api;

import band.kessoku.lib.event.api.Event;

import net.minecraft.block.entity.BlockEntity;
import net.minecraft.server.world.ServerWorld;

public class ServerBlockEntityEvent {

/**
* Called when an BlockEntity is loaded into a ServerWorld.
*
* <p>When this is event is called, the block entity is already in the world.
* However, its data might not be loaded yet, so don't rely on it.
*/
public static final Event<Loaded> LOADED = Event.of(loadeds -> (blockEntity, world) -> {
for (Loaded loaded : loadeds) {
loaded.onLoaded(blockEntity, world);
}
});

/**
* Called when an BlockEntity is about to be unloaded from a ServerWorld.
*
* <p>When this event is called, the block entity is still present on the world.
*/
public static final Event<Unloaded> UNLOADED = Event.of(unloadeds -> (blockEntity, world) -> {
for (Unloaded unloaded : unloadeds) {
unloaded.onUnloaded(blockEntity, world);
}
});

@FunctionalInterface
public interface Loaded {
void onLoaded(BlockEntity blockEntity, ServerWorld world);
}

@FunctionalInterface
public interface Unloaded {
void onUnloaded(BlockEntity blockEntity, ServerWorld world);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package band.kessoku.lib.events.lifecycle.api;

import band.kessoku.lib.event.api.Event;

import net.minecraft.server.world.ServerWorld;
import net.minecraft.world.chunk.WorldChunk;

public class ServerChunkEvent {

/**
* Called when a chunk is loaded into a ServerWorld.
*
* <p>When this event is called, the chunk is already in the world.
*/
public static final Event<Loaded> LOADED = Event.of(loadeds -> (serverWorld, chunk) -> {
for (Loaded loaded : loadeds) {
loaded.onChunkLoaded(serverWorld, chunk);
}
});

/**
* Called when a chunk is unloaded from a ServerWorld.
*
* <p>When this event is called, the chunk is still present in the world.
*/
public static final Event<Unloaded> UNLOADED = Event.of(unloadeds -> (serverWorld, chunk) -> {
for (Unloaded unloaded : unloadeds) {
unloaded.onChunkUnloaded(serverWorld, chunk);
}
});

@FunctionalInterface
public interface Loaded {
void onChunkLoaded(ServerWorld world, WorldChunk chunk);
}

@FunctionalInterface
public interface Unloaded {
void onChunkUnloaded(ServerWorld world, WorldChunk chunk);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package band.kessoku.lib.events.lifecycle.api;

import band.kessoku.lib.event.api.Event;

import net.minecraft.entity.Entity;
import net.minecraft.entity.EquipmentSlot;
import net.minecraft.entity.LivingEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.server.world.ServerWorld;

public class ServerEntityEvent {
/**
* Called when an Entity is loaded into a ServerWorld.
*
* <p>When this event is called, the entity is already in the world.
*/
public static final Event<Loaded> LOADED = Event.of(loadeds -> (entity, world) -> {
for (Loaded loaded : loadeds) {
loaded.onLoaded(entity, world);
}
});

/**
* Called when an Entity is unloaded from a ServerWorld.
*
* <p>This event is called before the entity is removed from the world.
*/
public static final Event<Unloaded> UNLOADED = Event.of(unloadeds -> (entity, world) -> {
for (Unloaded unloaded : unloadeds) {
unloaded.onUnloaded(entity, world);
}
});

/**
* Called during {@link LivingEntity#tick()} if the Entity's equipment has been changed or mutated.
*
* <p>This event is also called when the entity joins the world.
* A change in equipment is determined by {@link ItemStack#areEqual(ItemStack, ItemStack)}.
*/
public static final Event<EquipmentChanged> EQUIPMENT_CHANGED = Event.of(equipmentChangeds -> (livingEntity, equipmentSlot, previous, next) -> {
for (EquipmentChanged equipmentChanged : equipmentChangeds) {
equipmentChanged.onChanged(livingEntity, equipmentSlot, previous, next);
}
});

@FunctionalInterface
public interface Loaded {
void onLoaded(Entity entity, ServerWorld world);
}

@FunctionalInterface
public interface Unloaded {
void onUnloaded(Entity entity, ServerWorld world);
}

@FunctionalInterface
public interface EquipmentChanged {
void onChanged(LivingEntity livingEntity, EquipmentSlot equipmentSlot, ItemStack previousStack, ItemStack currentStack);
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
package band.kessoku.lib.events.lifecycle.api.server;
package band.kessoku.lib.events.lifecycle.api;

import band.kessoku.lib.event.api.Event;

import net.minecraft.resource.LifecycledResourceManager;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.network.ServerPlayerEntity;

public class ServerLifecycleEvents {
public class ServerLifecycleEvent {

/**
* Called when a Minecraft server is starting.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
package band.kessoku.lib.events.lifecycle.api.server;
package band.kessoku.lib.events.lifecycle.api;

import band.kessoku.lib.event.api.Event;

import net.minecraft.server.MinecraftServer;
import net.minecraft.server.world.ServerWorld;

public final class ServerTickEvents {
public class ServerTickEvent {

/**
* Called at the start of the server tick.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
package band.kessoku.lib.events.lifecycle.api.server;
package band.kessoku.lib.events.lifecycle.api;

import band.kessoku.lib.event.api.Event;

import net.minecraft.server.MinecraftServer;
import net.minecraft.server.world.ServerWorld;

public class ServerWorldEvents {
public class ServerWorldEvent {

/**
* Called just after a world is loaded by a Minecraft server.
Expand All @@ -21,7 +21,7 @@ public class ServerWorldEvents {
/**
* Called before a world is unloaded by a Minecraft server.
*
* <p>This typically occurs after a server has {@link ServerLifecycleEvents#STOPPING started shutting down}.
* <p>This typically occurs after a server has {@link ServerLifecycleEvent#STOPPING started shutting down}.
* Mods which allow dynamic world (un)registration should call this event so mods can let go of world handles when a world is removed.
*/
public static final Event<Unloaded> UNLOADED = Event.of(unloadeds -> (server, world) -> {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package band.kessoku.lib.events.lifecycle.api.client;

import band.kessoku.lib.event.api.Event;

import net.minecraft.client.MinecraftClient;

public class ClientLifecycleEvent {

/**
* Called when Minecraft has started and it's client about to tick for the first time.
*
* <p>This occurs while the splash screen is displayed.
*/
public static final Event<Client.Started> STARTED = Event.of(starteds -> client -> {
for (Client.Started started : starteds) {
started.onClientStarted(client);
}
});

/**
* Called when Minecraft's client begins to stop.
* This is caused by quitting while in game, or closing the game window.
*
* <p>This will be called before the integrated server is stopped if it is running.
*/
public static final Event<Client.Stopping> STOPPING = Event.of(stoppings -> client -> {
for (Client.Stopping stopping : stoppings) {
stopping.onClientStopping(client);
}
});

public interface Client {
@FunctionalInterface
interface Started {
void onClientStarted(MinecraftClient client);
}

@FunctionalInterface
interface Stopping {
void onClientStopping(MinecraftClient client);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package band.kessoku.lib.events.lifecycle.api.client;

import band.kessoku.lib.event.api.Event;

import net.minecraft.client.MinecraftClient;
import net.minecraft.client.world.ClientWorld;

public class ClientTickEvent {

/**
* Called at the start of the client tick.
*/
public static final Event<ClientTick.Start> START_CLIENT_TICK = Event.of(starts -> client -> {
for (ClientTick.Start start : starts) {
start.onStartTick(client);
}
});

/**
* Called at the end of the client tick.
*/
public static final Event<ClientTick.End> END_CLIENT_TICK = Event.of(ends -> client -> {
for (ClientTick.End end : ends) {
end.onEndTick(client);
}
});

/**
* Called at the start of a ClientWorld's tick.
*/
public static final Event<WorldTick.Start> START_WORLD_TICK = Event.of(starts -> world -> {
for (WorldTick.Start start : starts) {
start.onStartTick(world);
}
});

/**
* Called at the end of a ClientWorld's tick.
*
* <p>End of world tick may be used to start async computations for the next tick.
*/
public static final Event<WorldTick.End> END_WORLD_TICK = Event.of(ends -> world -> {
for (WorldTick.End end : ends) {
end.onEndTick(world);
}
});

public interface ClientTick {
@FunctionalInterface
interface Start {
void onStartTick(MinecraftClient client);
}

@FunctionalInterface
interface End {
void onEndTick(MinecraftClient client);
}
}

public interface WorldTick {
@FunctionalInterface
interface Start {
void onStartTick(ClientWorld world);
}

@FunctionalInterface
interface End {
void onEndTick(ClientWorld world);
}
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package band.kessoku.lib.events.lifecycle.impl;

import band.kessoku.lib.events.lifecycle.api.ServerBlockEntityEvent;
import band.kessoku.lib.events.lifecycle.api.ServerChunkEvent;
import band.kessoku.lib.events.lifecycle.api.ServerEntityEvent;
import band.kessoku.lib.events.lifecycle.api.ServerWorldEvent;

import net.minecraft.block.entity.BlockEntity;
import net.minecraft.entity.Entity;
import net.minecraft.world.chunk.WorldChunk;

public class KessokuLifecycleEventsImpl {
public static void clientInit() {

}

public static void init() {
// Part of impl for block entity events
ServerChunkEvent.LOADED.register((world, chunk) -> {
((LoadedChunksCache) world).kessoku$markLoaded(chunk);
});

ServerChunkEvent.UNLOADED.register((world, chunk) -> {
((LoadedChunksCache) world).kessoku$markUnloaded(chunk);
});

// Fire block entity unload events.
// This handles the edge case where going through a portal will cause block entities to unload without warning.
ServerChunkEvent.UNLOADED.register((world, chunk) -> {
for (BlockEntity blockEntity : chunk.getBlockEntities().values()) {
ServerBlockEntityEvent.UNLOADED.invoker().onUnloaded(blockEntity, world);
}
});

// We use the world unload event so worlds that are dynamically hot(un)loaded get (block) entity unload events fired when shut down.
ServerWorldEvent.UNLOADED.register((server, world) -> {
for (WorldChunk chunk : ((LoadedChunksCache) world).kessoku$getLoadedChunks()) {
for (BlockEntity blockEntity : chunk.getBlockEntities().values()) {
ServerBlockEntityEvent.UNLOADED.invoker().onUnloaded(blockEntity, world);
}
}

for (Entity entity : world.iterateEntities()) {
ServerEntityEvent.UNLOADED.invoker().onUnloaded(entity, world);
}
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package band.kessoku.lib.events.lifecycle.impl;

import net.minecraft.world.chunk.WorldChunk;

import java.util.Set;

/**
* A simple marker interface which holds references to chunks which block entities may be loaded or unloaded from.
*/
public interface LoadedChunksCache {
Set<WorldChunk> kessoku$getLoadedChunks();

/**
* Marks a chunk as loaded in a world.
*/
void kessoku$markLoaded(WorldChunk chunk);

/**
* Marks a chunk as unloaded in a world.
*/
void kessoku$markUnloaded(WorldChunk chunk);
}
Loading

0 comments on commit 3c462a3

Please sign in to comment.