mirror of
https://github.com/architectury/architectury-api.git
synced 2026-03-28 03:56:59 -05:00
More events and hooks
This commit is contained in:
@@ -33,7 +33,7 @@ public final class ArchitecturyPopulator {
|
||||
if (Modifier.isStatic(field.getModifiers())) {
|
||||
FieldUtils.removeFinalModifier(field);
|
||||
field.setAccessible(true);
|
||||
String type = field.getType().toString().replace("$", "");
|
||||
String type = field.getType().getName().replace("$", "");
|
||||
Class<?> newClass = Class.forName(type.substring(0, type.lastIndexOf('.')) + "." + Architectury.getModLoader() + "." + type.substring(type.lastIndexOf('.') + 1));
|
||||
field.set(null, newClass.getConstructor().newInstance());
|
||||
}
|
||||
@@ -44,7 +44,7 @@ public final class ArchitecturyPopulator {
|
||||
if (!Modifier.isStatic(field.getModifiers())) {
|
||||
FieldUtils.removeFinalModifier(field);
|
||||
field.setAccessible(true);
|
||||
String type = field.getType().toString().replace("$", "");
|
||||
String type = field.getType().getName().replace("$", "");
|
||||
Class<?> newClass = Class.forName(type.substring(0, type.lastIndexOf('.')) + "." + Architectury.getModLoader() + "." + type.substring(type.lastIndexOf('.') + 1));
|
||||
field.set(o, newClass.getConstructor().newInstance());
|
||||
}
|
||||
|
||||
@@ -17,11 +17,6 @@
|
||||
package me.shedaniel.architectury.event;
|
||||
|
||||
import com.google.common.reflect.AbstractInvocationHandler;
|
||||
import me.shedaniel.architectury.ArchitecturyPopulator;
|
||||
import me.shedaniel.architectury.Populatable;
|
||||
import me.shedaniel.architectury.platform.Platform;
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
import net.jodah.typetools.TypeResolver;
|
||||
import net.minecraft.world.InteractionResult;
|
||||
import net.minecraft.world.InteractionResultHolder;
|
||||
@@ -38,9 +33,6 @@ import java.util.function.Function;
|
||||
public final class EventFactory {
|
||||
private EventFactory() {}
|
||||
|
||||
@Populatable
|
||||
private static final Impl IMPL = null;
|
||||
|
||||
public static <T> Event<T> create(Function<T[], T> function) {
|
||||
Class<?>[] arguments = TypeResolver.resolveRawArguments(Function.class, function.getClass());
|
||||
return new EventImpl<>(arguments[1], function);
|
||||
@@ -177,23 +169,4 @@ public final class EventFactory {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public interface Impl {
|
||||
@Environment(EnvType.CLIENT)
|
||||
void registerClient();
|
||||
|
||||
void registerCommon();
|
||||
|
||||
@Environment(EnvType.SERVER)
|
||||
void registerServer();
|
||||
}
|
||||
|
||||
static {
|
||||
ArchitecturyPopulator.populate(EventFactory.class);
|
||||
if (Platform.getEnv() == EnvType.CLIENT)
|
||||
IMPL.registerClient();
|
||||
IMPL.registerCommon();
|
||||
if (Platform.getEnv() == EnvType.SERVER)
|
||||
IMPL.registerServer();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright 2020 shedaniel
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package me.shedaniel.architectury.event;
|
||||
|
||||
import me.shedaniel.architectury.ArchitecturyPopulator;
|
||||
import me.shedaniel.architectury.Populatable;
|
||||
import me.shedaniel.architectury.platform.Platform;
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
|
||||
public final class EventHandler {
|
||||
private EventHandler() {}
|
||||
|
||||
@Populatable
|
||||
private static final Impl IMPL = null;
|
||||
private static boolean initialized = false;
|
||||
|
||||
public static void init() {
|
||||
if (initialized) return;
|
||||
initialized = true;
|
||||
if (Platform.getEnv() == EnvType.CLIENT)
|
||||
IMPL.registerClient();
|
||||
IMPL.registerCommon();
|
||||
if (Platform.getEnv() == EnvType.SERVER)
|
||||
IMPL.registerServer();
|
||||
}
|
||||
|
||||
public interface Impl {
|
||||
@Environment(EnvType.CLIENT)
|
||||
void registerClient();
|
||||
|
||||
void registerCommon();
|
||||
|
||||
@Environment(EnvType.SERVER)
|
||||
void registerServer();
|
||||
}
|
||||
|
||||
static {
|
||||
ArchitecturyPopulator.populate(EventHandler.class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2020 shedaniel
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package me.shedaniel.architectury.event.events;
|
||||
|
||||
import me.shedaniel.architectury.event.Event;
|
||||
import me.shedaniel.architectury.event.EventFactory;
|
||||
import net.minecraft.world.InteractionResult;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.level.Explosion;
|
||||
import net.minecraft.world.level.Level;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface ExplosionEvent {
|
||||
Event<Pre> PRE = EventFactory.createInteractionResult(Pre.class);
|
||||
Event<Detonate> DETONATE = EventFactory.createInteractionResult(Detonate.class);
|
||||
|
||||
interface Pre {
|
||||
InteractionResult explode(Level world, Explosion explosion);
|
||||
}
|
||||
|
||||
interface Detonate {
|
||||
void explode(Level world, Explosion explosion, List<Entity> affectedEntities);
|
||||
}
|
||||
}
|
||||
@@ -44,6 +44,8 @@ public interface GuiEvent {
|
||||
* Invoked after Screen#init, equivalent to forge's {@code GuiScreenEvent.InitGuiEvent.Post}.
|
||||
*/
|
||||
Event<ScreenInitPost> INIT_POST = EventFactory.createLoop(ScreenInitPost.class);
|
||||
Event<ScreenRenderPre> RENDER_PRE = EventFactory.createInteractionResult(ScreenRenderPre.class);
|
||||
Event<ScreenRenderPost> RENDER_POST = EventFactory.createInteractionResult(ScreenRenderPost.class);
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
interface RenderHud {
|
||||
@@ -64,4 +66,14 @@ public interface GuiEvent {
|
||||
interface ScreenInitPost {
|
||||
void init(Screen screen, List<AbstractWidget> widgets, List<GuiEventListener> children);
|
||||
}
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
interface ScreenRenderPre {
|
||||
InteractionResult render(Screen screen, PoseStack matrices, int mouseX, int mouseY, float delta);
|
||||
}
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
interface ScreenRenderPost {
|
||||
void render(Screen screen, PoseStack matrices, int mouseX, int mouseY, float delta);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,9 +53,13 @@ public interface LifecycleEvent {
|
||||
*/
|
||||
Event<ServerState> SERVER_STOPPED = EventFactory.createLoop(ServerState.class);
|
||||
/**
|
||||
* Invoked after a world is loaded only on server, equivalent to forge's {@code WorldEvent.Load}.
|
||||
* Invoked after a world is loaded only on server, equivalent to forge's {@code WorldEvent.Load} and fabric's {@code ServerWorldEvents#LOAD}.
|
||||
*/
|
||||
Event<ServerWorldState> SERVER_WORLD_LOAD = EventFactory.createLoop(ServerWorldState.class);
|
||||
/**
|
||||
* Invoked after a world is unloaded, equivalent to forge's {@code WorldEvent.Unload} and fabric's {@code ServerWorldEvents#UNLOAD}.
|
||||
*/
|
||||
Event<ServerWorldState> SERVER_WORLD_UNLOAD = EventFactory.createLoop(ServerWorldState.class);
|
||||
/**
|
||||
* Invoked during a world is saved, equivalent to forge's {@code WorldEvent.Save}.
|
||||
*/
|
||||
|
||||
@@ -20,6 +20,7 @@ import me.shedaniel.architectury.event.Event;
|
||||
import me.shedaniel.architectury.event.EventFactory;
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
import net.minecraft.advancements.Advancement;
|
||||
import net.minecraft.client.player.LocalPlayer;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
|
||||
@@ -30,6 +31,8 @@ public interface PlayerEvent {
|
||||
@Environment(EnvType.CLIENT) Event<ClientPlayerJoin> CLIENT_PLAYER_JOIN = EventFactory.createLoop(ClientPlayerJoin.class);
|
||||
@Environment(EnvType.CLIENT) Event<ClientPlayerQuit> CLIENT_PLAYER_QUIT = EventFactory.createLoop(ClientPlayerQuit.class);
|
||||
@Environment(EnvType.CLIENT) Event<ClientPlayerRespawn> CLIENT_PLAYER_RESPAWN = EventFactory.createLoop(ClientPlayerRespawn.class);
|
||||
Event<PlayerAdvancement> PLAYER_ADVANCEMENT = EventFactory.createLoop(PlayerAdvancement.class);
|
||||
Event<PlayerClone> PLAYER_CLONE = EventFactory.createLoop(PlayerClone.class);
|
||||
|
||||
interface PlayerJoin {
|
||||
void join(ServerPlayer player);
|
||||
@@ -43,6 +46,14 @@ public interface PlayerEvent {
|
||||
void respawn(ServerPlayer newPlayer, boolean conqueredEnd);
|
||||
}
|
||||
|
||||
interface PlayerClone {
|
||||
void clone(ServerPlayer oldPlayer, ServerPlayer newPlayer, boolean wonGame);
|
||||
}
|
||||
|
||||
interface PlayerAdvancement {
|
||||
void award(ServerPlayer player, Advancement advancement);
|
||||
}
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
interface ClientPlayerJoin {
|
||||
void join(LocalPlayer player);
|
||||
|
||||
@@ -16,12 +16,16 @@
|
||||
|
||||
package me.shedaniel.architectury.registry;
|
||||
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public interface Registry<T> {
|
||||
public interface Registry<T> extends Iterable<T> {
|
||||
Supplier<T> delegate(ResourceLocation id);
|
||||
|
||||
Supplier<T> register(ResourceLocation id, Supplier<T> supplier);
|
||||
@@ -29,6 +33,18 @@ public interface Registry<T> {
|
||||
@Nullable
|
||||
ResourceLocation getId(T obj);
|
||||
|
||||
Optional<ResourceKey<T>> getKey(T obj);
|
||||
|
||||
@Nullable
|
||||
T get(ResourceLocation id);
|
||||
|
||||
boolean contains(ResourceLocation id);
|
||||
|
||||
boolean containsValue(T obj);
|
||||
|
||||
Set<ResourceLocation> getIds();
|
||||
|
||||
Set<Map.Entry<ResourceKey<T>, T>> entrySet();
|
||||
|
||||
ResourceKey<? extends net.minecraft.core.Registry<T>> key();
|
||||
}
|
||||
|
||||
@@ -17,6 +17,8 @@ dependencies {
|
||||
modCompile("net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}")
|
||||
modCompile("net.fabricmc.fabric-api:fabric-api:${rootProject.fabric_api_version}")
|
||||
modCompileOnly("io.github.prospector:modmenu:${rootProject.mod_menu_version}")
|
||||
implementation "net.jodah:typetools:0.6.2"
|
||||
shadow "net.jodah:typetools:0.6.2"
|
||||
|
||||
compile(project(":common")) {
|
||||
transitive = false
|
||||
@@ -34,6 +36,7 @@ processResources {
|
||||
}
|
||||
|
||||
shadowJar {
|
||||
relocate "net.jodah.typetools", "me.shedaniel.architectury.shadowed.impl.net.jodah.typetools"
|
||||
configurations = [project.configurations.shadow]
|
||||
classifier "shadow"
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
package me.shedaniel.architectury.event.fabric;
|
||||
|
||||
import me.shedaniel.architectury.event.EventFactory;
|
||||
import me.shedaniel.architectury.event.EventHandler;
|
||||
import me.shedaniel.architectury.event.events.*;
|
||||
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents;
|
||||
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
|
||||
@@ -25,9 +25,10 @@ import net.fabricmc.fabric.api.client.rendering.v1.HudRenderCallback;
|
||||
import net.fabricmc.fabric.api.command.v1.CommandRegistrationCallback;
|
||||
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
|
||||
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents;
|
||||
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerWorldEvents;
|
||||
import net.minecraft.commands.Commands;
|
||||
|
||||
public class EventFactoryImpl implements EventFactory.Impl {
|
||||
public class EventHandlerImpl implements EventHandler.Impl {
|
||||
@Override
|
||||
public void registerClient() {
|
||||
ClientLifecycleEvents.CLIENT_STARTED.register(LifecycleEvent.CLIENT_STARTED.invoker()::stateChanged);
|
||||
@@ -54,6 +55,9 @@ public class EventFactoryImpl implements EventFactory.Impl {
|
||||
ServerTickEvents.START_WORLD_TICK.register(TickEvent.SERVER_WORLD_PRE.invoker()::tick);
|
||||
ServerTickEvents.END_WORLD_TICK.register(TickEvent.SERVER_WORLD_POST.invoker()::tick);
|
||||
|
||||
ServerWorldEvents.LOAD.register((server, world) -> LifecycleEvent.SERVER_WORLD_LOAD.invoker().act(world));
|
||||
ServerWorldEvents.UNLOAD.register((server, world) -> LifecycleEvent.SERVER_WORLD_UNLOAD.invoker().act(world));
|
||||
|
||||
CommandRegistrationCallback.EVENT.register((commandDispatcher, b) -> CommandRegistrationEvent.EVENT.invoker().register(commandDispatcher, b ? Commands.CommandSelection.DEDICATED : Commands.CommandSelection.INTEGRATED));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2020 shedaniel
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package me.shedaniel.architectury.mixin.fabric;
|
||||
|
||||
import me.shedaniel.architectury.event.events.ExplosionEvent;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.InteractionResult;
|
||||
import net.minecraft.world.damagesource.DamageSource;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.level.Explosion;
|
||||
import net.minecraft.world.level.ExplosionDamageCalculator;
|
||||
import net.minecraft.world.level.Level;
|
||||
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.CallbackInfoReturnable;
|
||||
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
|
||||
|
||||
@Mixin(value = {Level.class, ServerLevel.class})
|
||||
public class ExplosionPreInvoker {
|
||||
@Inject(method = "explode(Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/damagesource/DamageSource;Lnet/minecraft/world/level/ExplosionDamageCalculator;DDDFZLnet/minecraft/world/level/Explosion$BlockInteraction;)Lnet/minecraft/world/level/Explosion;",
|
||||
at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Explosion;explode()V"), cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD)
|
||||
private void explodePre(Entity entity, DamageSource damageSource, ExplosionDamageCalculator explosionDamageCalculator, double d, double e, double f, float g, boolean bl, Explosion.BlockInteraction blockInteraction, CallbackInfoReturnable<Explosion> cir, Explosion explosion) {
|
||||
if (ExplosionEvent.PRE.invoker().explode((Level)(Object) this, explosion) == InteractionResult.FAIL) {
|
||||
cir.setReturnValue(explosion);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -32,7 +32,7 @@ import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
@Mixin(Commands.class)
|
||||
public class MixinCommands {
|
||||
@Redirect(method = "performCommand",
|
||||
at = @At(value = "INVOKE", target = "Lcom/mojang/brigadier/CommandDispatcher;execute(Lcom/mojang/brigadier/StringReader;Ljava/lang/Object;)I"))
|
||||
at = @At(value = "INVOKE", target = "Lcom/mojang/brigadier/CommandDispatcher;execute(Lcom/mojang/brigadier/StringReader;Ljava/lang/Object;)I", remap = false))
|
||||
private int performCommand(CommandDispatcher<CommandSourceStack> dispatcher, StringReader input, Object source) throws CommandSyntaxException {
|
||||
CommandSourceStack stack = (CommandSourceStack) source;
|
||||
ParseResults<CommandSourceStack> parse = dispatcher.parse(input, stack);
|
||||
|
||||
@@ -16,11 +16,10 @@
|
||||
|
||||
package me.shedaniel.architectury.mixin.fabric;
|
||||
|
||||
import me.shedaniel.architectury.event.events.LifecycleEvent;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.level.progress.ChunkProgressListener;
|
||||
import me.shedaniel.architectury.event.events.ExplosionEvent;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.level.Explosion;
|
||||
import net.minecraft.world.level.Level;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
@@ -28,17 +27,17 @@ import org.spongepowered.asm.mixin.Shadow;
|
||||
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.LocalCapture;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
@Mixin(MinecraftServer.class)
|
||||
public class MixinMinecraftServer {
|
||||
@Shadow @Final private Map<ResourceKey<Level>, ServerLevel> levels;
|
||||
@Mixin(Explosion.class)
|
||||
public class MixinExplosion {
|
||||
@Shadow @Final private Level level;
|
||||
|
||||
@Inject(method = "createLevels", at = @At("RETURN"))
|
||||
private void createLevels(ChunkProgressListener chunkProgressListener, CallbackInfo ci) {
|
||||
for (ServerLevel level : levels.values()) {
|
||||
LifecycleEvent.SERVER_WORLD_LOAD.invoker().act(level);
|
||||
}
|
||||
@Inject(method = "explode", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/phys/Vec3;<init>(DDD)V", ordinal = 0), locals = LocalCapture.CAPTURE_FAILHARD)
|
||||
private void explodePost(CallbackInfo ci, Set<BlockPos> set, float q, int r, int s, int t, int u, int v, int w, List<Entity> list) {
|
||||
ExplosionEvent.DETONATE.invoker().explode(level, (Explosion) (Object) this, list);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2020 shedaniel
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package me.shedaniel.architectury.mixin.fabric;
|
||||
|
||||
import me.shedaniel.architectury.event.events.PlayerEvent;
|
||||
import net.minecraft.advancements.Advancement;
|
||||
import net.minecraft.server.PlayerAdvancements;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
@Mixin(PlayerAdvancements.class)
|
||||
public class MixinPlayerAdvancements {
|
||||
@Shadow private ServerPlayer player;
|
||||
|
||||
@Inject(method = "award",
|
||||
at = @At(value = "INVOKE", target = "Lnet/minecraft/advancements/AdvancementRewards;grant(Lnet/minecraft/server/level/ServerPlayer;)V",
|
||||
shift = At.Shift.AFTER))
|
||||
private void award(Advancement advancement, String string, CallbackInfoReturnable<Boolean> cir) {
|
||||
PlayerEvent.PLAYER_ADVANCEMENT.invoker().award(player, advancement);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2020 shedaniel
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package me.shedaniel.architectury.mixin.fabric;
|
||||
|
||||
import me.shedaniel.architectury.event.events.PlayerEvent;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
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;
|
||||
|
||||
@Mixin(ServerPlayer.class)
|
||||
public class MixinServerPlayer {
|
||||
@Inject(method = "restoreFrom", at = @At("RETURN"))
|
||||
private void restoreFrom(ServerPlayer serverPlayer, boolean bl, CallbackInfo ci) {
|
||||
PlayerEvent.PLAYER_CLONE.invoker().clone((ServerPlayer) (Object) this, serverPlayer, bl);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright 2020 shedaniel
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package me.shedaniel.architectury.mixin.fabric.client;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import me.shedaniel.architectury.event.events.GuiEvent;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.GameRenderer;
|
||||
import net.minecraft.world.InteractionResult;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
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.LocalCapture;
|
||||
|
||||
@Mixin(GameRenderer.class)
|
||||
public abstract class MixinGameRenderer {
|
||||
@Shadow @Final private Minecraft minecraft;
|
||||
|
||||
@Inject(method = "render(FJZ)V",
|
||||
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screens/Screen;render(Lcom/mojang/blaze3d/vertex/PoseStack;IIF)V",
|
||||
ordinal = 0), locals = LocalCapture.CAPTURE_FAILEXCEPTION, cancellable = true)
|
||||
public void renderScreenPre(float tickDelta, long startTime, boolean tick, CallbackInfo ci, int mouseX, int mouseY, PoseStack matrices) {
|
||||
if (GuiEvent.RENDER_PRE.invoker().render(minecraft.screen, matrices, mouseX, mouseY, minecraft.getDeltaFrameTime()) == InteractionResult.FAIL) {
|
||||
ci.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "render(FJZ)V",
|
||||
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screens/Screen;render(Lcom/mojang/blaze3d/vertex/PoseStack;IIF)V",
|
||||
shift = At.Shift.AFTER, ordinal = 0), locals = LocalCapture.CAPTURE_FAILEXCEPTION)
|
||||
public void renderScreenPost(float tickDelta, long startTime, boolean tick, CallbackInfo ci, int mouseX, int mouseY, PoseStack matrices) {
|
||||
GuiEvent.RENDER_POST.invoker().render(minecraft.screen, matrices, mouseX, mouseY, minecraft.getDeltaFrameTime());
|
||||
}
|
||||
}
|
||||
@@ -21,8 +21,13 @@ import me.shedaniel.architectury.registry.Registry;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.util.LazyLoadedValue;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class RegistriesImpl implements Registries.Impl {
|
||||
@@ -78,10 +83,46 @@ public class RegistriesImpl implements Registries.Impl {
|
||||
public @Nullable ResourceLocation getId(T obj) {
|
||||
return delegate.getKey(obj);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Optional<ResourceKey<T>> getKey(T obj) {
|
||||
return delegate.getResourceKey(obj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable T get(ResourceLocation id) {
|
||||
return delegate.get(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(ResourceLocation id) {
|
||||
return delegate.containsKey(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsValue(T obj) {
|
||||
return delegate.getResourceKey(obj).isPresent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<ResourceLocation> getIds() {
|
||||
return delegate.keySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Map.Entry<ResourceKey<T>, T>> entrySet() {
|
||||
return delegate.entrySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceKey<? extends net.minecraft.core.Registry<T>> key() {
|
||||
return delegate.key();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Iterator<T> iterator() {
|
||||
return delegate.iterator();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package me.shedaniel.architectury.utils.fabric;
|
||||
|
||||
import me.shedaniel.architectury.event.EventHandler;
|
||||
import me.shedaniel.architectury.event.events.LifecycleEvent;
|
||||
import me.shedaniel.architectury.platform.Platform;
|
||||
import me.shedaniel.architectury.utils.GameInstance;
|
||||
@@ -38,6 +39,7 @@ public class GameInstanceImpl implements GameInstance.Impl {
|
||||
}
|
||||
|
||||
public static void init() {
|
||||
EventHandler.init();
|
||||
LifecycleEvent.SERVER_STARTING.register(server -> GameInstanceImpl.server = server);
|
||||
LifecycleEvent.SERVER_STOPPED.register(server -> GameInstanceImpl.server = null);
|
||||
}
|
||||
|
||||
@@ -7,11 +7,13 @@
|
||||
"client.MixinClientLevel",
|
||||
"client.MixinClientPacketListener",
|
||||
"client.MixinDebugScreenOverlay",
|
||||
"client.MixinGameRenderer",
|
||||
"client.MixinMinecraft",
|
||||
"client.MixinScreen"
|
||||
],
|
||||
"mixins": [
|
||||
"LivingDeathInvoker", "MixinCommands", "MixinMinecraftServer", "MixinPlayer", "MixinPlayerList", "MixinServerGamePacketListenerImpl", "MixinServerLevel"
|
||||
"ExplosionPreInvoker", "LivingDeathInvoker", "MixinCommands", "MixinExplosion", "MixinPlayer", "MixinPlayerAdvancements", "MixinPlayerList",
|
||||
"MixinServerGamePacketListenerImpl", "MixinServerLevel", "MixinServerPlayer"
|
||||
],
|
||||
"injectors": {
|
||||
"defaultRequire": 1
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
package me.shedaniel.architectury.event.forge;
|
||||
|
||||
import me.shedaniel.architectury.event.EventFactory;
|
||||
import me.shedaniel.architectury.event.EventHandler;
|
||||
import me.shedaniel.architectury.event.events.*;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.IGuiEventListener;
|
||||
@@ -35,10 +35,14 @@ import net.minecraftforge.event.RegisterCommandsEvent;
|
||||
import net.minecraftforge.event.ServerChatEvent;
|
||||
import net.minecraftforge.event.TickEvent.*;
|
||||
import net.minecraftforge.event.entity.living.LivingDeathEvent;
|
||||
import net.minecraftforge.event.entity.player.AdvancementEvent;
|
||||
import net.minecraftforge.event.entity.player.ItemTooltipEvent;
|
||||
import net.minecraftforge.event.entity.player.PlayerEvent.Clone;
|
||||
import net.minecraftforge.event.entity.player.PlayerEvent.PlayerLoggedInEvent;
|
||||
import net.minecraftforge.event.entity.player.PlayerEvent.PlayerLoggedOutEvent;
|
||||
import net.minecraftforge.event.entity.player.PlayerEvent.PlayerRespawnEvent;
|
||||
import net.minecraftforge.event.world.ExplosionEvent.Detonate;
|
||||
import net.minecraftforge.event.world.ExplosionEvent.Start;
|
||||
import net.minecraftforge.event.world.WorldEvent;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import net.minecraftforge.fml.LogicalSide;
|
||||
@@ -50,7 +54,7 @@ import net.minecraftforge.fml.server.ServerLifecycleHooks;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class EventFactoryImpl implements EventFactory.Impl {
|
||||
public class EventHandlerImpl implements EventHandler.Impl {
|
||||
@Override
|
||||
public void registerClient() {
|
||||
MinecraftForge.EVENT_BUS.register(Client.class);
|
||||
@@ -145,6 +149,18 @@ public class EventFactoryImpl implements EventFactory.Impl {
|
||||
LifecycleEvent.CLIENT_WORLD_LOAD.invoker().act(world);
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void event(GuiScreenEvent.DrawScreenEvent.Pre event) {
|
||||
if (GuiEvent.RENDER_PRE.invoker().render(event.getGui(), event.getMatrixStack(), event.getMouseX(), event.getMouseY(), event.getRenderPartialTicks()) == ActionResultType.FAIL) {
|
||||
event.setCanceled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void event(GuiScreenEvent.DrawScreenEvent.Post event) {
|
||||
GuiEvent.RENDER_POST.invoker().render(event.getGui(), event.getMatrixStack(), event.getMouseX(), event.getMouseY(), event.getRenderPartialTicks());
|
||||
}
|
||||
}
|
||||
|
||||
public static class Common {
|
||||
@@ -242,6 +258,14 @@ public class EventFactoryImpl implements EventFactory.Impl {
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void event(WorldEvent.Unload event) {
|
||||
if (event.getWorld() instanceof ServerWorld) {
|
||||
ServerWorld world = (ServerWorld) event.getWorld();
|
||||
LifecycleEvent.SERVER_WORLD_UNLOAD.invoker().act(world);
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void event(WorldEvent.Save event) {
|
||||
if (event.getWorld() instanceof ServerWorld) {
|
||||
@@ -256,6 +280,32 @@ public class EventFactoryImpl implements EventFactory.Impl {
|
||||
event.setCanceled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void event(AdvancementEvent event) {
|
||||
if (event.getPlayer() instanceof ServerPlayerEntity) {
|
||||
PlayerEvent.PLAYER_ADVANCEMENT.invoker().award((ServerPlayerEntity) event.getPlayer(), event.getAdvancement());
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void event(Clone event) {
|
||||
if (event.getOriginal() instanceof ServerPlayerEntity && event.getPlayer() instanceof ServerPlayerEntity) {
|
||||
PlayerEvent.PLAYER_CLONE.invoker().clone((ServerPlayerEntity) event.getOriginal(), (ServerPlayerEntity) event.getPlayer(), !event.isWasDeath());
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void event(Start event) {
|
||||
if (ExplosionEvent.PRE.invoker().explode(event.getWorld(), event.getExplosion()) == ActionResultType.FAIL) {
|
||||
event.setCanceled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void event(Detonate event) {
|
||||
ExplosionEvent.DETONATE.invoker().explode(event.getWorld(), event.getExplosion(), event.getAffectedEntities());
|
||||
}
|
||||
}
|
||||
|
||||
@OnlyIn(Dist.DEDICATED_SERVER)
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package me.shedaniel.architectury.me.shedaniel.architectury.hooks.forge;
|
||||
package me.shedaniel.architectury.hooks.forge;
|
||||
|
||||
import me.shedaniel.architectury.hooks.ScreenHooks;
|
||||
import net.minecraft.client.gui.IGuiEventListener;
|
||||
@@ -34,7 +34,10 @@ import net.minecraftforge.registries.RegistryManager;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class RegistriesImpl implements Registries.Impl {
|
||||
@@ -119,12 +122,47 @@ public class RegistriesImpl implements Registries.Impl {
|
||||
public ResourceLocation getId(T obj) {
|
||||
return delegate.getKey(obj);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Optional<RegistryKey<T>> getKey(T t) {
|
||||
return delegate.getResourceKey(t);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public T get(ResourceLocation id) {
|
||||
return delegate.get(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(ResourceLocation resourceLocation) {
|
||||
return delegate.containsKey(resourceLocation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsValue(T t) {
|
||||
return delegate.getResourceKey(t).isPresent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<ResourceLocation> getIds() {
|
||||
return delegate.keySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Map.Entry<RegistryKey<T>, T>> entrySet() {
|
||||
return delegate.entrySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public RegistryKey<? extends net.minecraft.util.registry.Registry<T>> key() {
|
||||
return delegate.key();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<T> iterator() {
|
||||
return delegate.iterator();
|
||||
}
|
||||
}
|
||||
|
||||
public static class ForgeBackedRegistryImpl<T extends IForgeRegistryEntry<T>> implements Registry<T> {
|
||||
@@ -154,11 +192,46 @@ public class RegistriesImpl implements Registries.Impl {
|
||||
public ResourceLocation getId(T obj) {
|
||||
return delegate.getKey(obj);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Optional<RegistryKey<T>> getKey(T t) {
|
||||
return Optional.ofNullable(getId(t)).map(id -> RegistryKey.create(key(), id));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public T get(ResourceLocation id) {
|
||||
return delegate.getValue(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(ResourceLocation resourceLocation) {
|
||||
return delegate.containsKey(resourceLocation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsValue(T t) {
|
||||
return delegate.containsValue(t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<ResourceLocation> getIds() {
|
||||
return delegate.getKeys();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Map.Entry<RegistryKey<T>, T>> entrySet() {
|
||||
return delegate.getEntries();
|
||||
}
|
||||
|
||||
@Override
|
||||
public RegistryKey<? extends net.minecraft.util.registry.Registry<T>> key() {
|
||||
return RegistryKey.createRegistryKey(delegate.getRegistryName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<T> iterator() {
|
||||
return delegate.iterator();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user