mirror of
https://github.com/architectury/architectury-api.git
synced 2026-03-30 05:05:19 -05:00
Merge remote-tracking branch 'architectury/1.16' into feature/gui-input
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
plugins {
|
||||
id "architect-plugin" version "1.2.33"
|
||||
id "architectury-plugin" version "1.3.41"
|
||||
id "forgified-fabric-loom" version "0.5.22" apply false
|
||||
id "org.cadixdev.licenser" version "0.5.0"
|
||||
id "com.jfrog.bintray" version "1.8.4"
|
||||
id "com.matthewprenger.cursegradle" version "1.4.0" apply false
|
||||
@@ -13,11 +14,15 @@ architectury {
|
||||
|
||||
subprojects {
|
||||
apply plugin: "forgified-fabric-loom"
|
||||
|
||||
dependencies {
|
||||
testCompile sourceSets.main.output
|
||||
}
|
||||
}
|
||||
|
||||
allprojects {
|
||||
apply plugin: "java"
|
||||
apply plugin: "architect-plugin"
|
||||
apply plugin: "architectury-plugin"
|
||||
apply plugin: "org.cadixdev.licenser"
|
||||
|
||||
archivesBaseName = rootProject.archives_base_name
|
||||
|
||||
@@ -20,8 +20,11 @@
|
||||
package me.shedaniel.architectury;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@ApiStatus.Internal
|
||||
@@ -37,16 +40,18 @@ public class Architectury {
|
||||
}
|
||||
|
||||
static {
|
||||
String loader = null;
|
||||
List<String> loader = new ArrayList<>();
|
||||
for (Map.Entry<String, String> entry : MOD_LOADERS.entrySet()) {
|
||||
try {
|
||||
Class.forName(entry.getKey(), false, Architectury.class.getClassLoader());
|
||||
loader = entry.getValue();
|
||||
loader.add(entry.getValue());
|
||||
break;
|
||||
} catch (ClassNotFoundException ignored) {}
|
||||
}
|
||||
if (loader == null)
|
||||
if (loader.isEmpty())
|
||||
throw new IllegalStateException("No detected mod loader!");
|
||||
MOD_LOADER = loader;
|
||||
if (loader.size() >= 2)
|
||||
LogManager.getLogger().error("Detected multiple mod loaders! Something is wrong on the classpath! " + String.join(", ", loader));
|
||||
MOD_LOADER = loader.get(0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ public interface PlayerEvent {
|
||||
}
|
||||
|
||||
interface CraftItem {
|
||||
void craft(Player player, ItemStack smelted, Container inventory);
|
||||
void craft(Player player, ItemStack constructed, Container inventory);
|
||||
}
|
||||
|
||||
interface SmeltItem {
|
||||
|
||||
@@ -27,7 +27,7 @@ import net.minecraft.world.item.ItemStack;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public final class CreativeTabs {
|
||||
public CreativeTabs() {}
|
||||
private CreativeTabs() {}
|
||||
|
||||
// I am sorry, fabric wants a resource location instead of the translation key for whatever reason
|
||||
@ExpectPlatform
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 shedaniel
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
package me.shedaniel.architectury.registry;
|
||||
|
||||
import me.shedaniel.architectury.ExpectPlatform;
|
||||
import net.minecraft.advancements.CriterionTrigger;
|
||||
|
||||
public final class CriteriaTriggersRegistry {
|
||||
private CriteriaTriggersRegistry() {}
|
||||
|
||||
/**
|
||||
* Invokes {@link net.minecraft.advancements.CriteriaTriggers#register(CriterionTrigger)}.
|
||||
*
|
||||
* @param trigger The trigger to register
|
||||
* @param <T> The type of trigger
|
||||
* @return The trigger registered
|
||||
*/
|
||||
@ExpectPlatform
|
||||
public static <T extends CriterionTrigger<?>> T register(T trigger) {
|
||||
throw new AssertionError();
|
||||
}
|
||||
}
|
||||
@@ -19,42 +19,65 @@
|
||||
|
||||
package me.shedaniel.architectury.registry;
|
||||
|
||||
import com.google.common.base.Objects;
|
||||
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.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class DeferredRegister<T> {
|
||||
@NotNull
|
||||
private final Supplier<Registries> registriesSupplier;
|
||||
@NotNull
|
||||
private final ResourceKey<net.minecraft.core.Registry<T>> key;
|
||||
private final List<Entry<T>> entries = new ArrayList<>();
|
||||
private boolean registered = false;
|
||||
@Nullable
|
||||
private String modId;
|
||||
|
||||
private DeferredRegister(Supplier<Registries> registriesSupplier, ResourceKey<net.minecraft.core.Registry<T>> key) {
|
||||
this.registriesSupplier = registriesSupplier;
|
||||
this.key = key;
|
||||
private DeferredRegister(@NotNull Supplier<Registries> registriesSupplier, @NotNull ResourceKey<net.minecraft.core.Registry<T>> key, @Nullable String modId) {
|
||||
this.registriesSupplier = Objects.requireNonNull(registriesSupplier);
|
||||
this.key = Objects.requireNonNull(key);
|
||||
this.modId = modId;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static <T> DeferredRegister<T> create(Registries registries, ResourceKey<net.minecraft.core.Registry<T>> key) {
|
||||
return new DeferredRegister<>(() -> registries, key);
|
||||
public static <T> DeferredRegister<T> create(@NotNull String modId, @NotNull ResourceKey<net.minecraft.core.Registry<T>> key) {
|
||||
LazyLoadedValue<Registries> value = new LazyLoadedValue<>(() -> Registries.get(modId));
|
||||
return new DeferredRegister<>(value::get, key, Objects.requireNonNull(modId));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static <T> DeferredRegister<T> create(Supplier<Registries> registries, ResourceKey<net.minecraft.core.Registry<T>> key) {
|
||||
return new DeferredRegister<>(registries, key);
|
||||
@Deprecated
|
||||
public static <T> DeferredRegister<T> create(@NotNull Registries registries, @NotNull ResourceKey<net.minecraft.core.Registry<T>> key) {
|
||||
return new DeferredRegister<>(() -> registries, key, null);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static <T> DeferredRegister<T> create(LazyLoadedValue<Registries> registries, ResourceKey<net.minecraft.core.Registry<T>> key) {
|
||||
@Deprecated
|
||||
public static <T> DeferredRegister<T> create(@NotNull Supplier<Registries> registries, @NotNull ResourceKey<net.minecraft.core.Registry<T>> key) {
|
||||
return new DeferredRegister<>(registries, key, null);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Deprecated
|
||||
public static <T> DeferredRegister<T> create(@NotNull LazyLoadedValue<Registries> registries, @NotNull ResourceKey<net.minecraft.core.Registry<T>> key) {
|
||||
return create(registries::get, key);
|
||||
}
|
||||
|
||||
public RegistrySupplier<T> register(String id, Supplier<T> supplier) {
|
||||
if (modId == null) {
|
||||
throw new NullPointerException("You must create the deferred register with a mod id to register entries without the namespace!");
|
||||
}
|
||||
|
||||
return register(new ResourceLocation(modId, id), supplier);
|
||||
}
|
||||
|
||||
public RegistrySupplier<T> register(ResourceLocation id, Supplier<T> supplier) {
|
||||
Entry<T> entry = new Entry<>(id, supplier);
|
||||
this.entries.add(entry);
|
||||
@@ -76,12 +99,12 @@ public class DeferredRegister<T> {
|
||||
}
|
||||
}
|
||||
|
||||
private class Entry<T> implements RegistrySupplier<T> {
|
||||
private class Entry<R> implements RegistrySupplier<R> {
|
||||
private final ResourceLocation id;
|
||||
private final Supplier<T> supplier;
|
||||
private RegistrySupplier<T> value;
|
||||
private final Supplier<R> supplier;
|
||||
private RegistrySupplier<R> value;
|
||||
|
||||
public Entry(ResourceLocation id, Supplier<T> supplier) {
|
||||
public Entry(ResourceLocation id, Supplier<R> supplier) {
|
||||
this.id = id;
|
||||
this.supplier = supplier;
|
||||
}
|
||||
@@ -102,7 +125,7 @@ public class DeferredRegister<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public T get() {
|
||||
public R get() {
|
||||
if (isPresent()) {
|
||||
return value.get();
|
||||
}
|
||||
@@ -111,7 +134,7 @@ public class DeferredRegister<T> {
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(getRegistryId(), getId());
|
||||
return com.google.common.base.Objects.hashCode(getRegistryId(), getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -34,6 +34,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
public final class Registries {
|
||||
private static final Map<String, Registries> REGISTRIES = new ConcurrentHashMap<>();
|
||||
private final RegistryProvider provider;
|
||||
private final String modId;
|
||||
|
||||
public static Registries get(String modId) {
|
||||
return REGISTRIES.computeIfAbsent(modId, Registries::new);
|
||||
@@ -41,6 +42,7 @@ public final class Registries {
|
||||
|
||||
private Registries(String modId) {
|
||||
this.provider = _get(modId);
|
||||
this.modId = modId;
|
||||
}
|
||||
|
||||
public <T> Registry<T> get(ResourceKey<net.minecraft.core.Registry<T>> key) {
|
||||
@@ -88,6 +90,10 @@ public final class Registries {
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
public String getModId() {
|
||||
return modId;
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public interface RegistryProvider {
|
||||
<T> Registry<T> get(ResourceKey<net.minecraft.core.Registry<T>> key);
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
package me.shedaniel.architectury.test;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
public class ConsoleMessageSink implements MessageSink {
|
||||
protected final Logger logger = LogManager.getLogger("Architectury Test");
|
||||
|
||||
@Override
|
||||
public void accept(String message) {
|
||||
logger.info(message);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package me.shedaniel.architectury.test;
|
||||
|
||||
public interface MessageSink {
|
||||
void accept(String message);
|
||||
|
||||
default void accept(String message, Object... args) {
|
||||
accept(String.format(message, args));
|
||||
}
|
||||
}
|
||||
211
common/src/test/java/me/shedaniel/architectury/test/TestMod.java
Normal file
211
common/src/test/java/me/shedaniel/architectury/test/TestMod.java
Normal file
@@ -0,0 +1,211 @@
|
||||
package me.shedaniel.architectury.test;
|
||||
|
||||
import me.shedaniel.architectury.event.events.*;
|
||||
import me.shedaniel.architectury.event.events.client.ClientChatEvent;
|
||||
import me.shedaniel.architectury.event.events.client.ClientLifecycleEvent;
|
||||
import me.shedaniel.architectury.event.events.client.ClientPlayerEvent;
|
||||
import me.shedaniel.architectury.hooks.ExplosionHooks;
|
||||
import me.shedaniel.architectury.platform.Platform;
|
||||
import me.shedaniel.architectury.test.client.ClientOverlayMessageSink;
|
||||
import me.shedaniel.architectury.utils.Env;
|
||||
import me.shedaniel.architectury.utils.EnvExecutor;
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
import net.minecraft.core.Position;
|
||||
import net.minecraft.core.Vec3i;
|
||||
import net.minecraft.network.chat.TranslatableComponent;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.InteractionResult;
|
||||
import net.minecraft.world.InteractionResultHolder;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.level.Level;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public class TestMod {
|
||||
public static final MessageSink SINK = EnvExecutor.getEnvSpecific(() -> ClientOverlayMessageSink::new, () -> ConsoleMessageSink::new);
|
||||
|
||||
public static void initialize() {
|
||||
debugEvents();
|
||||
if (Platform.getEnvironment() == Env.CLIENT)
|
||||
debugEventsClient();
|
||||
}
|
||||
|
||||
public static void debugEvents() {
|
||||
ChatEvent.SERVER.register((player, message, component) -> {
|
||||
SINK.accept("Server chat received: " + message);
|
||||
return InteractionResultHolder.pass(component);
|
||||
});
|
||||
CommandPerformEvent.EVENT.register(event -> {
|
||||
SINK.accept("Server command performed: " + event.getResults().getReader().getString());
|
||||
return InteractionResult.PASS;
|
||||
});
|
||||
CommandRegistrationEvent.EVENT.register((dispatcher, selection) -> {
|
||||
SINK.accept("Server commands registers");
|
||||
});
|
||||
EntityEvent.LIVING_DEATH.register((entity, source) -> {
|
||||
if (entity instanceof Player) {
|
||||
SINK.accept(entity.getScoreboardName() + " died to " + source.getMsgId() + logSide(entity.level));
|
||||
}
|
||||
return InteractionResult.PASS;
|
||||
});
|
||||
EntityEvent.LIVING_ATTACK.register((entity, source, amount) -> {
|
||||
if (source.getDirectEntity() instanceof Player) {
|
||||
SINK.accept(source.getDirectEntity().getScoreboardName() + " deals %.2f damage" + logSide(entity.level), amount);
|
||||
}
|
||||
return InteractionResult.PASS;
|
||||
});
|
||||
EntityEvent.ADD.register((entity, level) -> {
|
||||
if (entity instanceof Player) {
|
||||
SINK.accept(entity.getScoreboardName() + " was added to " + level.dimension().location().toString() + logSide(level));
|
||||
}
|
||||
return InteractionResult.PASS;
|
||||
});
|
||||
EntityEvent.PLACE_BLOCK.register((world, pos, state, placer) -> {
|
||||
SINK.accept(Optional.ofNullable(placer).map(Entity::getScoreboardName).orElse("null") + " places block at " + toShortString(pos) + logSide(world));
|
||||
return InteractionResult.PASS;
|
||||
});
|
||||
ExplosionEvent.DETONATE.register((world, explosion, affectedEntities) -> {
|
||||
SINK.accept(world.dimension().location() + " explodes at " + toShortString(ExplosionHooks.getPosition(explosion)) + logSide(world));
|
||||
});
|
||||
InteractionEvent.LEFT_CLICK_BLOCK.register((player, hand, pos, face) -> {
|
||||
SINK.accept(player.getScoreboardName() + " left clicks " + toShortString(pos) + logSide(player.level));
|
||||
return InteractionResult.PASS;
|
||||
});
|
||||
InteractionEvent.RIGHT_CLICK_BLOCK.register((player, hand, pos, face) -> {
|
||||
SINK.accept(player.getScoreboardName() + " right clicks " + toShortString(pos) + logSide(player.level));
|
||||
return InteractionResult.PASS;
|
||||
});
|
||||
InteractionEvent.RIGHT_CLICK_ITEM.register((player, hand) -> {
|
||||
SINK.accept(player.getScoreboardName() + " uses " + (hand == InteractionHand.MAIN_HAND ? "main hand" : "off hand") + logSide(player.level));
|
||||
return InteractionResultHolder.pass(player.getItemInHand(hand));
|
||||
});
|
||||
InteractionEvent.INTERACT_ENTITY.register((player, entity, hand) -> {
|
||||
SINK.accept(player.getScoreboardName() + " interacts with " + entity.getScoreboardName() + " using " + (hand == InteractionHand.MAIN_HAND ? "main hand" : "off hand") + logSide(player.level));
|
||||
return InteractionResult.PASS;
|
||||
});
|
||||
LifecycleEvent.SERVER_BEFORE_START.register(instance -> {
|
||||
SINK.accept("Server ready to start");
|
||||
});
|
||||
LifecycleEvent.SERVER_STARTING.register(instance -> {
|
||||
SINK.accept("Server starting");
|
||||
});
|
||||
LifecycleEvent.SERVER_STARTED.register(instance -> {
|
||||
SINK.accept("Server started");
|
||||
});
|
||||
LifecycleEvent.SERVER_STOPPING.register(instance -> {
|
||||
SINK.accept("Server stopping");
|
||||
});
|
||||
LifecycleEvent.SERVER_STOPPED.register(instance -> {
|
||||
SINK.accept("Server stopped");
|
||||
});
|
||||
LifecycleEvent.SERVER_WORLD_LOAD.register(instance -> {
|
||||
SINK.accept("Server world loaded: " + instance.dimension().location());
|
||||
});
|
||||
LifecycleEvent.SERVER_WORLD_UNLOAD.register(instance -> {
|
||||
SINK.accept("Server world unloaded: " + instance.dimension().location());
|
||||
});
|
||||
LifecycleEvent.SERVER_WORLD_SAVE.register(instance -> {
|
||||
SINK.accept("Server world saved: " + instance.dimension().location());
|
||||
});
|
||||
PlayerEvent.PLAYER_JOIN.register(player -> {
|
||||
SINK.accept(player.getScoreboardName() + " joined" + logSide(player.level));
|
||||
});
|
||||
PlayerEvent.PLAYER_QUIT.register(player -> {
|
||||
SINK.accept(player.getScoreboardName() + " quit" + logSide(player.level));
|
||||
});
|
||||
PlayerEvent.PLAYER_RESPAWN.register((player, conqueredEnd) -> {
|
||||
if (!conqueredEnd) {
|
||||
SINK.accept(player.getScoreboardName() + " respawns " + logSide(player.level));
|
||||
}
|
||||
});
|
||||
PlayerEvent.PLAYER_CLONE.register((oldPlayer, newPlayer, wonGame) -> {
|
||||
SINK.accept("Player cloned: " + newPlayer.getScoreboardName() + logSide(newPlayer.level));
|
||||
});
|
||||
PlayerEvent.PLAYER_ADVANCEMENT.register((player, advancement) -> {
|
||||
SINK.accept(player.getScoreboardName() + " was awarded with %s" + logSide(player.level), advancement.getChatComponent().getString());
|
||||
});
|
||||
PlayerEvent.CRAFT_ITEM.register((player, constructed, inventory) -> {
|
||||
SINK.accept(player.getScoreboardName() + " crafts " + new TranslatableComponent(constructed.getDescriptionId()).getString() + logSide(player.level));
|
||||
});
|
||||
PlayerEvent.SMELT_ITEM.register((player, smelted) -> {
|
||||
SINK.accept(player.getScoreboardName() + " smelts " + new TranslatableComponent(smelted.getDescriptionId()).getString() + logSide(player.level));
|
||||
});
|
||||
PlayerEvent.PICKUP_ITEM_POST.register((player, entity, stack) -> {
|
||||
SINK.accept(player.getScoreboardName() + " picks up " + new TranslatableComponent(stack.getDescriptionId()).getString() + logSide(player.level));
|
||||
});
|
||||
PlayerEvent.DROP_ITEM.register((player, entity) -> {
|
||||
SINK.accept(player.getScoreboardName() + " drops " + new TranslatableComponent(entity.getItem().getDescriptionId()).getString() + logSide(player.level));
|
||||
return InteractionResult.PASS;
|
||||
});
|
||||
PlayerEvent.BREAK_BLOCK.register((world, pos, state, player, xp) -> {
|
||||
SINK.accept(player.getScoreboardName() + " breaks " + toShortString(pos) + logSide(player.level));
|
||||
return InteractionResult.PASS;
|
||||
});
|
||||
PlayerEvent.OPEN_MENU.register((player, menu) -> {
|
||||
SINK.accept(player.getScoreboardName() + " opens " + toSimpleName(menu) + logSide(player.level));
|
||||
});
|
||||
PlayerEvent.CLOSE_MENU.register((player, menu) -> {
|
||||
SINK.accept(player.getScoreboardName() + " closes " + toSimpleName(menu) + logSide(player.level));
|
||||
});
|
||||
}
|
||||
|
||||
public static String toShortString(Vec3i pos) {
|
||||
return pos.getX() + ", " + pos.getY() + ", " + pos.getZ();
|
||||
}
|
||||
|
||||
public static String toShortString(Position pos) {
|
||||
return pos.x() + ", " + pos.y() + ", " + pos.z();
|
||||
}
|
||||
|
||||
public static String logSide(Level level) {
|
||||
if (level.isClientSide())
|
||||
return " (client)";
|
||||
return " (server)";
|
||||
}
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public static void debugEventsClient() {
|
||||
ClientChatEvent.CLIENT.register(message -> {
|
||||
SINK.accept("Client chat sent: " + message);
|
||||
return InteractionResultHolder.pass(message);
|
||||
});
|
||||
ClientChatEvent.CLIENT_RECEIVED.register((type, message, sender) -> {
|
||||
SINK.accept("Client chat received: " + message.getString());
|
||||
return InteractionResultHolder.pass(message);
|
||||
});
|
||||
ClientLifecycleEvent.CLIENT_WORLD_LOAD.register(world -> {
|
||||
SINK.accept("Client world loaded: " + world.dimension().location().toString());
|
||||
});
|
||||
ClientPlayerEvent.CLIENT_PLAYER_JOIN.register(player -> {
|
||||
SINK.accept(player.getScoreboardName() + " joined (client)");
|
||||
});
|
||||
ClientPlayerEvent.CLIENT_PLAYER_QUIT.register(player -> {
|
||||
SINK.accept(player.getScoreboardName() + " quit (client)");
|
||||
});
|
||||
ClientPlayerEvent.CLIENT_PLAYER_RESPAWN.register((oldPlayer, newPlayer) -> {
|
||||
SINK.accept(newPlayer.getScoreboardName() + " respawned (client)");
|
||||
});
|
||||
GuiEvent.INIT_PRE.register((screen, widgets, children) -> {
|
||||
SINK.accept(toSimpleName(screen) + " initializes");
|
||||
return InteractionResult.PASS;
|
||||
});
|
||||
InteractionEvent.CLIENT_LEFT_CLICK_AIR.register((player, hand) -> {
|
||||
SINK.accept(player.getScoreboardName() + " left clicks air" + logSide(player.level));
|
||||
});
|
||||
InteractionEvent.CLIENT_RIGHT_CLICK_AIR.register((player, hand) -> {
|
||||
SINK.accept(player.getScoreboardName() + " right clicks air" + logSide(player.level));
|
||||
});
|
||||
RecipeUpdateEvent.EVENT.register(recipeManager -> {
|
||||
SINK.accept("Client recipes received");
|
||||
});
|
||||
TextureStitchEvent.POST.register(atlas -> {
|
||||
SINK.accept("Client texture stitched: " + atlas.location());
|
||||
});
|
||||
}
|
||||
|
||||
private static String toSimpleName(Object o) {
|
||||
return o.getClass().getSimpleName() + "@" + Integer.toHexString(o.hashCode());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
package me.shedaniel.architectury.test.client;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import me.shedaniel.architectury.event.events.GuiEvent;
|
||||
import me.shedaniel.architectury.test.ConsoleMessageSink;
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
import net.minecraft.Util;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiComponent;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.TextComponent;
|
||||
import net.minecraft.util.Mth;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public class ClientOverlayMessageSink extends ConsoleMessageSink {
|
||||
private final List<Message> messages = Collections.synchronizedList(Lists.newArrayList());
|
||||
|
||||
public ClientOverlayMessageSink() {
|
||||
GuiEvent.RENDER_POST.register((screen, matrices, mouseX, mouseY, delta) -> render(matrices, delta));
|
||||
GuiEvent.RENDER_HUD.register((matrices, tickDelta) -> {
|
||||
if (Minecraft.getInstance().screen == null && !Minecraft.getInstance().options.renderDebug) {
|
||||
render(matrices, tickDelta);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(String message) {
|
||||
super.accept(message);
|
||||
messages.add(0, new Message(new TextComponent(message), Util.getMillis()));
|
||||
}
|
||||
|
||||
public void render(PoseStack matrices, float delta) {
|
||||
Minecraft minecraft = Minecraft.getInstance();
|
||||
long currentMills = Util.getMillis();
|
||||
int lineHeight = minecraft.font.lineHeight;
|
||||
|
||||
synchronized (messages) {
|
||||
Iterator<Message> messageIterator = messages.iterator();
|
||||
int y = 1;
|
||||
|
||||
RenderSystem.enableBlend();
|
||||
|
||||
while (messageIterator.hasNext()) {
|
||||
Message message = messageIterator.next();
|
||||
int timeExisted = (int) (currentMills - message.created);
|
||||
|
||||
if (timeExisted >= 5000) {
|
||||
messageIterator.remove();
|
||||
} else {
|
||||
int textWidth = minecraft.font.width(message.text);
|
||||
int alpha = (int) Mth.clamp((5000 - timeExisted) / 5000f * 400f + 8, 0, 255);
|
||||
GuiComponent.fill(matrices, 0, y - 1, 2 + textWidth + 1, y + lineHeight - 1, 0x505050 + ((alpha * 144 / 255) << 24));
|
||||
minecraft.font.draw(matrices, message.text, 1, y, 0xE0E0E0 + (alpha << 24));
|
||||
y += lineHeight;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RenderSystem.disableAlphaTest();
|
||||
RenderSystem.disableBlend();
|
||||
}
|
||||
|
||||
private static class Message {
|
||||
private final Component text;
|
||||
private final long created;
|
||||
|
||||
public Message(Component text, long created) {
|
||||
this.text = text;
|
||||
this.created = created;
|
||||
}
|
||||
}
|
||||
}
|
||||
17
common/src/test/resources/fabric.mod.json
Normal file
17
common/src/test/resources/fabric.mod.json
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"id": "architectury-test",
|
||||
"version": "${version}",
|
||||
"name": "Architectury Test",
|
||||
"description": "A intermediary api aimed to ease developing multiplatform mods.",
|
||||
"authors": [
|
||||
"shedaniel"
|
||||
],
|
||||
"license": "LGPL-3",
|
||||
"environment": "*",
|
||||
"entrypoints": {
|
||||
"main": [
|
||||
"me.shedaniel.architectury.test.TestMod::initialize"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -40,6 +40,8 @@ dependencies {
|
||||
shadow(project(path: ":common", configuration: "transformed")) {
|
||||
transitive = false
|
||||
}
|
||||
|
||||
testCompile project(":common").sourceSets.test.output
|
||||
}
|
||||
|
||||
processResources {
|
||||
|
||||
@@ -26,6 +26,7 @@ import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
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;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
@@ -35,9 +36,13 @@ public abstract class MixinItemEntity {
|
||||
@Shadow
|
||||
public abstract ItemStack getItem();
|
||||
|
||||
@Unique
|
||||
private ItemStack cache;
|
||||
|
||||
@Inject(method = "playerTouch",
|
||||
at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/ItemStack;getCount()I"), cancellable = true)
|
||||
private void prePickup(Player player, CallbackInfo ci) {
|
||||
cache = getItem().copy();
|
||||
InteractionResult canPickUp = PlayerEvent.PICKUP_ITEM_PRE.invoker().canPickup(player, (ItemEntity) (Object) this, getItem());
|
||||
if (canPickUp == InteractionResult.FAIL) {
|
||||
ci.cancel();
|
||||
@@ -47,6 +52,10 @@ public abstract class MixinItemEntity {
|
||||
@Inject(method = "playerTouch",
|
||||
at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;take(Lnet/minecraft/world/entity/Entity;I)V"))
|
||||
private void pickup(Player player, CallbackInfo ci) {
|
||||
PlayerEvent.PICKUP_ITEM_POST.invoker().pickup(player, (ItemEntity) (Object) this, getItem());
|
||||
if (cache != null) {
|
||||
PlayerEvent.PICKUP_ITEM_POST.invoker().pickup(player, (ItemEntity) (Object) this, cache);
|
||||
}
|
||||
|
||||
this.cache = null;
|
||||
}
|
||||
}
|
||||
@@ -48,7 +48,7 @@ public class MixinPlayer {
|
||||
|
||||
@Inject(method = "drop(Lnet/minecraft/world/item/ItemStack;ZZ)Lnet/minecraft/world/entity/item/ItemEntity;", at = @At("RETURN"), cancellable = true)
|
||||
private void drop(ItemStack itemStack, boolean bl, boolean bl2, CallbackInfoReturnable<ItemEntity> cir) {
|
||||
if (PlayerEvent.DROP_ITEM.invoker().drop((Player) (Object) this, cir.getReturnValue()) == InteractionResult.FAIL) {
|
||||
if (cir.getReturnValue() != null && PlayerEvent.DROP_ITEM.invoker().drop((Player) (Object) this, cir.getReturnValue()) == InteractionResult.FAIL) {
|
||||
cir.setReturnValue(null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,7 +44,9 @@ public class MixinMinecraft {
|
||||
@Inject(method = "clearLevel(Lnet/minecraft/client/gui/screens/Screen;)V",
|
||||
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/chat/NarratorChatListener;clear()V"))
|
||||
private void handleLogin(Screen screen, CallbackInfo ci) {
|
||||
ClientPlayerEvent.CLIENT_PLAYER_QUIT.invoker().quit(player);
|
||||
if (player != null) {
|
||||
ClientPlayerEvent.CLIENT_PLAYER_QUIT.invoker().quit(player);
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "startUseItem", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/ItemStack;isEmpty()Z", ordinal = 1),
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 shedaniel
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
package me.shedaniel.architectury.registry.fabric;
|
||||
|
||||
import net.minecraft.advancements.CriteriaTriggers;
|
||||
import net.minecraft.advancements.CriterionTrigger;
|
||||
|
||||
public class CriteriaTriggersRegistryImpl {
|
||||
public static <T extends CriterionTrigger<?>> T register(T trigger) {
|
||||
return CriteriaTriggers.register(trigger);
|
||||
}
|
||||
}
|
||||
@@ -51,4 +51,5 @@ accessible method net/minecraft/world/entity/Entity getEncodeId ()Ljava/lang/Str
|
||||
accessible field net/minecraft/server/packs/repository/PackRepository sources Ljava/util/Set;
|
||||
mutable field net/minecraft/server/packs/repository/PackRepository sources Ljava/util/Set;
|
||||
accessible field net/minecraft/world/item/DyeColor textureDiffuseColor I
|
||||
accessible method net/minecraft/world/entity/player/Player closeContainer ()V
|
||||
accessible method net/minecraft/world/entity/player/Player closeContainer ()V
|
||||
accessible method net/minecraft/advancements/CriteriaTriggers register (Lnet/minecraft/advancements/CriterionTrigger;)Lnet/minecraft/advancements/CriterionTrigger;
|
||||
@@ -91,8 +91,10 @@ public class EventHandlerImplClient {
|
||||
|
||||
@SubscribeEvent
|
||||
public static void event(RenderGameOverlayEvent.Text event) {
|
||||
GuiEvent.DEBUG_TEXT_LEFT.invoker().gatherText(event.getLeft());
|
||||
GuiEvent.DEBUG_TEXT_RIGHT.invoker().gatherText(event.getRight());
|
||||
if (Minecraft.getInstance().options.renderDebug) {
|
||||
GuiEvent.DEBUG_TEXT_LEFT.invoker().gatherText(event.getLeft());
|
||||
GuiEvent.DEBUG_TEXT_RIGHT.invoker().gatherText(event.getRight());
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 shedaniel
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
package me.shedaniel.architectury.registry.forge;
|
||||
|
||||
import net.minecraft.advancements.CriteriaTriggers;
|
||||
import net.minecraft.advancements.CriterionTrigger;
|
||||
|
||||
public class CriteriaTriggersRegistryImpl {
|
||||
public static <T extends CriterionTrigger<?>> T register(T trigger) {
|
||||
return CriteriaTriggers.register(trigger);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user