Port for 1.21.9

This commit is contained in:
shedaniel
2025-10-02 18:09:01 +08:00
parent 97ceb68560
commit bc6c57c33a
102 changed files with 1408 additions and 1856 deletions

View File

@@ -1,4 +1,4 @@
name: Build PR snapshot (1.21.6)
name: Build PR snapshot (1.21.9)
on:
pull_request:
@@ -7,7 +7,7 @@ on:
- '**.properties'
- '**/src/**'
branches:
- "1.21.7"
- "1.21.9"
types: [ opened, synchronize, reopened ]
jobs:
validate-gradle:

View File

@@ -1,4 +1,4 @@
name: Build and Release (1.21.6)
name: Build and Release (1.21.9)
on:
push:
@@ -8,7 +8,7 @@ on:
- '**/src/**'
- '.github/**'
branches:
- "1.21.7"
- "1.21.9"
workflow_dispatch:
inputs:
norelease:

View File

@@ -8,7 +8,7 @@ buildscript {
plugins {
id "architectury-plugin" version "3.4-SNAPSHOT"
id "dev.architectury.loom" version "1.10-SNAPSHOT" apply false
id "dev.architectury.loom" version "1.11-SNAPSHOT" apply false
id "org.cadixdev.licenser" version "0.6.1"
id "me.shedaniel.unified-publishing" version "0.1.+" apply false
id "maven-publish"

View File

@@ -1,93 +0,0 @@
/*
* This file is part of architectury.
* Copyright (C) 2020, 2021, 2022 architectury
*
* 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 dev.architectury.core.item;
import dev.architectury.registry.registries.RegistrySupplier;
import net.minecraft.core.Direction;
import net.minecraft.core.HolderLookup;
import net.minecraft.core.dispenser.BlockSource;
import net.minecraft.core.dispenser.DefaultDispenseItemBehavior;
import net.minecraft.core.dispenser.DispenseItemBehavior;
import net.minecraft.world.entity.EntitySpawnReason;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.Mob;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.SpawnEggItem;
import net.minecraft.world.level.block.DispenserBlock;
import net.minecraft.world.level.gameevent.GameEvent;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.jetbrains.annotations.Nullable;
import java.util.Objects;
public class ArchitecturySpawnEggItem extends SpawnEggItem {
private static final Logger LOGGER = LogManager.getLogger(ArchitecturySpawnEggItem.class);
private final RegistrySupplier<? extends EntityType<? extends Mob>> entityType;
protected static DispenseItemBehavior createDispenseItemBehavior() {
return new DefaultDispenseItemBehavior() {
@Override
public ItemStack execute(BlockSource source, ItemStack stack) {
Direction direction = source.state().getValue(DispenserBlock.FACING);
EntityType<?> entityType = ((SpawnEggItem) stack.getItem()).getType(source.level().registryAccess(), stack);
try {
entityType.spawn(source.level(), stack, null, source.pos().relative(direction), EntitySpawnReason.DISPENSER, direction != Direction.UP, false);
} catch (Exception var6) {
LOGGER.error("Error while dispensing spawn egg from dispenser at {}", source.pos(), var6);
return ItemStack.EMPTY;
}
stack.shrink(1);
source.level().gameEvent(null, GameEvent.ENTITY_PLACE, source.pos());
return stack;
}
};
}
public ArchitecturySpawnEggItem(RegistrySupplier<? extends EntityType<? extends Mob>> entityType, Properties properties) {
this(entityType, properties, createDispenseItemBehavior());
}
public ArchitecturySpawnEggItem(RegistrySupplier<? extends EntityType<? extends Mob>> entityType, Properties properties,
@Nullable DispenseItemBehavior dispenseItemBehavior) {
super(null, properties);
this.entityType = Objects.requireNonNull(entityType, "entityType");
SpawnEggItem.BY_ID.remove(null);
entityType.listen(type -> {
LOGGER.debug("Registering spawn egg {} for {}", toString(),
Objects.toString(type.arch$registryName()));
SpawnEggItem.BY_ID.put(type, this);
this.defaultType = type;
if (dispenseItemBehavior != null) {
DispenserBlock.registerBehavior(this, dispenseItemBehavior);
}
});
}
@Override
public EntityType<?> getType(HolderLookup.Provider provider, ItemStack itemStack) {
EntityType<?> type = super.getType(provider, itemStack);
return type == null ? entityType.get() : type;
}
}

View File

@@ -22,8 +22,6 @@ package dev.architectury.event;
import dev.architectury.injectables.annotations.ExpectPlatform;
import dev.architectury.platform.Platform;
import dev.architectury.utils.Env;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
public final class EventHandler {
private EventHandler() {
@@ -42,7 +40,6 @@ public final class EventHandler {
}
@ExpectPlatform
@Environment(EnvType.CLIENT)
private static void registerClient() {
throw new AssertionError();
}
@@ -53,7 +50,6 @@ public final class EventHandler {
}
@ExpectPlatform
@Environment(EnvType.SERVER)
private static void registerServer() {
throw new AssertionError();
}

View File

@@ -23,13 +23,10 @@ import dev.architectury.event.CompoundEventResult;
import dev.architectury.event.Event;
import dev.architectury.event.EventFactory;
import dev.architectury.event.EventResult;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.network.chat.ChatType;
import net.minecraft.network.chat.Component;
import org.jetbrains.annotations.Nullable;
@Environment(EnvType.CLIENT)
public interface ClientChatEvent {
/**
* @see Send#send(String, Component)
@@ -40,7 +37,6 @@ public interface ClientChatEvent {
*/
Event<Received> RECEIVED = EventFactory.createCompoundEventResult();
@Environment(EnvType.CLIENT)
interface Send {
/**
* Event to cancel clients sending the chat message.
@@ -54,7 +50,6 @@ public interface ClientChatEvent {
EventResult send(String message, @Nullable Component component);
}
@Environment(EnvType.CLIENT)
interface Received {
/**
* Event to intercept the receiving of an chat message.

View File

@@ -24,8 +24,6 @@ import dev.architectury.event.Event;
import dev.architectury.event.EventFactory;
import dev.architectury.event.EventResult;
import dev.architectury.hooks.client.screen.ScreenAccess;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.DeltaTracker;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.screens.Screen;
@@ -33,7 +31,6 @@ import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
import java.util.List;
@Environment(EnvType.CLIENT)
public interface ClientGuiEvent {
/**
* @see RenderHud#renderHud(GuiGraphics, float)
@@ -73,7 +70,6 @@ public interface ClientGuiEvent {
*/
Event<SetScreen> SET_SCREEN = EventFactory.createCompoundEventResult();
@Environment(EnvType.CLIENT)
interface RenderHud {
/**
* Invoked after the in-game hud has been rendered.
@@ -85,7 +81,6 @@ public interface ClientGuiEvent {
void renderHud(GuiGraphics graphics, DeltaTracker deltaTracker);
}
@Environment(EnvType.CLIENT)
interface DebugText {
/**
* Invoked when the debug text is being gathered for rendering.
@@ -97,7 +92,6 @@ public interface ClientGuiEvent {
void gatherText(List<String> strings);
}
@Environment(EnvType.CLIENT)
interface ScreenInitPre {
/**
* Invoked when a screen is being initialized and after the previous widgets have been cleared.
@@ -111,7 +105,6 @@ public interface ClientGuiEvent {
EventResult init(Screen screen, ScreenAccess access);
}
@Environment(EnvType.CLIENT)
interface ScreenInitPost {
/**
* Invoked after a screen has been initialized and all the vanilla initialization logic has happened.
@@ -123,7 +116,6 @@ public interface ClientGuiEvent {
void init(Screen screen, ScreenAccess access);
}
@Environment(EnvType.CLIENT)
interface ScreenRenderPre {
/**
* Invoked before any screen is rendered.
@@ -137,10 +129,9 @@ public interface ClientGuiEvent {
* @return A {@link EventResult} determining the outcome of the event,
* the vanilla render may be cancelled by the result.
*/
EventResult render(Screen screen, GuiGraphics graphics, int mouseX, int mouseY, DeltaTracker delta);
EventResult render(Screen screen, GuiGraphics graphics, int mouseX, int mouseY, float delta);
}
@Environment(EnvType.CLIENT)
interface ScreenRenderPost {
/**
* Invoked after a screen has finished rendering using the vanilla logic.
@@ -152,10 +143,9 @@ public interface ClientGuiEvent {
* @param mouseY The scaled y-coordinate of the mouse cursor.
* @param delta The current tick delta.
*/
void render(Screen screen, GuiGraphics graphics, int mouseX, int mouseY, DeltaTracker delta);
void render(Screen screen, GuiGraphics graphics, int mouseX, int mouseY, float delta);
}
@Environment(EnvType.CLIENT)
interface ContainerScreenRenderBackground {
/**
* Invoked after a container screen's background are rendered.
@@ -170,7 +160,6 @@ public interface ClientGuiEvent {
void render(AbstractContainerScreen<?> screen, GuiGraphics graphics, int mouseX, int mouseY, float delta);
}
@Environment(EnvType.CLIENT)
interface ContainerScreenRenderForeground {
/**
* Invoked after a screen has finished rendering most of the foreground, but before any floating widgets are rendered.
@@ -185,7 +174,6 @@ public interface ClientGuiEvent {
void render(AbstractContainerScreen<?> screen, GuiGraphics graphics, int mouseX, int mouseY, float delta);
}
@Environment(EnvType.CLIENT)
interface SetScreen {
/**
* Invoked before a new screen is set to open.

View File

@@ -22,12 +22,9 @@ package dev.architectury.event.events.client;
import dev.architectury.event.Event;
import dev.architectury.event.EventFactory;
import dev.architectury.event.events.common.LifecycleEvent;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.ClientLevel;
@Environment(EnvType.CLIENT)
public interface ClientLifecycleEvent {
/**
* Invoked when client has been initialised.
@@ -55,11 +52,9 @@ public interface ClientLifecycleEvent {
*/
Event<ClientState> CLIENT_SETUP = EventFactory.createLoop();
@Environment(EnvType.CLIENT)
interface ClientState extends LifecycleEvent.InstanceState<Minecraft> {
}
@Environment(EnvType.CLIENT)
interface ClientLevelState extends LifecycleEvent.LevelState<ClientLevel> {
}
}

View File

@@ -21,12 +21,9 @@ package dev.architectury.event.events.client;
import dev.architectury.event.Event;
import dev.architectury.event.EventFactory;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.player.LocalPlayer;
import org.jetbrains.annotations.Nullable;
@Environment(EnvType.CLIENT)
public interface ClientPlayerEvent {
/**
* @see ClientPlayerJoin#join(LocalPlayer)
@@ -41,7 +38,6 @@ public interface ClientPlayerEvent {
*/
Event<ClientPlayerRespawn> CLIENT_PLAYER_RESPAWN = EventFactory.createLoop();
@Environment(EnvType.CLIENT)
interface ClientPlayerJoin {
/**
* Invoked whenever a client player joins a level
@@ -51,7 +47,6 @@ public interface ClientPlayerEvent {
void join(LocalPlayer player);
}
@Environment(EnvType.CLIENT)
interface ClientPlayerQuit {
/**
* Invoked whenever a client player leaves a level and is cleared on the client side.
@@ -61,7 +56,6 @@ public interface ClientPlayerEvent {
void quit(@Nullable LocalPlayer player);
}
@Environment(EnvType.CLIENT)
interface ClientPlayerRespawn {
/**
* Invoked whenever the player respawn packet is received by the client.

View File

@@ -22,11 +22,10 @@ package dev.architectury.event.events.client;
import dev.architectury.event.Event;
import dev.architectury.event.EventFactory;
import dev.architectury.event.EventResult;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.Minecraft;
import net.minecraft.client.input.KeyEvent;
import net.minecraft.client.input.MouseButtonInfo;
@Environment(EnvType.CLIENT)
public interface ClientRawInputEvent {
/**
* @see MouseScrolled#mouseScrolled(Minecraft, double, double)
@@ -38,7 +37,7 @@ public interface ClientRawInputEvent {
Event<MouseClicked> MOUSE_CLICKED_PRE = EventFactory.createEventResult();
Event<MouseClicked> MOUSE_CLICKED_POST = EventFactory.createEventResult();
/**
* @see KeyPressed#keyPressed(Minecraft, int, int, int, int)
* @see KeyPressed#keyPressed(Minecraft, int, KeyEvent)
*/
Event<KeyPressed> KEY_PRESSED = EventFactory.createEventResult();
@@ -47,15 +46,13 @@ public interface ClientRawInputEvent {
* Invoked whenever a key input is performed.
* Equivalent to Forge's {@code InputEvent.KeyInputEvent} event.
*
* @param client The Minecraft instance performing it.
* @param keyCode The key code.
* @param scanCode The raw keyboard scan code.
* @param action The action that should be performed.
* @param modifiers Additional modifiers.
* @param client The Minecraft instance performing it.
* @param keyCode The key code.
* @param keyEvent The key event.
* @return A {@link EventResult} determining the outcome of the event,
* the execution of the vanilla pressing mechanism may be cancelled by the result.
*/
EventResult keyPressed(Minecraft client, int keyCode, int scanCode, int action, int modifiers);
EventResult keyPressed(Minecraft client, int keyCode, KeyEvent keyEvent);
}
interface MouseScrolled {
@@ -77,13 +74,12 @@ public interface ClientRawInputEvent {
* Invoked whenever a mouse button is pressed.
* There are two variants, either a raw mouse input or the input after it is processed by the game.
*
* @param client The Minecraft instance performing it.
* @param button The pressed mouse button.
* @param action The action that should be performed.
* @param mods Additional modifiers.
* @param client The Minecraft instance performing it.
* @param buttonInfo The pressed mouse button info.
* @param action The action that should be performed.
* @return A {@link EventResult} determining the outcome of the event,
* the execution of the vanilla clicking mechanism may be cancelled by the result.
*/
EventResult mouseClicked(Minecraft client, int button, int action, int mods);
EventResult mouseClicked(Minecraft client, MouseButtonInfo buttonInfo, int action);
}
}

View File

@@ -21,8 +21,6 @@ package dev.architectury.event.events.client;
import dev.architectury.event.Event;
import dev.architectury.event.EventFactory;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.network.protocol.game.ClientboundRecipeBookAddPacket;
import net.minecraft.world.item.crafting.RecipeAccess;
import net.minecraft.world.item.crafting.display.RecipeDisplayId;
@@ -30,7 +28,6 @@ import org.jetbrains.annotations.ApiStatus;
import java.util.List;
@Environment(EnvType.CLIENT)
public interface ClientRecipeUpdateEvent {
/**
* @see ClientRecipeUpdateEvent#update(RecipeAccess)

View File

@@ -22,12 +22,12 @@ package dev.architectury.event.events.client;
import dev.architectury.event.Event;
import dev.architectury.event.EventFactory;
import dev.architectury.event.EventResult;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.input.CharacterEvent;
import net.minecraft.client.input.KeyEvent;
import net.minecraft.client.input.MouseButtonEvent;
@Environment(EnvType.CLIENT)
public interface ClientScreenInputEvent {
/**
* @see MouseScrolled#mouseScrolled(Minecraft, Screen, double, double, double, double)
@@ -50,17 +50,17 @@ public interface ClientScreenInputEvent {
Event<MouseDragged> MOUSE_DRAGGED_PRE = EventFactory.createEventResult();
Event<MouseDragged> MOUSE_DRAGGED_POST = EventFactory.createEventResult();
/**
* @see KeyTyped#charTyped(Minecraft, Screen, char, int)
* @see KeyTyped#charTyped(Minecraft, Screen, CharacterEvent)
*/
Event<KeyTyped> CHAR_TYPED_PRE = EventFactory.createEventResult();
Event<KeyTyped> CHAR_TYPED_POST = EventFactory.createEventResult();
/**
* @see KeyPressed#keyPressed(Minecraft, Screen, int, int, int)
* @see KeyPressed#keyPressed(Minecraft, Screen, KeyEvent)
*/
Event<KeyPressed> KEY_PRESSED_PRE = EventFactory.createEventResult();
Event<KeyPressed> KEY_PRESSED_POST = EventFactory.createEventResult();
/**
* @see KeyReleased#keyReleased(Minecraft, Screen, int, int, int)
* @see KeyReleased#keyReleased(Minecraft, Screen, KeyEvent)
*/
Event<KeyReleased> KEY_RELEASED_PRE = EventFactory.createEventResult();
Event<KeyReleased> KEY_RELEASED_POST = EventFactory.createEventResult();
@@ -73,15 +73,13 @@ public interface ClientScreenInputEvent {
* <p> This event is handled in two phases PRE and POST, which are invoked
* before and after the keys have been processed by the screen, respectively.
*
* @param client The Minecraft instance performing it.
* @param screen The screen this keystroke was performed in.
* @param keyCode The key code.
* @param scanCode The raw keyboard scan code.
* @param modifiers Additional modifiers.
* @param client The Minecraft instance performing it.
* @param screen The screen this keystroke was performed in.
* @param keyEvent The key event.
* @return A {@link EventResult} determining the outcome of the event,
* the execution of the vanilla pressing mechanism may be cancelled by the result.
*/
EventResult keyPressed(Minecraft client, Screen screen, int keyCode, int scanCode, int modifiers);
EventResult keyPressed(Minecraft client, Screen screen, KeyEvent keyEvent);
}
interface KeyReleased {
@@ -92,15 +90,13 @@ public interface ClientScreenInputEvent {
* <p> This event is handled in two phases PRE and POST, which are invoked
* before and after the keys have been processed by the screen, respectively.
*
* @param client The Minecraft instance performing it.
* @param screen The screen this keystroke was performed in.
* @param keyCode The key code.
* @param scanCode The raw keyboard scan code.
* @param modifiers Additional modifiers.
* @param client The Minecraft instance performing it.
* @param screen The screen this keystroke was performed in.
* @param keyEvent The key event.
* @return A {@link EventResult} determining the outcome of the event,
* the execution of the vanilla releasing mechanism may be cancelled by the result.
*/
EventResult keyReleased(Minecraft client, Screen screen, int keyCode, int scanCode, int modifiers);
EventResult keyReleased(Minecraft client, Screen screen, KeyEvent keyEvent);
}
interface KeyTyped {
@@ -111,14 +107,13 @@ public interface ClientScreenInputEvent {
* <p> This event is handled in two phases PRE and POST, which are invoked
* before and after the keys have been processed by the screen, respectively.
*
* @param client The Minecraft instance performing it.
* @param screen The screen this keystroke was performed in.
* @param character The typed character.
* @param keyCode The key code.
* @param client The Minecraft instance performing it.
* @param screen The screen this keystroke was performed in.
* @param characterEvent The character event.
* @return A {@link EventResult} determining the outcome of the event,
* the execution of the vanilla typing mechanism may be cancelled by the result.
*/
EventResult charTyped(Minecraft client, Screen screen, char character, int keyCode);
EventResult charTyped(Minecraft client, Screen screen, CharacterEvent characterEvent);
}
interface MouseScrolled {
@@ -149,15 +144,13 @@ public interface ClientScreenInputEvent {
* <p> This event is handled in two phases PRE and POST, which are invoked
* before and after the keys have been processed by the screen, respectively.
*
* @param client The Minecraft instance performing it.
* @param screen The screen this keystroke was performed in.
* @param mouseX The scaled x-coordinate of the mouse cursor.
* @param mouseY The scaled y-coordinate of the mouse cursor.
* @param button The released mouse button.
* @param client The Minecraft instance performing it.
* @param screen The screen this keystroke was performed in.
* @param buttonEvent The button click event.
* @return A {@link EventResult} determining the outcome of the event,
* the execution of the vanilla releasing mechanism may be cancelled by the result.
*/
EventResult mouseReleased(Minecraft client, Screen screen, double mouseX, double mouseY, int button);
EventResult mouseReleased(Minecraft client, Screen screen, MouseButtonEvent buttonEvent);
}
interface MouseDragged {
@@ -168,17 +161,15 @@ public interface ClientScreenInputEvent {
* <p> This event is handled in two phases PRE and POST, which are invoked
* before and after the keys have been processed by the screen, respectively.
*
* @param client The Minecraft instance performing it.
* @param screen The screen this keystroke was performed in.
* @param mouseX1 The initial scaled x-coordinate of the mouse cursor.
* @param mouseY1 The initial scaled y-coordinate of the mouse cursor.
* @param button The dragged mouse button.
* @param mouseX2 The final scaled x-coordinate of the mouse cursor.
* @param mouseY2 The final scaled y-coordinate of the mouse cursor.
* @param client The Minecraft instance performing it.
* @param screen The screen this keystroke was performed in.
* @param buttonEvent The mouse event.
* @param mouseX2 The final scaled x-delta of the mouse cursor.
* @param mouseY2 The final scaled y-delta of the mouse cursor.
* @return A {@link EventResult} determining the outcome of the event,
* the execution of the vanilla dragging mechanism may be cancelled by the result.
*/
EventResult mouseDragged(Minecraft client, Screen screen, double mouseX1, double mouseY1, int button, double mouseX2, double mouseY2);
EventResult mouseDragged(Minecraft client, Screen screen, MouseButtonEvent buttonEvent, double mouseX2, double mouseY2);
}
interface MouseClicked {
@@ -189,14 +180,13 @@ public interface ClientScreenInputEvent {
* <p> This event is handled in two phases PRE and POST, which are invoked
* before and after the keys have been processed by the screen, respectively.
*
* @param client The Minecraft instance performing it.
* @param screen The screen this keystroke was performed in.
* @param mouseX The scaled x-coordinate of the mouse cursor.
* @param mouseY The scaled y-coordinate of the mouse cursor.
* @param button The clicked mouse button.
* @param client The Minecraft instance performing it.
* @param screen The screen this keystroke was performed in.
* @param buttonEvent The button click event.
* @param doubleClick Whether the click is a double click.
* @return A {@link EventResult} determining the outcome of the event,
* the execution of the vanilla clicking mechanism may be cancelled by the result.
*/
EventResult mouseClicked(Minecraft client, Screen screen, double mouseX, double mouseY, int button);
EventResult mouseClicked(Minecraft client, Screen screen, MouseButtonEvent buttonEvent, boolean doubleClick);
}
}

View File

@@ -22,18 +22,14 @@ package dev.architectury.event.events.client;
import dev.architectury.event.CompoundEventResult;
import dev.architectury.event.Event;
import dev.architectury.event.EventFactory;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.network.chat.Component;
@Environment(EnvType.CLIENT)
public interface ClientSystemMessageEvent {
/**
* @see Received#process(Component)
*/
Event<Received> RECEIVED = EventFactory.createCompoundEventResult();
@Environment(EnvType.CLIENT)
interface Received {
/**
* Event to intercept the receiving of a system message.

View File

@@ -21,11 +21,8 @@ package dev.architectury.event.events.client;
import dev.architectury.event.Event;
import dev.architectury.event.EventFactory;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.Minecraft;
@Environment(EnvType.CLIENT)
public interface ClientTickEvent<T> {
Event<Client> CLIENT_PRE = EventFactory.createLoop();
Event<Client> CLIENT_POST = EventFactory.createLoop();
@@ -34,11 +31,9 @@ public interface ClientTickEvent<T> {
void tick(T instance);
@Environment(EnvType.CLIENT)
interface Client extends ClientTickEvent<Minecraft> {
}
@Environment(EnvType.CLIENT)
interface ClientLevel extends ClientTickEvent<net.minecraft.client.multiplayer.ClientLevel> {
}
}

View File

@@ -23,8 +23,6 @@ import dev.architectury.event.Event;
import dev.architectury.event.EventFactory;
import dev.architectury.event.EventResult;
import dev.architectury.impl.TooltipAdditionalContextsImpl;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.screens.inventory.tooltip.ClientTooltipComponent;
import net.minecraft.network.chat.Component;
@@ -35,7 +33,6 @@ import org.jetbrains.annotations.Nullable;
import java.util.List;
@Environment(EnvType.CLIENT)
public interface ClientTooltipEvent {
/**
* @see Item#append(ItemStack, List, net.minecraft.world.item.Item.TooltipContext, TooltipFlag)
@@ -62,7 +59,6 @@ public interface ClientTooltipEvent {
void setItem(@Nullable ItemStack stack);
}
@Environment(EnvType.CLIENT)
interface Item {
/**
* Invoked whenever an item tooltip is rendered.
@@ -77,7 +73,6 @@ public interface ClientTooltipEvent {
void append(ItemStack stack, List<Component> lines, net.minecraft.world.item.Item.TooltipContext tooltipContext, TooltipFlag flag);
}
@Environment(EnvType.CLIENT)
interface Render {
/**
* Invoked before the tooltip for a tooltip is rendered.
@@ -92,7 +87,6 @@ public interface ClientTooltipEvent {
EventResult renderTooltip(GuiGraphics graphics, List<? extends ClientTooltipComponent> texts, int x, int y);
}
@Environment(EnvType.CLIENT)
interface RenderModifyPosition {
/**
* Event to manipulate the position of the tooltip.
@@ -103,7 +97,6 @@ public interface ClientTooltipEvent {
void renderTooltip(GuiGraphics graphics, PositionContext context);
}
@Environment(EnvType.CLIENT)
interface PositionContext {
int getTooltipX();

View File

@@ -0,0 +1,85 @@
/*
* This file is part of architectury.
* Copyright (C) 2020, 2021, 2022 architectury
*
* 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 dev.architectury.hooks.client.fluid;
import dev.architectury.fluid.FluidStack;
import dev.architectury.injectables.annotations.ExpectPlatform;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.BlockAndTintGetter;
import net.minecraft.world.level.material.Fluid;
import net.minecraft.world.level.material.FluidState;
import org.jetbrains.annotations.Nullable;
public class ClientFluidStackHooks {
private ClientFluidStackHooks() {
}
@ExpectPlatform
@Nullable
public static TextureAtlasSprite getStillTexture(@Nullable BlockAndTintGetter level, @Nullable BlockPos pos, FluidState state) {
throw new AssertionError();
}
@ExpectPlatform
@Nullable
public static TextureAtlasSprite getStillTexture(FluidStack stack) {
throw new AssertionError();
}
@ExpectPlatform
@Nullable
public static TextureAtlasSprite getStillTexture(Fluid fluid) {
throw new AssertionError();
}
@ExpectPlatform
@Nullable
public static TextureAtlasSprite getFlowingTexture(@Nullable BlockAndTintGetter level, @Nullable BlockPos pos, FluidState state) {
throw new AssertionError();
}
@ExpectPlatform
@Nullable
public static TextureAtlasSprite getFlowingTexture(FluidStack stack) {
throw new AssertionError();
}
@ExpectPlatform
@Nullable
public static TextureAtlasSprite getFlowingTexture(Fluid fluid) {
throw new AssertionError();
}
@ExpectPlatform
public static int getColor(@Nullable BlockAndTintGetter level, @Nullable BlockPos pos, FluidState state) {
throw new AssertionError();
}
@ExpectPlatform
public static int getColor(FluidStack stack) {
throw new AssertionError();
}
@ExpectPlatform
public static int getColor(Fluid fluid) {
throw new AssertionError();
}
}

View File

@@ -20,8 +20,6 @@
package dev.architectury.hooks.client.screen;
import dev.architectury.injectables.annotations.ExpectPlatform;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.gui.components.AbstractWidget;
import net.minecraft.client.gui.components.Renderable;
import net.minecraft.client.gui.components.events.GuiEventListener;
@@ -30,7 +28,6 @@ import net.minecraft.client.gui.screens.Screen;
import java.util.List;
@Environment(EnvType.CLIENT)
public final class ScreenHooks {
private ScreenHooks() {
}

View File

@@ -102,66 +102,6 @@ public class FluidStackHooks {
throw new AssertionError();
}
@ExpectPlatform
@Environment(EnvType.CLIENT)
@Nullable
public static TextureAtlasSprite getStillTexture(@Nullable BlockAndTintGetter level, @Nullable BlockPos pos, FluidState state) {
throw new AssertionError();
}
@ExpectPlatform
@Environment(EnvType.CLIENT)
@Nullable
public static TextureAtlasSprite getStillTexture(FluidStack stack) {
throw new AssertionError();
}
@ExpectPlatform
@Environment(EnvType.CLIENT)
@Nullable
public static TextureAtlasSprite getStillTexture(Fluid fluid) {
throw new AssertionError();
}
@ExpectPlatform
@Environment(EnvType.CLIENT)
@Nullable
public static TextureAtlasSprite getFlowingTexture(@Nullable BlockAndTintGetter level, @Nullable BlockPos pos, FluidState state) {
throw new AssertionError();
}
@ExpectPlatform
@Environment(EnvType.CLIENT)
@Nullable
public static TextureAtlasSprite getFlowingTexture(FluidStack stack) {
throw new AssertionError();
}
@ExpectPlatform
@Environment(EnvType.CLIENT)
@Nullable
public static TextureAtlasSprite getFlowingTexture(Fluid fluid) {
throw new AssertionError();
}
@ExpectPlatform
@Environment(EnvType.CLIENT)
public static int getColor(@Nullable BlockAndTintGetter level, @Nullable BlockPos pos, FluidState state) {
throw new AssertionError();
}
@ExpectPlatform
@Environment(EnvType.CLIENT)
public static int getColor(FluidStack stack) {
throw new AssertionError();
}
@ExpectPlatform
@Environment(EnvType.CLIENT)
public static int getColor(Fluid fluid) {
throw new AssertionError();
}
/**
* Returns the luminosity of the fluid.
*

View File

@@ -48,7 +48,7 @@ public abstract class MixinLightningBolt extends Entity {
by = 1
), locals = LocalCapture.CAPTURE_FAILHARD)
public void handleLightning(CallbackInfo ci, List<Entity> list) {
if (this.isRemoved() || this.level().isClientSide) {
if (this.isRemoved() || this.level().isClientSide()) {
return;
}

View File

@@ -0,0 +1,58 @@
/*
* This file is part of architectury.
* Copyright (C) 2020, 2021, 2022 architectury
*
* 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 dev.architectury.networking;
import dev.architectury.extensions.network.EntitySpawnExtension;
import io.netty.buffer.Unpooled;
import net.minecraft.client.Minecraft;
import net.minecraft.network.RegistryFriendlyByteBuf;
import net.minecraft.world.entity.EntitySpawnReason;
import net.minecraft.world.phys.Vec3;
public class ClientSpawnEntityPacket {
public static void register() {
NetworkManager.registerReceiver(NetworkManager.s2c(), SpawnEntityPacket.PACKET_TYPE, SpawnEntityPacket.PACKET_CODEC, ClientSpawnEntityPacket::receive);
}
private static void receive(SpawnEntityPacket.PacketPayload payload, NetworkManager.PacketContext context) {
context.queue(() -> {
if (Minecraft.getInstance().level == null) {
throw new IllegalStateException("Client world is null!");
}
var entity = payload.entityType().create(Minecraft.getInstance().level, EntitySpawnReason.LOAD);
if (entity == null) {
throw new IllegalStateException("Created entity is null!");
}
entity.setUUID(payload.uuid());
entity.setId(payload.id());
entity.syncPacketPositionCodec(payload.x(), payload.y(), payload.z());
entity.snapTo(payload.x(), payload.y(), payload.z(), payload.xRot(), payload.yRot());
entity.setYHeadRot(payload.yHeadRot());
entity.setYBodyRot(payload.yHeadRot());
if (entity instanceof EntitySpawnExtension ext) {
RegistryFriendlyByteBuf buf = new RegistryFriendlyByteBuf(Unpooled.wrappedBuffer(payload.data()), context.registryAccess());
ext.loadAdditionalSpawnData(buf);
buf.release();
}
Minecraft.getInstance().level.addEntity(entity);
entity.lerpMotion(new Vec3(payload.deltaX(), payload.deltaY(), payload.deltaZ()));
});
}
}

View File

@@ -1,132 +0,0 @@
/*
* This file is part of architectury.
* Copyright (C) 2020, 2021, 2022 architectury
*
* 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 dev.architectury.networking;
import com.google.common.collect.Maps;
import dev.architectury.networking.NetworkManager.PacketContext;
import dev.architectury.platform.Platform;
import dev.architectury.utils.Env;
import io.netty.buffer.Unpooled;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.ClientPacketListener;
import net.minecraft.core.RegistryAccess;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.RegistryFriendlyByteBuf;
import net.minecraft.network.protocol.Packet;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerPlayer;
import java.nio.charset.StandardCharsets;
import java.util.Iterator;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.function.Supplier;
/**
* Forge {@code SimpleChannel} like network wrapper of {@link NetworkManager}.
*/
@Deprecated(forRemoval = true)
public final class NetworkChannel {
private final ResourceLocation id;
private final Map<Class<?>, MessageInfo<?>> encoders = Maps.newHashMap();
private NetworkChannel(ResourceLocation id) {
this.id = id;
}
public static NetworkChannel create(ResourceLocation id) {
return new NetworkChannel(id);
}
public <T> void register(Class<T> type, BiConsumer<T, FriendlyByteBuf> encoder, Function<FriendlyByteBuf, T> decoder, BiConsumer<T, Supplier<PacketContext>> messageConsumer) {
// TODO: this is pretty wasteful; add a way to specify custom or numeric ids
var s = UUID.nameUUIDFromBytes(type.getName().getBytes(StandardCharsets.UTF_8)).toString().replace("-", "");
var info = new MessageInfo<T>(ResourceLocation.parse(id + "/" + s), encoder, decoder, messageConsumer);
encoders.put(type, info);
NetworkManager.NetworkReceiver<RegistryFriendlyByteBuf> receiver = (buf, context) -> {
info.messageConsumer.accept(info.decoder.apply(buf), () -> context);
};
NetworkManager.registerReceiver(NetworkManager.c2s(), info.packetId, receiver);
if (Platform.getEnvironment() == Env.CLIENT) {
NetworkManager.registerReceiver(NetworkManager.s2c(), info.packetId, receiver);
}
}
public static long hashCodeString(String str) {
long h = 0;
var length = str.length();
for (var i = 0; i < length; i++) {
h = 31 * h + str.charAt(i);
}
return h;
}
public <T> Packet<?> toPacket(NetworkManager.Side side, T message, RegistryAccess access) {
var messageInfo = (MessageInfo<T>) Objects.requireNonNull(encoders.get(message.getClass()), "Unknown message type! " + message);
var buf = new RegistryFriendlyByteBuf(Unpooled.buffer(), access);
messageInfo.encoder.accept(message, buf);
return NetworkManager.toPacket(side, messageInfo.packetId, buf);
}
public <T> void sendToPlayer(ServerPlayer player, T message) {
Objects.requireNonNull(player, "Unable to send packet to a 'null' player!").connection.send(toPacket(NetworkManager.s2c(), message, player.registryAccess()));
}
public <T> void sendToPlayers(Iterable<ServerPlayer> players, T message) {
Iterator<ServerPlayer> iterator = players.iterator();
if (!iterator.hasNext()) return;
var packet = toPacket(NetworkManager.s2c(), message, iterator.next().registryAccess());
for (var player : players) {
Objects.requireNonNull(player, "Unable to send packet to a 'null' player!").connection.send(packet);
}
}
@Environment(EnvType.CLIENT)
public <T> void sendToServer(T message) {
ClientPacketListener connection = Minecraft.getInstance().getConnection();
if (connection != null) {
connection.send(toPacket(NetworkManager.c2s(), message, connection.registryAccess()));
} else {
throw new IllegalStateException("Unable to send packet to the server while not in game!");
}
}
@Environment(EnvType.CLIENT)
public <T> boolean canServerReceive(Class<T> type) {
return NetworkManager.canServerReceive(encoders.get(type).packetId);
}
public <T> boolean canPlayerReceive(ServerPlayer player, Class<T> type) {
return NetworkManager.canPlayerReceive(player, encoders.get(type).packetId);
}
private record MessageInfo<T>(
ResourceLocation packetId,
BiConsumer<T, FriendlyByteBuf> encoder,
Function<FriendlyByteBuf, T> decoder,
BiConsumer<T, Supplier<PacketContext>> messageConsumer
) {
}
}

View File

@@ -26,10 +26,7 @@ import dev.architectury.networking.transformers.PacketSink;
import dev.architectury.networking.transformers.PacketTransformer;
import dev.architectury.networking.transformers.SinglePacketCollector;
import dev.architectury.utils.Env;
import dev.architectury.utils.GameInstance;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.multiplayer.ClientPacketListener;
import net.minecraft.core.RegistryAccess;
import net.minecraft.network.RegistryFriendlyByteBuf;
import net.minecraft.network.codec.StreamCodec;
@@ -147,7 +144,6 @@ public final class NetworkManager {
collectPackets(PacketSink.ofPlayers(players), serverToClient(), id, buf);
}
@Environment(EnvType.CLIENT)
@Deprecated(forRemoval = true)
public static void sendToServer(ResourceLocation id, RegistryFriendlyByteBuf buf) {
collectPackets(PacketSink.client(), clientToServer(), id, buf);
@@ -163,14 +159,11 @@ public final class NetworkManager {
collectPackets(PacketSink.ofPlayers(players), serverToClient(), payload, iterator.next().registryAccess());
}
@Environment(EnvType.CLIENT)
@ExpectPlatform
public static <T extends CustomPacketPayload> void sendToServer(T payload) {
ClientPacketListener connection = GameInstance.getClient().getConnection();
if (connection == null) return;
collectPackets(PacketSink.client(), clientToServer(), payload, connection.registryAccess());
throw new AssertionError();
}
@Environment(EnvType.CLIENT)
@ExpectPlatform
public static boolean canServerReceive(ResourceLocation id) {
throw new AssertionError();
@@ -181,7 +174,6 @@ public final class NetworkManager {
throw new AssertionError();
}
@Environment(EnvType.CLIENT)
public static boolean canServerReceive(CustomPacketPayload.Type<?> type) {
return canServerReceive(type.id());
}

View File

@@ -22,9 +22,6 @@ package dev.architectury.networking;
import dev.architectury.extensions.network.EntitySpawnExtension;
import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.Minecraft;
import net.minecraft.core.BlockPos;
import net.minecraft.core.registries.Registries;
import net.minecraft.network.FriendlyByteBuf;
@@ -37,7 +34,6 @@ import net.minecraft.network.protocol.game.ClientGamePacketListener;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerEntity;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntitySpawnReason;
import net.minecraft.world.entity.EntityType;
import java.util.UUID;
@@ -46,9 +42,9 @@ import java.util.UUID;
* @see net.minecraft.network.protocol.game.ClientboundAddEntityPacket
*/
public class SpawnEntityPacket {
private static final ResourceLocation PACKET_ID = ResourceLocation.fromNamespaceAndPath("architectury", "spawn_entity_packet");
private static final CustomPacketPayload.Type<PacketPayload> PACKET_TYPE = new CustomPacketPayload.Type<>(PACKET_ID);
private static final StreamCodec<RegistryFriendlyByteBuf, PacketPayload> PACKET_CODEC = CustomPacketPayload.codec(PacketPayload::write, PacketPayload::new);
static final ResourceLocation PACKET_ID = ResourceLocation.fromNamespaceAndPath("architectury", "spawn_entity_packet");
static final CustomPacketPayload.Type<PacketPayload> PACKET_TYPE = new CustomPacketPayload.Type<>(PACKET_ID);
static final StreamCodec<RegistryFriendlyByteBuf, PacketPayload> PACKET_CODEC = CustomPacketPayload.codec(PacketPayload::write, PacketPayload::new);
public static Packet<ClientGamePacketListener> create(Entity entity, ServerEntity serverEntity) {
if (entity.level().isClientSide()) {
@@ -61,42 +57,7 @@ public class SpawnEntityPacket {
NetworkManager.registerS2CPayloadType(PACKET_TYPE, PACKET_CODEC);
}
@Environment(EnvType.CLIENT)
public static class Client {
@Environment(EnvType.CLIENT)
public static void register() {
NetworkManager.registerReceiver(NetworkManager.s2c(), PACKET_TYPE, PACKET_CODEC, Client::receive);
}
@Environment(EnvType.CLIENT)
private static void receive(PacketPayload payload, NetworkManager.PacketContext context) {
context.queue(() -> {
if (Minecraft.getInstance().level == null) {
throw new IllegalStateException("Client world is null!");
}
var entity = payload.entityType().create(Minecraft.getInstance().level, EntitySpawnReason.LOAD);
if (entity == null) {
throw new IllegalStateException("Created entity is null!");
}
entity.setUUID(payload.uuid());
entity.setId(payload.id());
entity.syncPacketPositionCodec(payload.x(), payload.y(), payload.z());
entity.snapTo(payload.x(), payload.y(), payload.z(), payload.xRot(), payload.yRot());
entity.setYHeadRot(payload.yHeadRot());
entity.setYBodyRot(payload.yHeadRot());
if (entity instanceof EntitySpawnExtension ext) {
RegistryFriendlyByteBuf buf = new RegistryFriendlyByteBuf(Unpooled.wrappedBuffer(payload.data()), context.registryAccess());
ext.loadAdditionalSpawnData(buf);
buf.release();
}
Minecraft.getInstance().level.addEntity(entity);
entity.lerpMotion(payload.deltaX(), payload.deltaY(), payload.deltaZ());
});
}
}
private record PacketPayload(EntityType<?> entityType, UUID uuid, int id, double x, double y, double z, float xRot,
record PacketPayload(EntityType<?> entityType, UUID uuid, int id, double x, double y, double z, float xRot,
float yRot,
float yHeadRot,
double deltaX, double deltaY, double deltaZ,

View File

@@ -1,91 +0,0 @@
/*
* This file is part of architectury.
* Copyright (C) 2020, 2021, 2022 architectury
*
* 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 dev.architectury.networking.simple;
import net.minecraft.network.protocol.Packet;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerChunkCache;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.level.chunk.LevelChunk;
/**
* The base class for server -&gt; client messages managed by a {@link SimpleNetworkManager}.
*/
public abstract class BaseS2CMessage extends Message {
private void sendTo(ServerPlayer player, Packet<?> packet) {
if (player == null) {
throw new NullPointerException("Unable to send packet '" + getType().getId() + "' to a 'null' player!");
}
player.connection.send(packet);
}
/**
* Sends this message to a player.
*
* @param player the player
*/
public final void sendTo(ServerPlayer player) {
sendTo(player, toPacket(player.registryAccess()));
}
/**
* Sends this message to multiple players.
*
* @param players the players
*/
public final void sendTo(Iterable<ServerPlayer> players) {
if (!players.iterator().hasNext()) return;
Packet<?> packet = toPacket(players.iterator().next().registryAccess());
for (ServerPlayer player : players) {
sendTo(player, packet);
}
}
/**
* Sends this message to all players in the server.
*
* @param server the server
*/
public final void sendToAll(MinecraftServer server) {
sendTo(server.getPlayerList().getPlayers());
}
/**
* Sends this message to all players in a level.
*
* @param level the level
*/
public final void sendToLevel(ServerLevel level) {
sendTo(level.players());
}
/**
* Sends this message to all players listening to a chunk.
*
* @param chunk the listened chunk
*/
public final void sendToChunkListeners(LevelChunk chunk) {
Packet<?> packet = toPacket(chunk.getLevel().registryAccess());
((ServerChunkCache) chunk.getLevel().getChunkSource()).chunkMap.getPlayers(chunk.getPos(), false).forEach(e -> sendTo(e, packet));
}
}

View File

@@ -1,71 +0,0 @@
/*
* This file is part of architectury.
* Copyright (C) 2020, 2021, 2022 architectury
*
* 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 dev.architectury.networking.simple;
import dev.architectury.networking.NetworkManager;
import io.netty.buffer.Unpooled;
import net.minecraft.core.RegistryAccess;
import net.minecraft.network.RegistryFriendlyByteBuf;
import net.minecraft.network.protocol.Packet;
/**
* The base class for messages managed by a {@link SimpleNetworkManager}.
*
* @see BaseC2SMessage
* @see BaseS2CMessage
*/
public abstract class Message {
Message() {
}
/**
* Returns the {@link MessageType} of this message
*
* @return the {@link MessageType} of this message
* @see SimpleNetworkManager#registerC2S(String, MessageDecoder)
* @see SimpleNetworkManager#registerS2C(String, MessageDecoder)
*/
public abstract MessageType getType();
/**
* Writes this message to a byte buffer.
*
* @param buf the byte buffer
*/
public abstract void write(RegistryFriendlyByteBuf buf);
/**
* Handles this message when it is received.
*
* @param context the packet context for handling this message
*/
public abstract void handle(NetworkManager.PacketContext context);
/**
* Converts this message into a corresponding vanilla {@link Packet}.
*
* @return the converted {@link Packet}
*/
public final Packet<?> toPacket(RegistryAccess access) {
RegistryFriendlyByteBuf buf = new RegistryFriendlyByteBuf(Unpooled.buffer(), access);
write(buf);
return NetworkManager.toPacket(getType().getSide(), getType().getId(), buf);
}
}

View File

@@ -1,55 +0,0 @@
/*
* This file is part of architectury.
* Copyright (C) 2020, 2021, 2022 architectury
*
* 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 dev.architectury.networking.simple;
import dev.architectury.networking.NetworkManager;
import net.minecraft.network.RegistryFriendlyByteBuf;
/**
* Decodes a {@link Message} from a {@link RegistryFriendlyByteBuf}.
*
* @param <T> the message type handled by this decoder
* @author LatvianModder
*/
@FunctionalInterface
public interface MessageDecoder<T extends Message> {
/**
* Decodes a {@code T} message from a byte buffer.
*
* @param buf the byte buffer
* @return the decoded instance
*/
T decode(RegistryFriendlyByteBuf buf);
/**
* Creates a network receiver from this decoder.
*
* <p>The returned receiver will first {@linkplain #decode(RegistryFriendlyByteBuf) decode a message}
* and then call {@link Message#handle(NetworkManager.PacketContext)} on the decoded message.
*
* @return the created receiver
*/
default NetworkManager.NetworkReceiver<RegistryFriendlyByteBuf> createReceiver() {
return (buf, context) -> {
Message packet = decode(buf);
context.queue(() -> packet.handle(context));
};
}
}

View File

@@ -1,89 +0,0 @@
/*
* This file is part of architectury.
* Copyright (C) 2020, 2021, 2022 architectury
*
* 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 dev.architectury.networking.simple;
import dev.architectury.networking.NetworkManager;
import net.minecraft.resources.ResourceLocation;
import java.util.Objects;
/**
* A unique type for a message in a {@link SimpleNetworkManager}.
*/
public final class MessageType {
private final SimpleNetworkManager manager;
private final ResourceLocation id;
private final NetworkManager.Side side;
MessageType(SimpleNetworkManager manager, ResourceLocation id, NetworkManager.Side side) {
this.manager = manager;
this.id = id;
this.side = side;
}
/**
* Returns the network manager that manages this message type
*
* @return the network manager that manages this message type
*/
public SimpleNetworkManager getManager() {
return manager;
}
/**
* Returns the ID of this message type
*
* @return the ID of this message type
*/
public ResourceLocation getId() {
return id;
}
/**
* Returns the network side of this message type
*
* @return the network side of this message type
*/
public NetworkManager.Side getSide() {
return side;
}
@Override
public String toString() {
return id.toString() + ":" + side.name().toLowerCase();
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
} else if (o == null || getClass() != o.getClass()) {
return false;
}
MessageType messageType = (MessageType) o;
return id.equals(messageType.id) && side == messageType.side;
}
@Override
public int hashCode() {
return Objects.hash(id, side);
}
}

View File

@@ -1,115 +0,0 @@
/*
* This file is part of architectury.
* Copyright (C) 2020, 2021, 2022 architectury
*
* 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 dev.architectury.networking.simple;
import dev.architectury.networking.NetworkManager;
import dev.architectury.networking.transformers.PacketTransformer;
import dev.architectury.platform.Platform;
import dev.architectury.utils.Env;
import net.minecraft.network.RegistryFriendlyByteBuf;
import net.minecraft.resources.ResourceLocation;
import org.jetbrains.annotations.ApiStatus;
import java.util.List;
/**
* A simple wrapper for {@link NetworkManager} to make it easier to register messages and send them to clients/servers.
*/
public class SimpleNetworkManager {
/**
* Creates a new {@code SimpleNetworkManager}.
*
* @param namespace a unique namespace for the messages ({@link #namespace})
* @return the created network manager
*/
public static SimpleNetworkManager create(String namespace) {
return new SimpleNetworkManager(namespace);
}
/**
* The unique namespace for the messages managed by this manager.
* This will typically be a mod ID.
*/
public final String namespace;
private SimpleNetworkManager(String namespace) {
this.namespace = namespace;
}
/**
* Registers a server -&gt; client message with no packet transformers.
*
* @param id a unique ID for the message, must be a valid value for {@link ResourceLocation#getPath}
* @param decoder the message decoder for the message
* @return a {@link MessageType} describing the registered message
* @see #registerS2C(String, MessageDecoder, List)
*/
public MessageType registerS2C(String id, MessageDecoder<BaseS2CMessage> decoder) {
return registerS2C(id, decoder, List.of());
}
/**
* Registers a server -&gt; client message using the given packet transformers.
*
* @param id a unique ID for the message, must be a valid value for {@link ResourceLocation#getPath}
* @param decoder the message decoder for the message
* @param transformers a list of packet transformers to apply to the message packet
* @return a {@link MessageType} describing the registered message
*/
@ApiStatus.Experimental
public MessageType registerS2C(String id, MessageDecoder<BaseS2CMessage> decoder, List<PacketTransformer> transformers) {
MessageType messageType = new MessageType(this, ResourceLocation.fromNamespaceAndPath(namespace, id), NetworkManager.s2c());
if (Platform.getEnvironment() == Env.CLIENT) {
NetworkManager.NetworkReceiver<RegistryFriendlyByteBuf> receiver = decoder.createReceiver();
NetworkManager.registerReceiver(NetworkManager.s2c(), messageType.getId(), transformers, receiver);
}
return messageType;
}
/**
* Registers a client -&gt; server message with no packet transformers.
*
* @param id a unique ID for the message, must be a valid value for {@link ResourceLocation#getPath}
* @param decoder the message decoder for the message
* @return a {@link MessageType} describing the registered message
* @see #registerC2S(String, MessageDecoder, List)
*/
public MessageType registerC2S(String id, MessageDecoder<BaseC2SMessage> decoder) {
return registerC2S(id, decoder, List.of());
}
/**
* Registers a client -&gt; server message using the given packet transformers.
*
* @param id a unique ID for the message, must be a valid value for {@link ResourceLocation#getPath}
* @param decoder the message decoder for the message
* @param transformers a list of packet transformers to apply to the message packet
* @return a {@link MessageType} describing the registered message
*/
@ApiStatus.Experimental
public MessageType registerC2S(String id, MessageDecoder<BaseC2SMessage> decoder, List<PacketTransformer> transformers) {
MessageType messageType = new MessageType(this, ResourceLocation.fromNamespaceAndPath(namespace, id), NetworkManager.c2s());
NetworkManager.NetworkReceiver<RegistryFriendlyByteBuf> receiver = decoder.createReceiver();
NetworkManager.registerReceiver(NetworkManager.c2s(), messageType.getId(), transformers, receiver);
return messageType;
}
}

View File

@@ -19,8 +19,6 @@
package dev.architectury.networking.transformers;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.Minecraft;
import net.minecraft.network.protocol.Packet;
import net.minecraft.server.level.ServerPlayer;
@@ -41,7 +39,6 @@ public interface PacketSink {
};
}
@Environment(EnvType.CLIENT)
static PacketSink client() {
return packet -> {
if (Minecraft.getInstance().getConnection() != null) {

View File

@@ -19,15 +19,13 @@
package dev.architectury.networking.transformers;
import dev.architectury.event.events.client.ClientPlayerEvent;
import dev.architectury.event.events.common.PlayerEvent;
import dev.architectury.networking.NetworkManager;
import dev.architectury.networking.transformers.client.ClientSplitPacketTransformer;
import dev.architectury.utils.Env;
import dev.architectury.utils.EnvExecutor;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.network.RegistryFriendlyByteBuf;
import net.minecraft.resources.ResourceLocation;
import org.apache.logging.log4j.LogManager;
@@ -46,47 +44,17 @@ public class SplitPacketTransformer implements PacketTransformer {
private static final byte END = 0x2;
private static final byte ONLY = 0x3;
private static class PartKey {
private final NetworkManager.Side side;
@Nullable
private final UUID playerUUID;
public PartKey(NetworkManager.Side side, @Nullable UUID playerUUID) {
this.side = side;
this.playerUUID = playerUUID;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof PartKey)) return false;
PartKey key = (PartKey) o;
return side == key.side && Objects.equals(playerUUID, key.playerUUID);
}
@Override
public int hashCode() {
return Objects.hash(side, playerUUID);
}
@Override
public String toString() {
return "PartKey{" +
"side=" + side +
", playerUUID=" + playerUUID +
'}';
}
@ApiStatus.Internal
public record PartKey(NetworkManager.Side side, @Nullable UUID playerUUID) {
}
private static class PartData {
private final ResourceLocation id;
private final int partsExpected;
private final List<RegistryFriendlyByteBuf> parts;
public PartData(ResourceLocation id, int partsExpected) {
this.id = id;
this.partsExpected = partsExpected;
this.parts = new ArrayList<>();
public record PartData(
ResourceLocation id,
int partsExpected,
List<RegistryFriendlyByteBuf> parts
) {
private PartData(ResourceLocation id, int partsExpected) {
this(id, partsExpected, new ArrayList<>());
}
}
@@ -96,16 +64,7 @@ public class SplitPacketTransformer implements PacketTransformer {
PlayerEvent.PLAYER_QUIT.register(player -> {
cache.keySet().removeIf(key -> Objects.equals(key.playerUUID, player.getUUID()));
});
EnvExecutor.runInEnv(Env.CLIENT, () -> new Client()::init);
}
private class Client {
@Environment(EnvType.CLIENT)
private void init() {
ClientPlayerEvent.CLIENT_PLAYER_QUIT.register(player -> {
cache.keySet().removeIf(key -> key.side == NetworkManager.Side.S2C);
});
}
EnvExecutor.runInEnv(Env.CLIENT, () -> () -> ClientSplitPacketTransformer.init(cache));
}
@Override
@@ -204,7 +163,7 @@ public class SplitPacketTransformer implements PacketTransformer {
buf.skipBytes(next);
sink.accept(side, id, packetBuffer);
}
buf.release();
}
}

View File

@@ -17,25 +17,18 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package dev.architectury.networking.simple;
package dev.architectury.networking.transformers.client;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.Minecraft;
import dev.architectury.event.events.client.ClientPlayerEvent;
import dev.architectury.networking.NetworkManager;
import dev.architectury.networking.transformers.SplitPacketTransformer;
/**
* The base class for client -&gt; server messages managed by a {@link SimpleNetworkManager}.
*/
public abstract class BaseC2SMessage extends Message {
/**
* Sends this message to the server.
*/
@Environment(EnvType.CLIENT)
public final void sendToServer() {
if (Minecraft.getInstance().getConnection() != null) {
Minecraft.getInstance().getConnection().send(toPacket(Minecraft.getInstance().level.registryAccess()));
} else {
throw new IllegalStateException("Unable to send packet to the server while not in game!");
}
import java.util.Map;
public class ClientSplitPacketTransformer {
public static void init(Map<SplitPacketTransformer.PartKey, SplitPacketTransformer.PartData> cache) {
ClientPlayerEvent.CLIENT_PLAYER_QUIT.register(player -> {
cache.keySet().removeIf(key -> key.side() == NetworkManager.Side.S2C);
});
}
}

View File

@@ -19,9 +19,6 @@
package dev.architectury.platform;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.gui.screens.Screen;
import org.jetbrains.annotations.Nullable;
import java.nio.file.Path;
@@ -80,13 +77,4 @@ public interface Mod {
Optional<String> getSources();
Optional<String> getIssueTracker();
@Environment(EnvType.CLIENT)
void registerConfigurationScreen(ConfigurationScreenProvider provider);
@Environment(EnvType.CLIENT)
@FunctionalInterface
interface ConfigurationScreenProvider {
Screen provide(Screen parent);
}
}

View File

@@ -17,5 +17,20 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
@Deprecated(forRemoval = true)
package dev.architectury.networking.simple;
package dev.architectury.platform.client;
import dev.architectury.injectables.annotations.ExpectPlatform;
import dev.architectury.platform.Mod;
import net.minecraft.client.gui.screens.Screen;
public class ConfigurationScreenRegistry {
@ExpectPlatform
public static void register(Mod mod, ConfigurationScreenProvider provider) {
throw new AssertionError();
}
@FunctionalInterface
public interface ConfigurationScreenProvider {
Screen provide(Screen parent);
}
}

View File

@@ -20,8 +20,6 @@
package dev.architectury.registry.client.gui;
import dev.architectury.injectables.annotations.ExpectPlatform;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.gui.screens.inventory.tooltip.ClientTooltipComponent;
import net.minecraft.world.inventory.tooltip.TooltipComponent;
@@ -30,7 +28,6 @@ import java.util.function.Function;
/**
* Registry for {@link ClientTooltipComponent} factories
*/
@Environment(EnvType.CLIENT)
public final class ClientTooltipComponentRegistry {
private ClientTooltipComponentRegistry() {
}

View File

@@ -0,0 +1,62 @@
/*
* This file is part of architectury.
* Copyright (C) 2020, 2021, 2022 architectury
*
* 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 dev.architectury.registry.client.gui;
import dev.architectury.injectables.annotations.ExpectPlatform;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.gui.screens.inventory.MenuAccess;
import net.minecraft.network.chat.Component;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.inventory.MenuType;
public class MenuScreenRegistry {
/**
* Registers a Screen Factory on the client to display.
*
* @param type The {@link MenuType} the screen visualizes
* @param factory A functional interface that is used to create new {@link Screen}s
* @param <H> The type of {@link AbstractContainerMenu} for the screen
* @param <S> The type for the {@link Screen}
*/
@ExpectPlatform
public static <H extends AbstractContainerMenu, S extends Screen & MenuAccess<H>> void registerScreenFactory(MenuType<? extends H> type, ScreenFactory<H, S> factory) {
throw new AssertionError();
}
/**
* Creates new screens.
*
* @param <H> The type of {@link AbstractContainerMenu} for the screen
* @param <S> The type for the {@link Screen}
*/
@FunctionalInterface
public interface ScreenFactory<H extends AbstractContainerMenu, S extends Screen & MenuAccess<H>> {
/**
* Creates a new {@link S} that extends {@link Screen}
*
* @param containerMenu The {@link AbstractContainerMenu} that controls the game logic for the screen
* @param inventory The {@link Inventory} for the screen
* @param component The {@link Component} for the screen
* @return A new {@link S} that extends {@link Screen}
*/
S create(H containerMenu, Inventory inventory, Component component);
}
}

View File

@@ -20,11 +20,8 @@
package dev.architectury.registry.client.keymappings;
import dev.architectury.injectables.annotations.ExpectPlatform;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.KeyMapping;
@Environment(EnvType.CLIENT)
public final class KeyMappingRegistry {
private KeyMappingRegistry() {
}

View File

@@ -20,14 +20,11 @@
package dev.architectury.registry.client.level.entity;
import dev.architectury.injectables.annotations.ExpectPlatform;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.model.geom.ModelLayerLocation;
import net.minecraft.client.model.geom.builders.LayerDefinition;
import java.util.function.Supplier;
@Environment(EnvType.CLIENT)
public class EntityModelLayerRegistry {
@ExpectPlatform
public static void register(ModelLayerLocation location, Supplier<LayerDefinition> definition) {

View File

@@ -20,15 +20,12 @@
package dev.architectury.registry.client.level.entity;
import dev.architectury.injectables.annotations.ExpectPlatform;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.renderer.entity.EntityRendererProvider;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
import java.util.function.Supplier;
@Environment(EnvType.CLIENT)
public final class EntityRendererRegistry {
private EntityRendererRegistry() {
}

View File

@@ -20,10 +20,7 @@
package dev.architectury.registry.client.particle;
import dev.architectury.event.events.client.ClientLifecycleEvent;
import dev.architectury.injectables.annotations.ExpectPlatform;
import dev.architectury.registry.registries.RegistrySupplier;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.particle.ParticleProvider;
import net.minecraft.client.particle.SpriteSet;
import net.minecraft.client.renderer.texture.TextureAtlas;
@@ -44,7 +41,6 @@ import java.util.List;
* or use the helper methods {@link #register(RegistrySupplier, ParticleProvider)} and {@link #register(RegistrySupplier, DeferredParticleProvider)},
* which will automatically handle the listening for you.
*/
@Environment(EnvType.CLIENT)
public final class ParticleProviderRegistry {
public interface ExtendedSpriteSet extends SpriteSet {
TextureAtlas getAtlas();

View File

@@ -20,19 +20,17 @@
package dev.architectury.registry.client.rendering;
import dev.architectury.injectables.annotations.ExpectPlatform;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider;
import net.minecraft.client.renderer.blockentity.state.BlockEntityRenderState;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType;
@Environment(EnvType.CLIENT)
public final class BlockEntityRendererRegistry {
private BlockEntityRendererRegistry() {
}
@ExpectPlatform
public static <T extends BlockEntity> void register(BlockEntityType<T> type, BlockEntityRendererProvider<? super T> provider) {
public static <E extends BlockEntity, S extends BlockEntityRenderState> void register(BlockEntityType<E> type, BlockEntityRendererProvider<? super E, ? super S> provider) {
throw new AssertionError();
}
}

View File

@@ -20,15 +20,12 @@
package dev.architectury.registry.client.rendering;
import dev.architectury.injectables.annotations.ExpectPlatform;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.color.block.BlockColor;
import net.minecraft.world.level.block.Block;
import java.util.Objects;
import java.util.function.Supplier;
@Environment(EnvType.CLIENT)
public final class ColorHandlerRegistry {
private ColorHandlerRegistry() {
}

View File

@@ -20,13 +20,10 @@
package dev.architectury.registry.client.rendering;
import dev.architectury.injectables.annotations.ExpectPlatform;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.renderer.chunk.ChunkSectionLayer;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.material.Fluid;
@Environment(EnvType.CLIENT)
public final class RenderTypeRegistry {
private RenderTypeRegistry() {
}

View File

@@ -20,10 +20,7 @@
package dev.architectury.registry.menu;
import dev.architectury.injectables.annotations.ExpectPlatform;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.gui.screens.inventory.MenuAccess;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerPlayer;
@@ -38,6 +35,7 @@ import java.util.function.Consumer;
/**
* A utility class to register {@link MenuType}s and {@link Screen}s for containers
* @see dev.architectury.registry.client.gui.MenuScreenRegistry
*/
public final class MenuRegistry {
private MenuRegistry() {
@@ -117,40 +115,6 @@ public final class MenuRegistry {
throw new AssertionError();
}
/**
* Registers a Screen Factory on the client to display.
*
* @param type The {@link MenuType} the screen visualizes
* @param factory A functional interface that is used to create new {@link Screen}s
* @param <H> The type of {@link AbstractContainerMenu} for the screen
* @param <S> The type for the {@link Screen}
*/
@Environment(EnvType.CLIENT)
@ExpectPlatform
public static <H extends AbstractContainerMenu, S extends Screen & MenuAccess<H>> void registerScreenFactory(MenuType<? extends H> type, ScreenFactory<H, S> factory) {
throw new AssertionError();
}
/**
* Creates new screens.
*
* @param <H> The type of {@link AbstractContainerMenu} for the screen
* @param <S> The type for the {@link Screen}
*/
@Environment(EnvType.CLIENT)
@FunctionalInterface
public interface ScreenFactory<H extends AbstractContainerMenu, S extends Screen & MenuAccess<H>> {
/**
* Creates a new {@link S} that extends {@link Screen}
*
* @param containerMenu The {@link AbstractContainerMenu} that controls the game logic for the screen
* @param inventory The {@link Inventory} for the screen
* @param component The {@link Component} for the screen
* @return A new {@link S} that extends {@link Screen}
*/
S create(H containerMenu, Inventory inventory, Component component);
}
/**
* Creates simple menus.
*

View File

@@ -20,18 +20,10 @@
package dev.architectury.utils;
import dev.architectury.injectables.annotations.ExpectPlatform;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.Minecraft;
import net.minecraft.server.MinecraftServer;
import org.jetbrains.annotations.Nullable;
public final class GameInstance {
@Environment(EnvType.CLIENT)
public static Minecraft getClient() {
return Minecraft.getInstance();
}
@Nullable
@ExpectPlatform
public static MinecraftServer getServer() {

View File

@@ -120,16 +120,12 @@ transitive-accessible method net/minecraft/client/renderer/RenderType create (Lj
transitive-accessible class net/minecraft/client/renderer/RenderType$CompositeState
transitive-accessible class net/minecraft/client/renderer/RenderType$CompositeRenderType
transitive-accessible class net/minecraft/client/renderer/RenderType$OutlineProperty
accessible class net/minecraft/client/resources/model/AtlasSet$AtlasEntry
accessible field net/minecraft/world/item/SpawnEggItem BY_ID Ljava/util/Map;
accessible field net/minecraft/world/item/SpawnEggItem defaultType Lnet/minecraft/world/entity/EntityType;
mutable field net/minecraft/world/item/SpawnEggItem defaultType Lnet/minecraft/world/entity/EntityType;
accessible field net/minecraft/client/particle/ParticleEngine textureAtlas Lnet/minecraft/client/renderer/texture/TextureAtlas;
accessible class net/minecraft/client/particle/ParticleEngine$MutableSpriteSet
accessible field net/minecraft/client/particle/ParticleEngine$MutableSpriteSet sprites Ljava/util/List;
accessible class net/minecraft/client/particle/ParticleResources$MutableSpriteSet
accessible field net/minecraft/client/particle/ParticleResources$MutableSpriteSet sprites Ljava/util/List;
transitive-accessible class net/minecraft/world/item/CreativeModeTab$Output
transitive-accessible class net/minecraft/world/item/CreativeModeTab$TabVisibility
accessible field net/minecraft/client/multiplayer/MultiPlayerGameMode connection Lnet/minecraft/client/multiplayer/ClientPacketListener;
accessible field net/minecraft/client/Minecraft particleResources Lnet/minecraft/client/particle/ParticleResources;
##############################
# This section is generated automatically with Gradle task generateAccessWidener!!!
@@ -154,7 +150,7 @@ transitive-accessible method net/minecraft/world/level/block/CakeBlock <init> (L
transitive-accessible method net/minecraft/world/level/block/CandleCakeBlock <init> (Lnet/minecraft/world/level/block/Block;Lnet/minecraft/world/level/block/state/BlockBehaviour$Properties;)V
transitive-accessible method net/minecraft/world/level/block/CartographyTableBlock <init> (Lnet/minecraft/world/level/block/state/BlockBehaviour$Properties;)V
transitive-accessible method net/minecraft/world/level/block/CarvedPumpkinBlock <init> (Lnet/minecraft/world/level/block/state/BlockBehaviour$Properties;)V
transitive-accessible method net/minecraft/world/level/block/ChestBlock <init> (Ljava/util/function/Supplier;Lnet/minecraft/world/level/block/state/BlockBehaviour$Properties;)V
transitive-accessible method net/minecraft/world/level/block/ChestBlock <init> (Ljava/util/function/Supplier;Lnet/minecraft/sounds/SoundEvent;Lnet/minecraft/sounds/SoundEvent;Lnet/minecraft/world/level/block/state/BlockBehaviour$Properties;)V
transitive-accessible method net/minecraft/world/level/block/ChorusFlowerBlock <init> (Lnet/minecraft/world/level/block/Block;Lnet/minecraft/world/level/block/state/BlockBehaviour$Properties;)V
transitive-accessible method net/minecraft/world/level/block/ChorusPlantBlock <init> (Lnet/minecraft/world/level/block/state/BlockBehaviour$Properties;)V
transitive-accessible method net/minecraft/world/level/block/CoralFanBlock <init> (Lnet/minecraft/world/level/block/Block;Lnet/minecraft/world/level/block/state/BlockBehaviour$Properties;)V
@@ -174,7 +170,6 @@ transitive-accessible method net/minecraft/world/level/block/EndPortalBlock <ini
transitive-accessible method net/minecraft/world/level/block/EndRodBlock <init> (Lnet/minecraft/world/level/block/state/BlockBehaviour$Properties;)V
transitive-accessible method net/minecraft/world/level/block/EnderChestBlock <init> (Lnet/minecraft/world/level/block/state/BlockBehaviour$Properties;)V
transitive-accessible method net/minecraft/world/level/block/FarmBlock <init> (Lnet/minecraft/world/level/block/state/BlockBehaviour$Properties;)V
transitive-accessible method net/minecraft/world/level/block/FletchingTableBlock <init> (Lnet/minecraft/world/level/block/state/BlockBehaviour$Properties;)V
transitive-accessible method net/minecraft/world/level/block/FlowerBedBlock <init> (Lnet/minecraft/world/level/block/state/BlockBehaviour$Properties;)V
transitive-accessible method net/minecraft/world/level/block/FungusBlock <init> (Lnet/minecraft/resources/ResourceKey;Lnet/minecraft/world/level/block/Block;Lnet/minecraft/world/level/block/state/BlockBehaviour$Properties;)V
transitive-accessible method net/minecraft/world/level/block/FurnaceBlock <init> (Lnet/minecraft/world/level/block/state/BlockBehaviour$Properties;)V
@@ -230,9 +225,13 @@ transitive-accessible method net/minecraft/world/level/block/WallSkullBlock <ini
transitive-accessible method net/minecraft/world/level/block/WallTorchBlock <init> (Lnet/minecraft/core/particles/SimpleParticleType;Lnet/minecraft/world/level/block/state/BlockBehaviour$Properties;)V
transitive-accessible method net/minecraft/world/level/block/WaterlilyBlock <init> (Lnet/minecraft/world/level/block/state/BlockBehaviour$Properties;)V
transitive-accessible method net/minecraft/world/level/block/WaterloggedTransparentBlock <init> (Lnet/minecraft/world/level/block/state/BlockBehaviour$Properties;)V
transitive-accessible method net/minecraft/world/level/block/WeatheringCopperBarsBlock <init> (Lnet/minecraft/world/level/block/WeatheringCopper$WeatherState;Lnet/minecraft/world/level/block/state/BlockBehaviour$Properties;)V
transitive-accessible method net/minecraft/world/level/block/WeatheringCopperChainBlock <init> (Lnet/minecraft/world/level/block/WeatheringCopper$WeatherState;Lnet/minecraft/world/level/block/state/BlockBehaviour$Properties;)V
transitive-accessible method net/minecraft/world/level/block/WeatheringCopperDoorBlock <init> (Lnet/minecraft/world/level/block/state/properties/BlockSetType;Lnet/minecraft/world/level/block/WeatheringCopper$WeatherState;Lnet/minecraft/world/level/block/state/BlockBehaviour$Properties;)V
transitive-accessible method net/minecraft/world/level/block/WeatheringCopperGrateBlock <init> (Lnet/minecraft/world/level/block/WeatheringCopper$WeatherState;Lnet/minecraft/world/level/block/state/BlockBehaviour$Properties;)V
transitive-accessible method net/minecraft/world/level/block/WeatheringCopperTrapDoorBlock <init> (Lnet/minecraft/world/level/block/state/properties/BlockSetType;Lnet/minecraft/world/level/block/WeatheringCopper$WeatherState;Lnet/minecraft/world/level/block/state/BlockBehaviour$Properties;)V
transitive-accessible method net/minecraft/world/level/block/WeatheringLanternBlock <init> (Lnet/minecraft/world/level/block/WeatheringCopper$WeatherState;Lnet/minecraft/world/level/block/state/BlockBehaviour$Properties;)V
transitive-accessible method net/minecraft/world/level/block/WeatheringLightningRodBlock <init> (Lnet/minecraft/world/level/block/WeatheringCopper$WeatherState;Lnet/minecraft/world/level/block/state/BlockBehaviour$Properties;)V
transitive-accessible method net/minecraft/world/level/block/WeightedPressurePlateBlock <init> (ILnet/minecraft/world/level/block/state/properties/BlockSetType;Lnet/minecraft/world/level/block/state/BlockBehaviour$Properties;)V
transitive-accessible method net/minecraft/world/level/block/WetSpongeBlock <init> (Lnet/minecraft/world/level/block/state/BlockBehaviour$Properties;)V
transitive-accessible method net/minecraft/world/level/block/WitherSkullBlock <init> (Lnet/minecraft/world/level/block/state/BlockBehaviour$Properties;)V
@@ -256,8 +255,6 @@ transitive-accessible field net/minecraft/client/renderer/RenderStateShard VIEW_
transitive-accessible field net/minecraft/client/renderer/RenderStateShard VIEW_OFFSET_Z_LAYERING_FORWARD Lnet/minecraft/client/renderer/RenderStateShard$LayeringStateShard;
transitive-accessible field net/minecraft/client/renderer/RenderStateShard MAIN_TARGET Lnet/minecraft/client/renderer/RenderStateShard$OutputStateShard;
transitive-accessible field net/minecraft/client/renderer/RenderStateShard OUTLINE_TARGET Lnet/minecraft/client/renderer/RenderStateShard$OutputStateShard;
transitive-accessible field net/minecraft/client/renderer/RenderStateShard TRANSLUCENT_TARGET Lnet/minecraft/client/renderer/RenderStateShard$OutputStateShard;
transitive-accessible field net/minecraft/client/renderer/RenderStateShard PARTICLES_TARGET Lnet/minecraft/client/renderer/RenderStateShard$OutputStateShard;
transitive-accessible field net/minecraft/client/renderer/RenderStateShard WEATHER_TARGET Lnet/minecraft/client/renderer/RenderStateShard$OutputStateShard;
transitive-accessible field net/minecraft/client/renderer/RenderStateShard ITEM_ENTITY_TARGET Lnet/minecraft/client/renderer/RenderStateShard$OutputStateShard;
transitive-accessible field net/minecraft/client/renderer/RenderStateShard DEFAULT_LINE Lnet/minecraft/client/renderer/RenderStateShard$LineStateShard;
@@ -304,6 +301,7 @@ transitive-accessible field net/minecraft/client/renderer/RenderPipelines PARTIC
transitive-accessible field net/minecraft/client/renderer/RenderPipelines WEATHER_SNIPPET Lcom/mojang/blaze3d/pipeline/RenderPipeline$Snippet;
transitive-accessible field net/minecraft/client/renderer/RenderPipelines GUI_SNIPPET Lcom/mojang/blaze3d/pipeline/RenderPipeline$Snippet;
transitive-accessible field net/minecraft/client/renderer/RenderPipelines GUI_TEXTURED_SNIPPET Lcom/mojang/blaze3d/pipeline/RenderPipeline$Snippet;
transitive-accessible field net/minecraft/client/renderer/RenderPipelines GUI_TEXT_SNIPPET Lcom/mojang/blaze3d/pipeline/RenderPipeline$Snippet;
transitive-accessible field net/minecraft/client/renderer/RenderPipelines OUTLINE_SNIPPET Lcom/mojang/blaze3d/pipeline/RenderPipeline$Snippet;
# CreativeModeTabs fields

View File

@@ -113,7 +113,7 @@ unifiedPublishing {
displayName = "[Fabric $rootProject.supported_version] v$project.version"
releaseType = "$rootProject.artifact_type"
changelog = releaseChangelog()
gameVersions = ["1.21.8"]
gameVersions = ["1.21.9"]
gameLoaders = ["fabric"]
mainPublication renameJarForPublication
relations {

View File

@@ -22,7 +22,7 @@ package dev.architectury.compat.fabric;
import com.google.common.collect.Maps;
import com.terraformersmc.modmenu.api.ConfigScreenFactory;
import com.terraformersmc.modmenu.api.ModMenuApi;
import dev.architectury.platform.fabric.PlatformImpl;
import dev.architectury.platform.client.fabric.ConfigurationScreenRegistryImpl;
import java.util.Map;
@@ -36,7 +36,7 @@ public class ModMenuCompatibility implements ModMenuApi {
}
private void validateMap() {
for (var entry : PlatformImpl.CONFIG_SCREENS.entrySet()) {
for (var entry : ConfigurationScreenRegistryImpl.CONFIG_SCREENS.entrySet()) {
if (!FACTORIES.containsKey(entry.getKey())) {
FACTORIES.put(entry.getKey(), entry.getValue()::provide);
}

View File

@@ -27,7 +27,6 @@ import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.client.render.fluid.v1.FluidRenderHandler;
import net.fabricmc.fabric.api.transfer.v1.client.fluid.FluidVariantRenderHandler;
import net.fabricmc.fabric.api.transfer.v1.fluid.FluidVariant;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.texture.TextureAtlas;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.core.BlockPos;
@@ -36,12 +35,10 @@ import net.minecraft.world.level.BlockAndTintGetter;
import net.minecraft.world.level.material.FluidState;
import org.jetbrains.annotations.Nullable;
import java.util.function.Function;
@SuppressWarnings("UnstableApiUsage")
@Environment(EnvType.CLIENT)
class ArchitecturyFluidRenderingFabric implements FluidVariantRenderHandler, FluidRenderHandler {
private final ArchitecturyFluidAttributes attributes;
private TextureAtlas atlas = null;
private final TextureAtlasSprite[] sprites = new TextureAtlasSprite[2];
private final TextureAtlasSprite[] spritesOverlaid = new TextureAtlasSprite[3];
private final TextureAtlasSprite[] spritesOther = new TextureAtlasSprite[2];
@@ -55,12 +52,11 @@ class ArchitecturyFluidRenderingFabric implements FluidVariantRenderHandler, Flu
@Nullable
public TextureAtlasSprite[] getSprites(FluidVariant variant) {
FluidStack stack = FluidStackHooksFabric.fromFabric(variant, FluidStack.bucketAmount());
Function<ResourceLocation, TextureAtlasSprite> atlas = Minecraft.getInstance().getTextureAtlas(TextureAtlas.LOCATION_BLOCKS);
ResourceLocation overlayTexture = attributes.getOverlayTexture(stack);
TextureAtlasSprite overlaySprite = overlayTexture == null ? null : atlas.apply(overlayTexture);
TextureAtlasSprite overlaySprite = overlayTexture == null ? null : atlas.getSprite(overlayTexture);
TextureAtlasSprite[] sprites = overlaySprite == null ? this.sprites : spritesOverlaid;
sprites[0] = atlas.apply(attributes.getSourceTexture(stack));
sprites[1] = atlas.apply(attributes.getFlowingTexture(stack));
sprites[0] = atlas.getSprite(attributes.getSourceTexture(stack));
sprites[1] = atlas.getSprite(attributes.getFlowingTexture(stack));
if (overlaySprite != null) sprites[2] = overlaySprite;
return sprites;
}
@@ -72,12 +68,11 @@ class ArchitecturyFluidRenderingFabric implements FluidVariantRenderHandler, Flu
@Override
public TextureAtlasSprite[] getFluidSprites(@Nullable BlockAndTintGetter view, @Nullable BlockPos pos, FluidState state) {
Function<ResourceLocation, TextureAtlasSprite> atlas = Minecraft.getInstance().getTextureAtlas(TextureAtlas.LOCATION_BLOCKS);
ResourceLocation overlayTexture = attributes.getOverlayTexture(state, view, pos);
TextureAtlasSprite overlaySprite = overlayTexture == null ? null : atlas.apply(overlayTexture);
TextureAtlasSprite overlaySprite = overlayTexture == null ? null : atlas.getSprite(overlayTexture);
TextureAtlasSprite[] sprites = overlaySprite == null ? this.spritesOther : spritesOtherOverlaid;
sprites[0] = atlas.apply(attributes.getSourceTexture(state, view, pos));
sprites[1] = atlas.apply(attributes.getFlowingTexture(state, view, pos));
sprites[0] = atlas.getSprite(attributes.getSourceTexture(state, view, pos));
sprites[1] = atlas.getSprite(attributes.getFlowingTexture(state, view, pos));
if (overlaySprite != null) sprites[2] = overlaySprite;
return sprites;
}
@@ -86,4 +81,9 @@ class ArchitecturyFluidRenderingFabric implements FluidVariantRenderHandler, Flu
public int getFluidColor(@Nullable BlockAndTintGetter view, @Nullable BlockPos pos, FluidState state) {
return attributes.getColor(state, view, pos);
}
@Override
public void reloadTextures(TextureAtlas atlas) {
this.atlas = atlas;
}
}

View File

@@ -0,0 +1,97 @@
/*
* This file is part of architectury.
* Copyright (C) 2020, 2021, 2022 architectury
*
* 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 dev.architectury.hooks.client.fluid.fabric;
import dev.architectury.fluid.FluidStack;
import dev.architectury.hooks.fluid.fabric.FluidStackHooksFabric;
import net.fabricmc.fabric.api.client.render.fluid.v1.FluidRenderHandlerRegistry;
import net.fabricmc.fabric.api.transfer.v1.client.fluid.FluidVariantRendering;
import net.fabricmc.fabric.api.transfer.v1.fluid.FluidVariant;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.BlockAndTintGetter;
import net.minecraft.world.level.material.Fluid;
import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.level.material.Fluids;
import org.jetbrains.annotations.Nullable;
public class ClientFluidStackHooksImpl {
@Nullable
public static TextureAtlasSprite getStillTexture(@Nullable BlockAndTintGetter level, @Nullable BlockPos pos, FluidState state) {
if (state.getType() == Fluids.EMPTY) return null;
var handler = FluidRenderHandlerRegistry.INSTANCE.get(state.getType());
if (handler == null) return null;
var sprites = handler.getFluidSprites(level, pos, state);
if (sprites == null) return null;
return sprites[0];
}
@Nullable
public static TextureAtlasSprite getStillTexture(FluidStack stack) {
var sprites = FluidVariantRendering.getSprites(FluidStackHooksFabric.toFabric(stack));
return sprites == null ? null : sprites[0];
}
@Nullable
public static TextureAtlasSprite getStillTexture(Fluid fluid) {
var sprites = FluidVariantRendering.getSprites(FluidVariant.of(fluid));
return sprites == null ? null : sprites[0];
}
@Nullable
public static TextureAtlasSprite getFlowingTexture(@Nullable BlockAndTintGetter level, @Nullable BlockPos pos, FluidState state) {
if (state.getType() == Fluids.EMPTY) return null;
var handler = FluidRenderHandlerRegistry.INSTANCE.get(state.getType());
if (handler == null) return null;
var sprites = handler.getFluidSprites(level, pos, state);
if (sprites == null) return null;
return sprites[1];
}
@Nullable
public static TextureAtlasSprite getFlowingTexture(FluidStack stack) {
var sprites = FluidVariantRendering.getSprites(FluidStackHooksFabric.toFabric(stack));
return sprites == null ? null : sprites[1];
}
@Nullable
public static TextureAtlasSprite getFlowingTexture(Fluid fluid) {
var sprites = FluidVariantRendering.getSprites(FluidVariant.of(fluid));
return sprites == null ? null : sprites[1];
}
public static int getColor(@Nullable BlockAndTintGetter level, @Nullable BlockPos pos, FluidState state) {
if (state.getType() == Fluids.EMPTY) return -1;
var handler = FluidRenderHandlerRegistry.INSTANCE.get(state.getType());
if (handler == null) return -1;
return handler.getFluidColor(level, pos, state);
}
public static int getColor(FluidStack stack) {
return FluidVariantRendering.getColor(FluidStackHooksFabric.toFabric(stack));
}
public static int getColor(Fluid fluid) {
if (fluid == Fluids.EMPTY) return -1;
var handler = FluidRenderHandlerRegistry.INSTANCE.get(fluid);
if (handler == null) return -1;
return handler.getFluidColor(null, null, fluid.defaultFluidState());
}
}

View File

@@ -21,14 +21,8 @@ package dev.architectury.hooks.fluid.fabric;
import com.mojang.logging.LogUtils;
import dev.architectury.fluid.FluidStack;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.client.render.fluid.v1.FluidRenderHandlerRegistry;
import net.fabricmc.fabric.api.transfer.v1.client.fluid.FluidVariantRendering;
import net.fabricmc.fabric.api.transfer.v1.fluid.FluidVariant;
import net.fabricmc.fabric.api.transfer.v1.fluid.FluidVariantAttributes;
import net.minecraft.Util;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.core.BlockPos;
import net.minecraft.core.HolderLookup;
import net.minecraft.core.registries.BuiltInRegistries;
@@ -37,11 +31,8 @@ import net.minecraft.nbt.NbtOps;
import net.minecraft.nbt.Tag;
import net.minecraft.network.RegistryFriendlyByteBuf;
import net.minecraft.network.chat.Component;
import net.minecraft.world.level.BlockAndTintGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.material.Fluid;
import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.level.material.Fluids;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
@@ -84,77 +75,6 @@ public class FluidStackHooksImpl {
return 81000;
}
@Environment(EnvType.CLIENT)
@Nullable
public static TextureAtlasSprite getStillTexture(@Nullable BlockAndTintGetter level, @Nullable BlockPos pos, FluidState state) {
if (state.getType() == Fluids.EMPTY) return null;
var handler = FluidRenderHandlerRegistry.INSTANCE.get(state.getType());
if (handler == null) return null;
var sprites = handler.getFluidSprites(level, pos, state);
if (sprites == null) return null;
return sprites[0];
}
@Environment(EnvType.CLIENT)
@Nullable
public static TextureAtlasSprite getStillTexture(FluidStack stack) {
var sprites = FluidVariantRendering.getSprites(FluidStackHooksFabric.toFabric(stack));
return sprites == null ? null : sprites[0];
}
@Environment(EnvType.CLIENT)
@Nullable
public static TextureAtlasSprite getStillTexture(Fluid fluid) {
var sprites = FluidVariantRendering.getSprites(FluidVariant.of(fluid));
return sprites == null ? null : sprites[0];
}
@Environment(EnvType.CLIENT)
@Nullable
public static TextureAtlasSprite getFlowingTexture(@Nullable BlockAndTintGetter level, @Nullable BlockPos pos, FluidState state) {
if (state.getType() == Fluids.EMPTY) return null;
var handler = FluidRenderHandlerRegistry.INSTANCE.get(state.getType());
if (handler == null) return null;
var sprites = handler.getFluidSprites(level, pos, state);
if (sprites == null) return null;
return sprites[1];
}
@Environment(EnvType.CLIENT)
@Nullable
public static TextureAtlasSprite getFlowingTexture(FluidStack stack) {
var sprites = FluidVariantRendering.getSprites(FluidStackHooksFabric.toFabric(stack));
return sprites == null ? null : sprites[1];
}
@Environment(EnvType.CLIENT)
@Nullable
public static TextureAtlasSprite getFlowingTexture(Fluid fluid) {
var sprites = FluidVariantRendering.getSprites(FluidVariant.of(fluid));
return sprites == null ? null : sprites[1];
}
@Environment(EnvType.CLIENT)
public static int getColor(@Nullable BlockAndTintGetter level, @Nullable BlockPos pos, FluidState state) {
if (state.getType() == Fluids.EMPTY) return -1;
var handler = FluidRenderHandlerRegistry.INSTANCE.get(state.getType());
if (handler == null) return -1;
return handler.getFluidColor(level, pos, state);
}
@Environment(EnvType.CLIENT)
public static int getColor(FluidStack stack) {
return FluidVariantRendering.getColor(FluidStackHooksFabric.toFabric(stack));
}
@Environment(EnvType.CLIENT)
public static int getColor(Fluid fluid) {
if (fluid == Fluids.EMPTY) return -1;
var handler = FluidRenderHandlerRegistry.INSTANCE.get(fluid);
if (handler == null) return -1;
return handler.getFluidColor(null, null, fluid.defaultFluidState());
}
public static int getLuminosity(FluidStack fluid, @Nullable Level level, @Nullable BlockPos pos) {
return FluidVariantAttributes.getLuminance(FluidStackHooksFabric.toFabric(fluid));
}

View File

@@ -22,6 +22,7 @@ package dev.architectury.impl.fabric;
import dev.architectury.event.events.client.ClientScreenInputEvent;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.input.CharacterEvent;
import net.minecraft.network.chat.Component;
public interface ScreenInputDelegate {
@@ -36,12 +37,12 @@ public interface ScreenInputDelegate {
}
@Override
public boolean charTyped(char c, int i) {
if (ClientScreenInputEvent.CHAR_TYPED_PRE.invoker().charTyped(Minecraft.getInstance(), parent, c, i).isPresent())
public boolean charTyped(CharacterEvent characterEvent) {
if (ClientScreenInputEvent.CHAR_TYPED_PRE.invoker().charTyped(Minecraft.getInstance(), parent, characterEvent).isPresent())
return true;
if (parent.charTyped(c, i))
if (parent.charTyped(characterEvent))
return true;
return ClientScreenInputEvent.CHAR_TYPED_POST.invoker().charTyped(Minecraft.getInstance(), parent, c, i).isPresent();
return ClientScreenInputEvent.CHAR_TYPED_POST.invoker().charTyped(Minecraft.getInstance(), parent, characterEvent).isPresent();
}
}
}

View File

@@ -21,7 +21,7 @@ package dev.architectury.init.fabric;
import dev.architectury.event.events.client.ClientLifecycleEvent;
import dev.architectury.event.events.common.LifecycleEvent;
import dev.architectury.networking.SpawnEntityPacket;
import dev.architectury.networking.ClientSpawnEntityPacket;
import net.minecraft.client.Minecraft;
public class ArchitecturyClient {
@@ -29,6 +29,6 @@ public class ArchitecturyClient {
LifecycleEvent.SETUP.invoker().run();
ClientLifecycleEvent.CLIENT_SETUP.invoker().stateChanged(Minecraft.getInstance());
SpawnEntityPacket.Client.register();
ClientSpawnEntityPacket.register();
}
}

View File

@@ -45,7 +45,7 @@ public abstract class MixinPhantomSpawner {
),
cancellable = true
)
private void checkPhantomSpawn(ServerLevel level, boolean bl, boolean bl2, CallbackInfo ci, @Local(ordinal = 1) BlockPos pos, @Local Phantom entity) {
private void checkPhantomSpawn(ServerLevel level, boolean bl, CallbackInfo ci, @Local(ordinal = 1) BlockPos pos, @Local Phantom entity) {
if (EntityEvent.LIVING_CHECK_SPAWN.invoker().canSpawn(entity, level, pos.getX(), pos.getY(), pos.getZ(), EntitySpawnReason.NATURAL, null).value() == Boolean.FALSE) {
ci.cancel();
}

View File

@@ -24,13 +24,14 @@ import dev.architectury.event.events.common.ExplosionEvent;
import dev.architectury.event.events.common.LifecycleEvent;
import dev.architectury.hooks.fabric.PersistentEntitySectionManagerHooks;
import net.minecraft.core.Holder;
import net.minecraft.core.particles.ExplosionParticleInfo;
import net.minecraft.core.particles.ParticleOptions;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.sounds.SoundEvent;
import net.minecraft.util.ProgressListener;
import net.minecraft.util.random.WeightedList;
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 net.minecraft.world.level.ServerExplosion;
@@ -61,9 +62,9 @@ public class MixinServerLevel {
((PersistentEntitySectionManagerHooks) this.entityManager).architectury_attachLevel((ServerLevel) (Object) this);
}
@Inject(method = "explode(Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/damagesource/DamageSource;Lnet/minecraft/world/level/ExplosionDamageCalculator;DDDFZLnet/minecraft/world/level/Level$ExplosionInteraction;Lnet/minecraft/core/particles/ParticleOptions;Lnet/minecraft/core/particles/ParticleOptions;Lnet/minecraft/core/Holder;)V",
at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/ServerExplosion;explode()V"), cancellable = true)
private void explodePre(Entity entity, DamageSource damageSource, ExplosionDamageCalculator explosionDamageCalculator, double d, double e, double f, float g, boolean bl, Level.ExplosionInteraction explosionInteraction, ParticleOptions particleOptions, ParticleOptions particleOptions2, Holder<SoundEvent> soundEvent, CallbackInfo ci, @Local Explosion.BlockInteraction blockInteraction, @Local ServerExplosion explosion) {
@Inject(method = "explode",
at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/ServerExplosion;explode()I"), cancellable = true)
private void explodePre(Entity entity, DamageSource damageSource, ExplosionDamageCalculator explosionDamageCalculator, double d, double e, double f, float g, boolean bl, Level.ExplosionInteraction explosionInteraction, ParticleOptions particleOptions, ParticleOptions particleOptions2, WeightedList<ExplosionParticleInfo> weightedList, Holder<SoundEvent> holder, CallbackInfo ci, @Local ServerExplosion explosion) {
if (ExplosionEvent.PRE.invoker().explode((Level) (Object) this, explosion).isFalse()) {
ci.cancel();
}

View File

@@ -20,23 +20,23 @@
package dev.architectury.mixin.fabric.client;
import dev.architectury.event.events.client.ClientGuiEvent;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.components.DebugScreenOverlay;
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.CallbackInfo;
import java.util.List;
@Mixin(DebugScreenOverlay.class)
public class MixinDebugScreenOverlay {
@Inject(method = "getGameInformation", at = @At("RETURN"))
private void getLeftTexts(CallbackInfoReturnable<List<String>> cir) {
ClientGuiEvent.DEBUG_TEXT_LEFT.invoker().gatherText(cir.getReturnValue());
}
@Inject(method = "getSystemInformation", at = @At("RETURN"))
private void getRightTexts(CallbackInfoReturnable<List<String>> cir) {
ClientGuiEvent.DEBUG_TEXT_RIGHT.invoker().gatherText(cir.getReturnValue());
@Inject(method = "renderLines", at = @At("RETURN"))
private void getLeftTexts(GuiGraphics guiGraphics, List<String> list, boolean bl, CallbackInfo ci) {
if (bl) {
ClientGuiEvent.DEBUG_TEXT_LEFT.invoker().gatherText(list);
} else {
ClientGuiEvent.DEBUG_TEXT_RIGHT.invoker().gatherText(list);
}
}
}

View File

@@ -19,41 +19,25 @@
package dev.architectury.mixin.fabric.client;
import com.llamalad7.mixinextras.sugar.Local;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import dev.architectury.event.events.client.ClientGuiEvent;
import net.minecraft.client.DeltaTracker;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.renderer.GameRenderer;
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;
@Mixin(value = GameRenderer.class, priority = 1100)
public abstract class MixinGameRenderer {
@Shadow
@Final
private Minecraft minecraft;
@Shadow
public abstract void tick();
@Inject(method = "render(Lnet/minecraft/client/DeltaTracker;Z)V",
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screens/Screen;renderWithTooltip(Lnet/minecraft/client/gui/GuiGraphics;IIF)V",
ordinal = 0), cancellable = true)
public void renderScreenPre(DeltaTracker tickDelta, boolean tick, CallbackInfo ci, @Local(ordinal = 0) int mouseX, @Local(ordinal = 1) int mouseY, @Local GuiGraphics graphics) {
if (ClientGuiEvent.RENDER_PRE.invoker().render(minecraft.screen, graphics, mouseX, mouseY, tickDelta).isFalse()) {
ci.cancel();
@WrapOperation(method = "render(Lnet/minecraft/client/DeltaTracker;Z)V",
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screens/Screen;renderWithTooltipAndSubtitles(Lnet/minecraft/client/gui/GuiGraphics;IIF)V",
ordinal = 0))
public void wrapRenderScreen(Screen screen, GuiGraphics graphics, int mouseX, int mouseY, float delta, Operation<Void> original) {
if (ClientGuiEvent.RENDER_PRE.invoker().render(screen, graphics, mouseX, mouseY, delta).isFalse()) {
return;
}
}
@Inject(method = "render(Lnet/minecraft/client/DeltaTracker;Z)V",
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screens/Screen;renderWithTooltip(Lnet/minecraft/client/gui/GuiGraphics;IIF)V",
shift = At.Shift.AFTER, ordinal = 0))
public void renderScreenPost(DeltaTracker tickDelta, boolean tick, CallbackInfo ci, @Local(ordinal = 0) int mouseX, @Local(ordinal = 1) int mouseY, @Local GuiGraphics graphics) {
ClientGuiEvent.RENDER_POST.invoker().render(minecraft.screen, graphics, mouseX, mouseY, tickDelta);
original.call(screen, graphics, mouseX, mouseY, delta);
ClientGuiEvent.RENDER_POST.invoker().render(screen, graphics, mouseX, mouseY, delta);
}
}

View File

@@ -27,6 +27,8 @@ import dev.architectury.impl.fabric.ScreenInputDelegate;
import net.minecraft.client.KeyboardHandler;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.input.CharacterEvent;
import net.minecraft.client.input.KeyEvent;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@@ -40,40 +42,40 @@ public class MixinKeyboardHandler {
@Final
private Minecraft minecraft;
@WrapOperation(method = "charTyped", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screens/Screen;charTyped(CI)Z"))
private boolean wrapCharTyped(Screen screen, char chr, int mods, Operation<Boolean> original) {
@WrapOperation(method = "charTyped", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screens/Screen;charTyped(Lnet/minecraft/client/input/CharacterEvent;)Z"))
private boolean wrapCharTyped(Screen screen, CharacterEvent characterEvent, Operation<Boolean> original) {
if (screen instanceof ScreenInputDelegate delegate) {
return original.call(delegate.architectury_delegateInputs(), chr, mods);
return original.call(delegate.architectury_delegateInputs(), characterEvent);
}
return original.call(screen, chr, mods);
return original.call(screen, characterEvent);
}
@WrapOperation(method = "keyPress", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screens/Screen;keyPressed(III)Z"))
private boolean wrapKeyPressed(Screen screen, int keyCode, int scanCode, int modifiers, Operation<Boolean> original) {
var result = ClientScreenInputEvent.KEY_PRESSED_PRE.invoker().keyPressed(minecraft, screen, keyCode, scanCode, modifiers);
@WrapOperation(method = "keyPress", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screens/Screen;keyPressed(Lnet/minecraft/client/input/KeyEvent;)Z"))
private boolean wrapKeyPressed(Screen screen, KeyEvent keyEvent, Operation<Boolean> original) {
var result = ClientScreenInputEvent.KEY_PRESSED_PRE.invoker().keyPressed(minecraft, screen, keyEvent);
if (result.isPresent())
return true;
if (original.call(screen, keyCode, scanCode, modifiers))
if (original.call(screen, keyEvent))
return true;
result = ClientScreenInputEvent.KEY_PRESSED_POST.invoker().keyPressed(minecraft, screen, keyCode, scanCode, modifiers);
result = ClientScreenInputEvent.KEY_PRESSED_POST.invoker().keyPressed(minecraft, screen, keyEvent);
return result.isPresent();
}
@WrapOperation(method = "keyPress", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screens/Screen;keyReleased(III)Z"))
private boolean wrapKeyReleased(Screen screen, int keyCode, int scanCode, int modifiers, Operation<Boolean> original) {
var result = ClientScreenInputEvent.KEY_RELEASED_PRE.invoker().keyReleased(minecraft, screen, keyCode, scanCode, modifiers);
@WrapOperation(method = "keyPress", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screens/Screen;keyReleased(Lnet/minecraft/client/input/KeyEvent;)Z"))
private boolean wrapKeyReleased(Screen screen, KeyEvent keyEvent, Operation<Boolean> original) {
var result = ClientScreenInputEvent.KEY_RELEASED_PRE.invoker().keyReleased(minecraft, screen, keyEvent);
if (result.isPresent())
return true;
if (original.call(screen, keyCode, scanCode, modifiers))
if (original.call(screen, keyEvent))
return true;
result = ClientScreenInputEvent.KEY_RELEASED_POST.invoker().keyReleased(minecraft, screen, keyCode, scanCode, modifiers);
result = ClientScreenInputEvent.KEY_RELEASED_POST.invoker().keyReleased(minecraft, screen, keyEvent);
return result.isPresent();
}
@Inject(method = "keyPress", at = @At("RETURN"), cancellable = true)
public void onRawKey(long handle, int key, int scanCode, int action, int modifiers, CallbackInfo info) {
if (handle == this.minecraft.getWindow().getWindow()) {
var result = ClientRawInputEvent.KEY_PRESSED.invoker().keyPressed(minecraft, key, scanCode, action, modifiers);
public void onRawKey(long handle, int key, KeyEvent keyEvent, CallbackInfo info) {
if (handle == this.minecraft.getWindow().handle()) {
var result = ClientRawInputEvent.KEY_PRESSED.invoker().keyPressed(minecraft, key, keyEvent);
if (result.isPresent())
info.cancel();
}

View File

@@ -27,13 +27,14 @@ import dev.architectury.event.events.client.ClientScreenInputEvent;
import net.minecraft.client.Minecraft;
import net.minecraft.client.MouseHandler;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.input.MouseButtonEvent;
import net.minecraft.client.input.MouseButtonInfo;
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(MouseHandler.class)
public class MixinMouseHandler {
@@ -41,15 +42,6 @@ public class MixinMouseHandler {
@Final
private Minecraft minecraft;
@Shadow
private int activeButton;
@Shadow
private double xpos;
@Shadow
private double ypos;
@WrapOperation(method = "onScroll", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screens/Screen;mouseScrolled(DDDD)Z", ordinal = 0))
private boolean onGuiMouseClicked(Screen instance, double mouseX, double mouseY, double amountX, double amountY, Operation<Boolean> original) {
var minecraft = Minecraft.getInstance();
@@ -66,8 +58,8 @@ public class MixinMouseHandler {
@Inject(method = "onScroll",
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/player/LocalPlayer;isSpectator()Z",
ordinal = 0), cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD)
public void onRawMouseScrolled(long handle, double xOffset, double yOffset, CallbackInfo info, boolean discreteMouseScroll, double mouseWheelSensitivity, double amountX, double doubleY) {
ordinal = 0), cancellable = true)
public void onRawMouseScrolled(long handle, double xOffset, double yOffset, CallbackInfo info, @Local(ordinal = 3) double amountX, @Local(ordinal = 4) double doubleY) {
if (!info.isCancelled()) {
var result = ClientRawInputEvent.MOUSE_SCROLLED.invoker().mouseScrolled(minecraft, amountX, doubleY);
if (result.isPresent())
@@ -75,68 +67,62 @@ public class MixinMouseHandler {
}
}
@WrapOperation(method = "onPress", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screens/Screen;mouseClicked(DDI)Z", ordinal = 0))
private boolean onGuiMouseClicked(Screen instance, double mouseX, double mouseY, int b, Operation<Boolean> original) {
var minecraft = Minecraft.getInstance();
var result = ClientScreenInputEvent.MOUSE_CLICKED_PRE.invoker().mouseClicked(minecraft, minecraft.screen, mouseX, mouseY, b);
@WrapOperation(method = "onButton", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screens/Screen;mouseClicked(Lnet/minecraft/client/input/MouseButtonEvent;Z)Z"))
private boolean wrapMouseClicked(Screen screen, MouseButtonEvent buttonEvent, boolean doubleClick, Operation<Boolean> original) {
var result = ClientScreenInputEvent.MOUSE_CLICKED_PRE.invoker().mouseClicked(minecraft, minecraft.screen, buttonEvent, doubleClick);
if (result.isPresent()) {
return true;
}
if (original.call(instance, mouseX, mouseY, b)) {
if (original.call(screen, buttonEvent, doubleClick)) {
return true;
}
result = ClientScreenInputEvent.MOUSE_CLICKED_POST.invoker().mouseClicked(minecraft, minecraft.screen, mouseX, mouseY, b);
result = ClientScreenInputEvent.MOUSE_CLICKED_POST.invoker().mouseClicked(minecraft, minecraft.screen, buttonEvent, doubleClick);
return result.isPresent();
}
@Inject(method = "onPress", at = @At(value = "INVOKE",
@Inject(method = "onButton", at = @At(value = "INVOKE",
target = "Lnet/minecraft/client/Minecraft;getOverlay()Lnet/minecraft/client/gui/screens/Overlay;",
ordinal = 0), cancellable = true)
public void onRawMouseClicked(long handle, int button, int action, int mods, CallbackInfo info) {
public void onRawMouseClicked(long handle, MouseButtonInfo buttonInfo, int action, CallbackInfo info) {
if (!info.isCancelled()) {
var result = ClientRawInputEvent.MOUSE_CLICKED_PRE.invoker().mouseClicked(minecraft, button, action, mods);
var result = ClientRawInputEvent.MOUSE_CLICKED_PRE.invoker().mouseClicked(minecraft, buttonInfo, action);
if (result.isPresent())
info.cancel();
}
}
@Inject(method = "onPress", at = @At("RETURN"), cancellable = true)
public void onRawMouseClickedPost(long handle, int button, int action, int mods, CallbackInfo info) {
if (handle == this.minecraft.getWindow().getWindow()) {
var result = ClientRawInputEvent.MOUSE_CLICKED_POST.invoker().mouseClicked(minecraft, button, action, mods);
@Inject(method = "onButton", at = @At("RETURN"), cancellable = true)
public void onRawMouseClickedPost(long handle, MouseButtonInfo buttonInfo, int action, CallbackInfo info) {
if (handle == this.minecraft.getWindow().handle()) {
var result = ClientRawInputEvent.MOUSE_CLICKED_POST.invoker().mouseClicked(minecraft, buttonInfo, action);
if (result.isPresent())
info.cancel();
}
}
@WrapOperation(method = "onPress", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screens/Screen;mouseReleased(DDI)Z", ordinal = 0))
private boolean onGuiMouseReleased(Screen instance, double mouseX, double mouseY, int b, Operation<Boolean> original) {
var minecraft = Minecraft.getInstance();
var result = ClientScreenInputEvent.MOUSE_RELEASED_PRE.invoker().mouseReleased(minecraft, minecraft.screen, mouseX, mouseY, b);
@WrapOperation(method = "onButton", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screens/Screen;mouseReleased(Lnet/minecraft/client/input/MouseButtonEvent;)Z"))
private boolean wrapMouseReleased(Screen screen, MouseButtonEvent buttonEvent, Operation<Boolean> original) {
var result = ClientScreenInputEvent.MOUSE_RELEASED_PRE.invoker().mouseReleased(minecraft, minecraft.screen, buttonEvent);
if (result.isPresent()) {
return true;
}
if (original.call(instance, mouseX, mouseY, b)) {
if (original.call(screen, buttonEvent)) {
return true;
}
result = ClientScreenInputEvent.MOUSE_RELEASED_POST.invoker().mouseReleased(minecraft, minecraft.screen, mouseX, mouseY, b);
result = ClientScreenInputEvent.MOUSE_RELEASED_POST.invoker().mouseReleased(minecraft, minecraft.screen, buttonEvent);
return result.isPresent();
}
@Inject(method = "handleAccumulatedMovement", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screens/Screen;mouseDragged(DDIDD)Z", ordinal = 0), cancellable = true)
private void onGuiMouseDraggedPre(CallbackInfo ci, @Local(ordinal = 2) double mouseX, @Local(ordinal = 3) double mouseY, @Local(ordinal = 4) double deltaX, @Local(ordinal = 5) double deltaY) {
if (ClientScreenInputEvent.MOUSE_DRAGGED_PRE.invoker().mouseDragged(Minecraft.getInstance(), Minecraft.getInstance().screen, mouseX, mouseY, this.activeButton, deltaX, deltaY).isPresent()) {
ci.cancel();
@WrapOperation(method = "handleAccumulatedMovement", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screens/Screen;mouseDragged(Lnet/minecraft/client/input/MouseButtonEvent;DD)Z"))
private boolean wrapMouseDragged(Screen screen, MouseButtonEvent event, double deltaX, double deltaY, Operation<Boolean> original) {
var result = ClientScreenInputEvent.MOUSE_DRAGGED_POST.invoker().mouseDragged(minecraft, screen, event, deltaX, deltaY);
if (result.isPresent()) {
return true;
}
}
@SuppressWarnings({"UnresolvedMixinReference", "DefaultAnnotationParam"})
@WrapOperation(method = "handleAccumulatedMovement", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screens/Screen;mouseDragged(DDIDD)Z"))
private boolean onGuiMouseDraggedPost(Screen screen, double mouseX, double mouseY, int button, double deltaX, double deltaY, Operation<Boolean> original) {
if (original.call(screen, mouseX, mouseY, button, deltaX, deltaY)) {
if (original.call(screen, event, deltaX, deltaY)) {
return true;
}
return ClientScreenInputEvent.MOUSE_DRAGGED_POST.invoker().mouseDragged(Minecraft.getInstance(), screen, mouseX, mouseY, button, deltaX, deltaY).isPresent();
return ClientScreenInputEvent.MOUSE_DRAGGED_POST.invoker().mouseDragged(Minecraft.getInstance(), screen, event, deltaX, deltaY).isPresent();
}
}

View File

@@ -0,0 +1,58 @@
/*
* This file is part of architectury.
* Copyright (C) 2020, 2021, 2022 architectury
*
* 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 dev.architectury.networking.client.fabric;
import com.mojang.logging.LogUtils;
import dev.architectury.networking.NetworkManager;
import dev.architectury.networking.fabric.NetworkManagerImpl;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
import net.fabricmc.fabric.api.networking.v1.PayloadTypeRegistry;
import net.minecraft.network.RegistryFriendlyByteBuf;
import net.minecraft.network.codec.StreamCodec;
import net.minecraft.network.protocol.common.custom.CustomPacketPayload;
import org.slf4j.Logger;
@Environment(EnvType.CLIENT)
public class ClientNetworkManagerImpl {
private static final Logger LOGGER = LogUtils.getLogger();
public static <T extends CustomPacketPayload> void registerS2C(CustomPacketPayload.Type<T> type, StreamCodec<? super RegistryFriendlyByteBuf, T> codec, NetworkManager.NetworkReceiver<T> receiver) {
LOGGER.info("Registering S2C receiver with id {}", type.id());
ClientPlayNetworking.registerGlobalReceiver(type, new ClientPlayPayloadHandler<>(receiver));
}
// Lambda methods aren't included in @EnvType, so this inelegant solution is used instead.
@Environment(EnvType.CLIENT)
static class ClientPlayPayloadHandler<T extends CustomPacketPayload> implements ClientPlayNetworking.PlayPayloadHandler<T> {
private final NetworkManager.NetworkReceiver<T> receiver;
ClientPlayPayloadHandler(NetworkManager.NetworkReceiver<T> receiver) {
this.receiver = receiver;
}
@Override
public void receive(T payload, ClientPlayNetworking.Context fabricContext) {
var context = NetworkManagerImpl.context(fabricContext.player(), fabricContext.client(), true);
receiver.receive(payload, context);
}
}
}

View File

@@ -24,12 +24,17 @@ import dev.architectury.impl.NetworkAggregator;
import dev.architectury.networking.NetworkManager;
import dev.architectury.networking.NetworkManager.NetworkReceiver;
import dev.architectury.networking.SpawnEntityPacket;
import dev.architectury.networking.client.fabric.ClientNetworkManagerImpl;
import dev.architectury.networking.transformers.PacketSink;
import dev.architectury.platform.Platform;
import dev.architectury.utils.Env;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
import net.fabricmc.fabric.api.networking.v1.PayloadTypeRegistry;
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.ClientPacketListener;
import net.minecraft.core.RegistryAccess;
import net.minecraft.network.RegistryFriendlyByteBuf;
import net.minecraft.network.codec.StreamCodec;
@@ -54,33 +59,16 @@ public class NetworkManagerImpl {
LOGGER.info("Registering C2S receiver with id {}", type.id());
PayloadTypeRegistry.playC2S().register(type, codec);
ServerPlayNetworking.registerGlobalReceiver(type, (payload, fabricContext) -> {
var context = context(fabricContext.player(), fabricContext.player().getServer(), false);
var context = context(fabricContext.player(), fabricContext.server(), false);
receiver.receive(payload, context);
});
}
@Override
@Environment(EnvType.CLIENT)
public <T extends CustomPacketPayload> void registerS2C(CustomPacketPayload.Type<T> type, StreamCodec<? super RegistryFriendlyByteBuf, T> codec, NetworkReceiver<T> receiver) {
LOGGER.info("Registering S2C receiver with id {}", type.id());
PayloadTypeRegistry.playS2C().register(type, codec);
ClientPlayNetworking.registerGlobalReceiver(type, new ClientPlayPayloadHandler<>(receiver));
}
// Lambda methods aren't included in @EnvType, so this inelegant solution is used instead.
@Environment(EnvType.CLIENT)
class ClientPlayPayloadHandler<T extends CustomPacketPayload> implements ClientPlayNetworking.PlayPayloadHandler<T> {
private final NetworkReceiver<T> receiver;
ClientPlayPayloadHandler(NetworkReceiver<T> receiver) {
this.receiver = receiver;
}
@Override
public void receive(T payload, ClientPlayNetworking.Context fabricContext) {
var context = context(fabricContext.player(), fabricContext.client(), true);
receiver.receive(payload, context);
}
if (Platform.getEnvironment() == Env.CLIENT)
ClientNetworkManagerImpl.registerS2C(type, codec, receiver);
}
@Override
@@ -100,7 +88,7 @@ public class NetworkManagerImpl {
};
}
private static NetworkManager.PacketContext context(Player player, BlockableEventLoop<?> taskQueue, boolean client) {
public static NetworkManager.PacketContext context(Player player, BlockableEventLoop<?> taskQueue, boolean client) {
return new NetworkManager.PacketContext() {
@Override
public Player getPlayer() {
@@ -133,6 +121,12 @@ public class NetworkManagerImpl {
return ServerPlayNetworking.canSend(player, id);
}
public static <T extends CustomPacketPayload> void sendToServer(T payload) {
ClientPacketListener connection = Minecraft.getInstance().getConnection();
if (connection == null) return;
NetworkManager.collectPackets(PacketSink.client(), NetworkManager.clientToServer(), payload, connection.registryAccess());
}
public static Packet<ClientGamePacketListener> createAddEntityPacket(Entity entity, ServerEntity serverEntity) {
return SpawnEntityPacket.create(entity, serverEntity);
}

View File

@@ -0,0 +1,36 @@
/*
* This file is part of architectury.
* Copyright (C) 2020, 2021, 2022 architectury
*
* 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 dev.architectury.platform.client.fabric;
import dev.architectury.platform.Mod;
import dev.architectury.platform.client.ConfigurationScreenRegistry.ConfigurationScreenProvider;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class ConfigurationScreenRegistryImpl {
public static final Map<String, ConfigurationScreenProvider> CONFIG_SCREENS = new ConcurrentHashMap<>();
public static void register(Mod mod, ConfigurationScreenProvider provider) {
if (CONFIG_SCREENS.containsKey(mod.getModId()))
throw new IllegalStateException("Can not register configuration screen for mod '" + mod.getModId() + "' because it was already registered!");
CONFIG_SCREENS.put(mod.getModId(), provider);
}
}

View File

@@ -37,7 +37,6 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
public class PlatformImpl {
public static final Map<String, Mod.ConfigurationScreenProvider> CONFIG_SCREENS = new ConcurrentHashMap<>();
private static final Map<String, Mod> mods = new ConcurrentHashMap<>();
public static Path getGameFolder() {
@@ -164,12 +163,5 @@ public class PlatformImpl {
public Optional<String> getIssueTracker() {
return metadata.getContact().get("sources");
}
@Override
public void registerConfigurationScreen(ConfigurationScreenProvider provider) {
if (CONFIG_SCREENS.containsKey(getModId()))
throw new IllegalStateException("Can not register configuration screen for mod '" + getModId() + "' because it was already registered!");
CONFIG_SCREENS.put(getModId(), provider);
}
}
}

View File

@@ -0,0 +1,33 @@
/*
* This file is part of architectury.
* Copyright (C) 2020, 2021, 2022 architectury
*
* 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 dev.architectury.registry.client.gui.fabric;
import dev.architectury.registry.client.gui.MenuScreenRegistry.ScreenFactory;
import net.minecraft.client.gui.screens.MenuScreens;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.gui.screens.inventory.MenuAccess;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.inventory.MenuType;
public class MenuScreenRegistryImpl {
public static <H extends AbstractContainerMenu, S extends Screen & MenuAccess<H>> void registerScreenFactory(MenuType<? extends H> type, ScreenFactory<H, S> factory) {
MenuScreens.register(type, factory::create);
}
}

View File

@@ -20,8 +20,8 @@
package dev.architectury.registry.client.particle.fabric;
import dev.architectury.registry.client.particle.ParticleProviderRegistry;
//import net.fabricmc.fabric.api.client.particle.v1.FabricSpriteProvider;
//import net.fabricmc.fabric.api.client.particle.v1.ParticleFactoryRegistry;
import net.fabricmc.fabric.api.client.particle.v1.FabricSpriteProvider;
import net.fabricmc.fabric.api.client.particle.v1.ParticleFactoryRegistry;
import net.minecraft.client.particle.ParticleProvider;
import net.minecraft.client.renderer.texture.TextureAtlas;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
@@ -32,7 +32,7 @@ import net.minecraft.util.RandomSource;
import java.util.List;
public class ParticleProviderRegistryImpl {
/*public record ExtendedSpriteSetImpl(
public record ExtendedSpriteSetImpl(
FabricSpriteProvider delegate
) implements ParticleProviderRegistry.ExtendedSpriteSet {
@Override
@@ -54,6 +54,11 @@ public class ParticleProviderRegistryImpl {
public TextureAtlasSprite get(RandomSource random) {
return delegate.get(random);
}
@Override
public TextureAtlasSprite first() {
return delegate.first();
}
}
public static <T extends ParticleOptions> void register(ParticleType<T> type, ParticleProvider<T> provider) {
@@ -63,5 +68,5 @@ public class ParticleProviderRegistryImpl {
public static <T extends ParticleOptions> void register(ParticleType<T> type, ParticleProviderRegistry.DeferredParticleProvider<T> provider) {
ParticleFactoryRegistry.getInstance().register(type, sprites ->
provider.create(new ExtendedSpriteSetImpl(sprites)));
}*/
}
}

View File

@@ -21,11 +21,12 @@ package dev.architectury.registry.client.rendering.fabric;
import net.fabricmc.fabric.api.client.rendering.v1.BlockEntityRendererRegistry;
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider;
import net.minecraft.client.renderer.blockentity.state.BlockEntityRenderState;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType;
public class BlockEntityRendererRegistryImpl {
public static <T extends BlockEntity> void register(BlockEntityType<T> type, BlockEntityRendererProvider<? super T> provider) {
public static <E extends BlockEntity, S extends BlockEntityRenderState> void register(BlockEntityType<E> type, BlockEntityRendererProvider<? super E, ? super S> provider) {
BlockEntityRendererRegistry.register(type, provider);
}
}

View File

@@ -25,10 +25,7 @@ import net.fabricmc.fabric.api.resource.ResourceManagerHelper;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.packs.PackType;
import net.minecraft.server.packs.resources.PreparableReloadListener;
import net.minecraft.server.packs.resources.ResourceManager;
import net.minecraft.util.profiling.ProfilerFiller;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.Nullable;
import java.security.SecureRandom;
import java.util.Collection;
@@ -59,8 +56,8 @@ public class ReloadListenerRegistryImpl {
}
@Override
public CompletableFuture<Void> reload(PreparationBarrier preparationBarrier, ResourceManager resourceManager, Executor executor, Executor executor2) {
return listener.reload(preparationBarrier, resourceManager, executor, executor2);
public CompletableFuture<Void> reload(SharedState sharedState, Executor executor, PreparationBarrier preparationBarrier, Executor executor2) {
return listener.reload(sharedState, executor, preparationBarrier, executor2);
}
});
}

View File

@@ -21,18 +21,12 @@ package dev.architectury.registry.menu.fabric;
import dev.architectury.registry.menu.ExtendedMenuProvider;
import dev.architectury.registry.menu.MenuRegistry.ExtendedMenuTypeFactory;
import dev.architectury.registry.menu.MenuRegistry.ScreenFactory;
import dev.architectury.registry.menu.MenuRegistry.SimpleMenuTypeFactory;
import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.networking.v1.PacketByteBufs;
import net.fabricmc.fabric.api.screenhandler.v1.ExtendedScreenHandlerFactory;
import net.fabricmc.fabric.api.screenhandler.v1.ExtendedScreenHandlerType;
import net.minecraft.client.gui.screens.MenuScreens;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.gui.screens.inventory.MenuAccess;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.chat.Component;
import net.minecraft.network.codec.ByteBufCodecs;
@@ -83,9 +77,4 @@ public class MenuRegistryImpl {
return menu;
}, ByteBufCodecs.BYTE_ARRAY.mapStream(Function.identity()));
}
@Environment(EnvType.CLIENT)
public static <H extends AbstractContainerMenu, S extends Screen & MenuAccess<H>> void registerScreenFactory(MenuType<? extends H> type, ScreenFactory<H, S> factory) {
MenuScreens.register(type, factory::create);
}
}

View File

@@ -3,23 +3,23 @@ org.gradle.daemon=false
platforms=fabric,neoforge
minecraft_version=1.21.7
supported_version=1.21.7/8
minecraft_version=1.21.9
supported_version=1.21.9
artifact_type=release
archives_base_name=architectury
archives_base_name_snapshot=architectury-snapshot
base_version=17.0
base_version=18.0
maven_group=dev.architectury
version_suffix=
fabric_loader_version=0.16.14
fabric_api_version=0.128.1+1.21.7
fabric_loader_version=0.17.2
fabric_api_version=0.133.14+1.21.9
mod_menu_version=15.0.0-beta.1
forge_version=51.0.0
neoforge_version=21.7.3-beta
neoforge_version=21.9.2-beta
# Set to empty if not snapshots
neoforge_pr=

View File

@@ -121,7 +121,7 @@ unifiedPublishing {
displayName = "[NeoForge $rootProject.supported_version] v$project.version"
releaseType = "$rootProject.artifact_type"
changelog = releaseChangelog()
gameVersions = ["1.21.7", "1.21.8"]
gameVersions = ["1.21.9"]
gameLoaders = ["neoforge"]
mainPublication renameJarForPublication

View File

@@ -21,6 +21,7 @@ package dev.architectury.core.fluid.forge.imitator;
import com.google.common.base.MoreObjects;
import dev.architectury.core.fluid.ArchitecturyFluidAttributes;
import dev.architectury.fluid.forge.ArchitecturyFluidAttributesClient;
import dev.architectury.hooks.client.forge.ClientExtensionsRegistryImpl;
import dev.architectury.hooks.fluid.forge.FluidStackHooksForge;
import dev.architectury.platform.Platform;
@@ -64,7 +65,7 @@ class ArchitecturyFluidAttributesForge extends FluidType {
this.attributes = attributes;
this.defaultTranslationKey = Util.makeDescriptionId("fluid", BuiltInRegistries.FLUID.getKey(fluid));
if (Platform.getEnvironment() == Env.CLIENT) {
this.registerClient();
ArchitecturyFluidAttributesClient.registerClient(this, () -> this.attributes);
}
}
@@ -84,93 +85,7 @@ class ArchitecturyFluidAttributesForge extends FluidType {
return item == null ? super.getBucket(stack) : new ItemStack(item);
}
@OnlyIn(Dist.CLIENT)
public void registerClient() {
ClientExtensionsRegistryImpl.register(event -> {
if (event != null) {
event.registerFluidType(initializeClient(), this);
} else {
try {
Class<?> clazz = Class.forName("net.neoforged.neoforge.client.extensions.common.ClientExtensionsManager");
Field field = clazz.getDeclaredField("FLUID_TYPE_EXTENSIONS");
field.setAccessible(true);
Method method = clazz.getDeclaredMethod("register", Object.class, Map.class, Object[].class);
method.setAccessible(true);
method.invoke(null, initializeClient(), (Map<?, ?>) field.get(null), new Object[]{this});
} catch (Throwable e) {
e.printStackTrace();
}
}
});
}
@OnlyIn(Dist.CLIENT)
public IClientFluidTypeExtensions initializeClient() {
return new IClientFluidTypeExtensions() {
@Override
public int getTintColor() {
return attributes.getColor();
}
@Override
public ResourceLocation getStillTexture() {
return attributes.getSourceTexture();
}
@Override
public ResourceLocation getFlowingTexture() {
return attributes.getFlowingTexture();
}
@Override
@Nullable
public ResourceLocation getOverlayTexture() {
return attributes.getOverlayTexture();
}
@Override
public ResourceLocation getStillTexture(FluidState state, BlockAndTintGetter getter, BlockPos pos) {
return attributes.getSourceTexture(state, getter, pos);
}
@Override
public ResourceLocation getFlowingTexture(FluidState state, BlockAndTintGetter getter, BlockPos pos) {
return attributes.getFlowingTexture(state, getter, pos);
}
@Override
@Nullable
public ResourceLocation getOverlayTexture(FluidState state, BlockAndTintGetter getter, BlockPos pos) {
return attributes.getOverlayTexture(state, getter, pos);
}
@Override
public int getTintColor(FluidState state, BlockAndTintGetter getter, BlockPos pos) {
return attributes.getColor(state, getter, pos);
}
@Override
public int getTintColor(FluidStack stack) {
return attributes.getColor(convertSafe(stack));
}
@Override
public ResourceLocation getStillTexture(FluidStack stack) {
return attributes.getSourceTexture(convertSafe(stack));
}
@Override
public ResourceLocation getFlowingTexture(FluidStack stack) {
return attributes.getFlowingTexture(convertSafe(stack));
}
@Override
@Nullable
public ResourceLocation getOverlayTexture(FluidStack stack) {
return attributes.getOverlayTexture(convertSafe(stack));
}
};
}
@Override
public int getLightLevel(FluidStack stack) {

View File

@@ -27,7 +27,7 @@ import net.minecraft.world.item.BucketItem;
import net.minecraft.world.level.material.Fluid;
import net.neoforged.neoforge.capabilities.Capabilities;
import net.neoforged.neoforge.capabilities.RegisterCapabilitiesEvent;
import net.neoforged.neoforge.fluids.capability.wrappers.FluidBucketWrapper;
import net.neoforged.neoforge.transfer.fluid.BucketResourceHandler;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@@ -41,7 +41,7 @@ public class ArchitecturyBucketItem extends BucketItem {
EventBusesHooks.whenAvailable(ArchitecturyConstants.MOD_ID, bus -> {
bus.<RegisterCapabilitiesEvent>addListener(event -> {
if (BuiltInRegistries.ITEM.containsValue(this)) {
event.registerItem(Capabilities.FluidHandler.ITEM, (stack, ctx) -> new FluidBucketWrapper(stack), this);
event.registerItem(Capabilities.Fluid.ITEM, (stack, access) -> new BucketResourceHandler(access), this);
} else {
LOGGER.warn("Tried to register a bucket item capability for an item that is not registered: {}", this);
}

View File

@@ -21,17 +21,10 @@ package dev.architectury.event.forge;
import dev.architectury.platform.hooks.EventBusesHooks;
import dev.architectury.utils.ArchitecturyConstants;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.api.distmarker.OnlyIn;
import net.neoforged.neoforge.common.NeoForge;
public class EventHandlerImpl {
@OnlyIn(Dist.CLIENT)
public static void registerClient() {
NeoForge.EVENT_BUS.register(EventHandlerImplClient.class);
EventBusesHooks.whenAvailable(ArchitecturyConstants.MOD_ID, bus -> {
bus.register(EventHandlerImplClient.ModBasedEventHandler.class);
});
}
public static void registerCommon() {
@@ -41,11 +34,6 @@ public class EventHandlerImpl {
});
}
@OnlyIn(Dist.DEDICATED_SERVER)
public static void registerServer() {
// MinecraftForge.EVENT_BUS.register(EventHandlerImplServer.class);
// EventBusesHooks.whenAvailable(ArchitecturyConstants.MOD_ID, bus -> {
// bus.register(EventHandlerImplServer.ModBasedEventHandler.class);
// });
}
}

View File

@@ -22,8 +22,8 @@ package dev.architectury.event.forge;
import com.mojang.brigadier.CommandDispatcher;
import dev.architectury.event.CompoundEventResult;
import dev.architectury.event.EventResult;
import dev.architectury.event.events.client.ClientChatEvent;
import dev.architectury.event.events.client.*;
import dev.architectury.event.events.client.ClientChatEvent;
import dev.architectury.event.events.common.InteractionEvent;
import dev.architectury.impl.ScreenAccessImpl;
import dev.architectury.impl.TooltipEventPositionContextImpl;
@@ -33,17 +33,17 @@ import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.network.chat.Component;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.api.distmarker.OnlyIn;
import net.neoforged.bus.api.EventPriority;
import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.fml.common.EventBusSubscriber;
import net.neoforged.fml.event.lifecycle.FMLClientSetupEvent;
import net.neoforged.neoforge.client.event.ClientTickEvent;
import net.neoforged.neoforge.client.event.*;
import net.neoforged.neoforge.client.event.ClientTickEvent;
import net.neoforged.neoforge.event.entity.player.ItemTooltipEvent;
import net.neoforged.neoforge.event.entity.player.PlayerInteractEvent;
import net.neoforged.neoforge.event.level.LevelEvent;
@OnlyIn(Dist.CLIENT)
@EventBusSubscriber(modid = "architectury", value = Dist.CLIENT)
public class EventHandlerImplClient {
@SubscribeEvent(priority = EventPriority.HIGH)
public static void event(ItemTooltipEvent event) {
@@ -140,14 +140,14 @@ public class EventHandlerImplClient {
@SubscribeEvent(priority = EventPriority.HIGH)
public static void eventDrawScreenEvent(ScreenEvent.Render.Pre event) {
if (ClientGuiEvent.RENDER_PRE.invoker().render(event.getScreen(), event.getGuiGraphics(), event.getMouseX(), event.getMouseY(), Minecraft.getInstance().getDeltaTracker()).isFalse()) {
if (ClientGuiEvent.RENDER_PRE.invoker().render(event.getScreen(), event.getGuiGraphics(), event.getMouseX(), event.getMouseY(), event.getPartialTick()).isFalse()) {
event.setCanceled(true);
}
}
@SubscribeEvent(priority = EventPriority.HIGH)
public static void eventDrawScreenEvent(ScreenEvent.Render.Post event) {
ClientGuiEvent.RENDER_POST.invoker().render(event.getScreen(), event.getGuiGraphics(), event.getMouseX(), event.getMouseY(), Minecraft.getInstance().getDeltaTracker());
ClientGuiEvent.RENDER_POST.invoker().render(event.getScreen(), event.getGuiGraphics(), event.getMouseX(), event.getMouseY(), event.getPartialTick());
}
@SubscribeEvent(priority = EventPriority.HIGH)
@@ -207,74 +207,74 @@ public class EventHandlerImplClient {
@SubscribeEvent(priority = EventPriority.HIGH)
public static void eventMouseClickedEvent(ScreenEvent.MouseButtonPressed.Pre event) {
if (ClientScreenInputEvent.MOUSE_CLICKED_PRE.invoker().mouseClicked(Minecraft.getInstance(), event.getScreen(), event.getMouseX(), event.getMouseY(), event.getButton()).isFalse()) {
if (ClientScreenInputEvent.MOUSE_CLICKED_PRE.invoker().mouseClicked(Minecraft.getInstance(), event.getScreen(), event.getMouseButtonEvent(), event.isDoubleClick()).isFalse()) {
event.setCanceled(true);
}
}
@SubscribeEvent(priority = EventPriority.HIGH)
public static void eventMouseClickedEvent(ScreenEvent.MouseButtonPressed.Post event) {
ClientScreenInputEvent.MOUSE_CLICKED_POST.invoker().mouseClicked(Minecraft.getInstance(), event.getScreen(), event.getMouseX(), event.getMouseY(), event.getButton());
ClientScreenInputEvent.MOUSE_CLICKED_POST.invoker().mouseClicked(Minecraft.getInstance(), event.getScreen(), event.getMouseButtonEvent(), event.isDoubleClick());
}
@SubscribeEvent(priority = EventPriority.HIGH)
public static void eventMouseDragEvent(ScreenEvent.MouseDragged.Pre event) {
if (ClientScreenInputEvent.MOUSE_DRAGGED_PRE.invoker().mouseDragged(Minecraft.getInstance(), event.getScreen(), event.getMouseX(), event.getMouseY(), event.getMouseButton(), event.getDragX(), event.getDragY()).isFalse()) {
if (ClientScreenInputEvent.MOUSE_DRAGGED_PRE.invoker().mouseDragged(Minecraft.getInstance(), event.getScreen(), event.getMouseButtonEvent(), event.getDragX(), event.getDragY()).isFalse()) {
event.setCanceled(true);
}
}
@SubscribeEvent(priority = EventPriority.HIGH)
public static void eventMouseDragEvent(ScreenEvent.MouseDragged.Post event) {
ClientScreenInputEvent.MOUSE_DRAGGED_POST.invoker().mouseDragged(Minecraft.getInstance(), event.getScreen(), event.getMouseX(), event.getMouseY(), event.getMouseButton(), event.getDragX(), event.getDragY());
ClientScreenInputEvent.MOUSE_DRAGGED_POST.invoker().mouseDragged(Minecraft.getInstance(), event.getScreen(), event.getMouseButtonEvent(), event.getDragX(), event.getDragY());
}
@SubscribeEvent(priority = EventPriority.HIGH)
public static void eventMouseReleasedEvent(ScreenEvent.MouseButtonReleased.Pre event) {
if (ClientScreenInputEvent.MOUSE_RELEASED_PRE.invoker().mouseReleased(Minecraft.getInstance(), event.getScreen(), event.getMouseX(), event.getMouseY(), event.getButton()).isFalse()) {
if (ClientScreenInputEvent.MOUSE_RELEASED_PRE.invoker().mouseReleased(Minecraft.getInstance(), event.getScreen(), event.getMouseButtonEvent()).isFalse()) {
event.setCanceled(true);
}
}
@SubscribeEvent(priority = EventPriority.HIGH)
public static void eventMouseReleasedEvent(ScreenEvent.MouseButtonReleased.Post event) {
ClientScreenInputEvent.MOUSE_RELEASED_PRE.invoker().mouseReleased(Minecraft.getInstance(), event.getScreen(), event.getMouseX(), event.getMouseY(), event.getButton());
ClientScreenInputEvent.MOUSE_RELEASED_PRE.invoker().mouseReleased(Minecraft.getInstance(), event.getScreen(), event.getMouseButtonEvent());
}
@SubscribeEvent(priority = EventPriority.HIGH)
public static void eventKeyboardCharTypedEvent(ScreenEvent.CharacterTyped.Pre event) {
if (ClientScreenInputEvent.CHAR_TYPED_PRE.invoker().charTyped(Minecraft.getInstance(), event.getScreen(), event.getCodePoint(), event.getModifiers()).isFalse()) {
if (ClientScreenInputEvent.CHAR_TYPED_PRE.invoker().charTyped(Minecraft.getInstance(), event.getScreen(), event.getCharacterEvent()).isFalse()) {
event.setCanceled(true);
}
}
@SubscribeEvent(priority = EventPriority.HIGH)
public static void eventKeyboardCharTypedEvent(ScreenEvent.CharacterTyped.Post event) {
ClientScreenInputEvent.CHAR_TYPED_POST.invoker().charTyped(Minecraft.getInstance(), event.getScreen(), event.getCodePoint(), event.getModifiers());
ClientScreenInputEvent.CHAR_TYPED_POST.invoker().charTyped(Minecraft.getInstance(), event.getScreen(), event.getCharacterEvent());
}
@SubscribeEvent(priority = EventPriority.HIGH)
public static void eventKeyboardKeyPressedEvent(ScreenEvent.KeyPressed.Pre event) {
if (ClientScreenInputEvent.KEY_PRESSED_PRE.invoker().keyPressed(Minecraft.getInstance(), event.getScreen(), event.getKeyCode(), event.getScanCode(), event.getModifiers()).isFalse()) {
if (ClientScreenInputEvent.KEY_PRESSED_PRE.invoker().keyPressed(Minecraft.getInstance(), event.getScreen(), event.getKeyEvent()).isFalse()) {
event.setCanceled(true);
}
}
@SubscribeEvent(priority = EventPriority.HIGH)
public static void eventKeyboardKeyPressedEvent(ScreenEvent.KeyPressed.Post event) {
ClientScreenInputEvent.KEY_PRESSED_POST.invoker().keyPressed(Minecraft.getInstance(), event.getScreen(), event.getKeyCode(), event.getScanCode(), event.getModifiers());
ClientScreenInputEvent.KEY_PRESSED_POST.invoker().keyPressed(Minecraft.getInstance(), event.getScreen(), event.getKeyEvent());
}
@SubscribeEvent(priority = EventPriority.HIGH)
public static void eventKeyboardKeyReleasedEvent(ScreenEvent.KeyReleased.Pre event) {
if (ClientScreenInputEvent.KEY_RELEASED_PRE.invoker().keyReleased(Minecraft.getInstance(), event.getScreen(), event.getKeyCode(), event.getScanCode(), event.getModifiers()).isFalse()) {
if (ClientScreenInputEvent.KEY_RELEASED_PRE.invoker().keyReleased(Minecraft.getInstance(), event.getScreen(), event.getKeyEvent()).isFalse()) {
event.setCanceled(true);
}
}
@SubscribeEvent(priority = EventPriority.HIGH)
public static void eventKeyboardKeyReleasedEvent(ScreenEvent.KeyReleased.Post event) {
ClientScreenInputEvent.KEY_RELEASED_POST.invoker().keyReleased(Minecraft.getInstance(), event.getScreen(), event.getKeyCode(), event.getScanCode(), event.getModifiers());
ClientScreenInputEvent.KEY_RELEASED_POST.invoker().keyReleased(Minecraft.getInstance(), event.getScreen(), event.getKeyEvent());
}
@SubscribeEvent(priority = EventPriority.HIGH)
@@ -286,19 +286,19 @@ public class EventHandlerImplClient {
@SubscribeEvent(priority = EventPriority.HIGH)
public static void eventInputEvent(InputEvent.MouseButton.Pre event) {
if (ClientRawInputEvent.MOUSE_CLICKED_PRE.invoker().mouseClicked(Minecraft.getInstance(), event.getButton(), event.getAction(), event.getModifiers()).isFalse()) {
if (ClientRawInputEvent.MOUSE_CLICKED_PRE.invoker().mouseClicked(Minecraft.getInstance(), event.getMouseButtonInfo(), event.getAction()).isFalse()) {
event.setCanceled(true);
}
}
@SubscribeEvent(priority = EventPriority.HIGH)
public static void eventInputEvent(InputEvent.MouseButton.Post event) {
ClientRawInputEvent.MOUSE_CLICKED_POST.invoker().mouseClicked(Minecraft.getInstance(), event.getButton(), event.getAction(), event.getModifiers());
ClientRawInputEvent.MOUSE_CLICKED_POST.invoker().mouseClicked(Minecraft.getInstance(), event.getMouseButtonInfo(), event.getAction());
}
@SubscribeEvent(priority = EventPriority.HIGH)
public static void eventInputEvent(InputEvent.Key event) {
ClientRawInputEvent.KEY_PRESSED.invoker().keyPressed(Minecraft.getInstance(), event.getKey(), event.getScanCode(), event.getAction(), event.getModifiers());
ClientRawInputEvent.KEY_PRESSED.invoker().keyPressed(Minecraft.getInstance(), event.getKey(), event.getKeyEvent());
}
@SubscribeEvent(priority = EventPriority.HIGH)
@@ -307,7 +307,7 @@ public class EventHandlerImplClient {
(CommandDispatcher<?>) event.getDispatcher(), event.getBuildContext());
}
@OnlyIn(Dist.CLIENT)
@EventBusSubscriber(modid = "architectury", value = Dist.CLIENT)
public static class ModBasedEventHandler {
// @SubscribeEvent(priority = EventPriority.HIGH)
// public static void eventTextureStitchEvent(TextureStitchEvent.Post event) {

View File

@@ -20,12 +20,11 @@
package dev.architectury.event.forge;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.api.distmarker.OnlyIn;
import net.neoforged.fml.common.EventBusSubscriber;
@OnlyIn(Dist.DEDICATED_SERVER)
@EventBusSubscriber(modid = "architectury", value = Dist.DEDICATED_SERVER)
public class EventHandlerImplServer {
@OnlyIn(Dist.DEDICATED_SERVER)
@EventBusSubscriber(modid = "architectury", value = Dist.DEDICATED_SERVER)
public static class ModBasedEventHandler {
}
}

View File

@@ -0,0 +1,135 @@
/*
* This file is part of architectury.
* Copyright (C) 2020, 2021, 2022 architectury
*
* 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 dev.architectury.fluid.forge;
import dev.architectury.core.fluid.ArchitecturyFluidAttributes;
import dev.architectury.hooks.client.forge.ClientExtensionsRegistryImpl;
import dev.architectury.hooks.fluid.forge.FluidStackHooksForge;
import net.minecraft.core.BlockPos;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.BlockAndTintGetter;
import net.minecraft.world.level.material.FluidState;
import net.neoforged.neoforge.client.extensions.common.IClientFluidTypeExtensions;
import net.neoforged.neoforge.fluids.FluidStack;
import net.neoforged.neoforge.fluids.FluidType;
import org.jetbrains.annotations.Nullable;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.function.Supplier;
public class ArchitecturyFluidAttributesClient {
public static void registerClient(FluidType fluid, Supplier<ArchitecturyFluidAttributes> attributes) {
ClientExtensionsRegistryImpl.register(event -> {
if (event != null) {
event.registerFluidType(initializeClient(attributes.get()), fluid);
} else {
try {
Class<?> clazz = Class.forName("net.neoforged.neoforge.client.extensions.common.ClientExtensionsManager");
Field field = clazz.getDeclaredField("FLUID_TYPE_EXTENSIONS");
field.setAccessible(true);
Method method = clazz.getDeclaredMethod("register", Object.class, Map.class, Object[].class);
method.setAccessible(true);
method.invoke(null, initializeClient(attributes.get()), (Map<?, ?>) field.get(null), new Object[]{fluid});
} catch (Throwable e) {
e.printStackTrace();
}
}
});
}
public static IClientFluidTypeExtensions initializeClient(ArchitecturyFluidAttributes attributes) {
return new IClientFluidTypeExtensions() {
@Override
public int getTintColor() {
return attributes.getColor();
}
@Override
public ResourceLocation getStillTexture() {
return attributes.getSourceTexture();
}
@Override
public ResourceLocation getFlowingTexture() {
return attributes.getFlowingTexture();
}
@Override
@Nullable
public ResourceLocation getOverlayTexture() {
return attributes.getOverlayTexture();
}
@Override
public ResourceLocation getStillTexture(FluidState state, BlockAndTintGetter getter, BlockPos pos) {
return attributes.getSourceTexture(state, getter, pos);
}
@Override
public ResourceLocation getFlowingTexture(FluidState state, BlockAndTintGetter getter, BlockPos pos) {
return attributes.getFlowingTexture(state, getter, pos);
}
@Override
@Nullable
public ResourceLocation getOverlayTexture(FluidState state, BlockAndTintGetter getter, BlockPos pos) {
return attributes.getOverlayTexture(state, getter, pos);
}
@Override
public int getTintColor(FluidState state, BlockAndTintGetter getter, BlockPos pos) {
return attributes.getColor(state, getter, pos);
}
@Override
public int getTintColor(FluidStack stack) {
return attributes.getColor(convertSafe(stack));
}
@Override
public ResourceLocation getStillTexture(FluidStack stack) {
return attributes.getSourceTexture(convertSafe(stack));
}
@Override
public ResourceLocation getFlowingTexture(FluidStack stack) {
return attributes.getFlowingTexture(convertSafe(stack));
}
@Override
@Nullable
public ResourceLocation getOverlayTexture(FluidStack stack) {
return attributes.getOverlayTexture(convertSafe(stack));
}
};
}
@Nullable
public static dev.architectury.fluid.FluidStack convertSafe(@Nullable FluidStack stack) {
return stack == null ? null : FluidStackHooksForge.fromForge(stack);
}
@Nullable
public static dev.architectury.fluid.FluidStack convertSafe(@Nullable FluidState state) {
return state == null ? null : dev.architectury.fluid.FluidStack.create(state.getType(), dev.architectury.fluid.FluidStack.bucketAmount());
}
}

View File

@@ -0,0 +1,94 @@
/*
* This file is part of architectury.
* Copyright (C) 2020, 2021, 2022 architectury
*
* 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 dev.architectury.hooks.client.fluid.forge;
import dev.architectury.fluid.FluidStack;
import dev.architectury.hooks.fluid.forge.FluidStackHooksForge;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.texture.TextureAtlas;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.resources.model.Material;
import net.minecraft.core.BlockPos;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.BlockAndTintGetter;
import net.minecraft.world.level.material.Fluid;
import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.level.material.Fluids;
import net.neoforged.neoforge.client.extensions.common.IClientFluidTypeExtensions;
import org.jetbrains.annotations.Nullable;
public class ClientFluidStackHooksImpl {
@Nullable
public static TextureAtlasSprite getStillTexture(@Nullable BlockAndTintGetter level, @Nullable BlockPos pos, FluidState state) {
if (state.getType() == Fluids.EMPTY) return null;
ResourceLocation texture = IClientFluidTypeExtensions.of(state).getStillTexture(state, level, pos);
return Minecraft.getInstance().getAtlasManager().get(new Material(TextureAtlas.LOCATION_BLOCKS, texture));
}
@Nullable
public static TextureAtlasSprite getStillTexture(FluidStack stack) {
if (stack.getFluid() == Fluids.EMPTY) return null;
ResourceLocation texture = IClientFluidTypeExtensions.of(stack.getFluid()).getStillTexture(FluidStackHooksForge.toForge(stack));
return Minecraft.getInstance().getAtlasManager().get(new Material(TextureAtlas.LOCATION_BLOCKS, texture));
}
@Nullable
public static TextureAtlasSprite getStillTexture(Fluid fluid) {
if (fluid == Fluids.EMPTY) return null;
ResourceLocation texture = IClientFluidTypeExtensions.of(fluid).getStillTexture();
return Minecraft.getInstance().getAtlasManager().get(new Material(TextureAtlas.LOCATION_BLOCKS, texture));
}
@Nullable
public static TextureAtlasSprite getFlowingTexture(@Nullable BlockAndTintGetter level, @Nullable BlockPos pos, FluidState state) {
if (state.getType() == Fluids.EMPTY) return null;
ResourceLocation texture = IClientFluidTypeExtensions.of(state).getFlowingTexture(state, level, pos);
return Minecraft.getInstance().getAtlasManager().get(new Material(TextureAtlas.LOCATION_BLOCKS, texture));
}
@Nullable
public static TextureAtlasSprite getFlowingTexture(FluidStack stack) {
if (stack.getFluid() == Fluids.EMPTY) return null;
ResourceLocation texture = IClientFluidTypeExtensions.of(stack.getFluid()).getFlowingTexture(FluidStackHooksForge.toForge(stack));
return Minecraft.getInstance().getAtlasManager().get(new Material(TextureAtlas.LOCATION_BLOCKS, texture));
}
@Nullable
public static TextureAtlasSprite getFlowingTexture(Fluid fluid) {
if (fluid == Fluids.EMPTY) return null;
ResourceLocation texture = IClientFluidTypeExtensions.of(fluid).getFlowingTexture();
return Minecraft.getInstance().getAtlasManager().get(new Material(TextureAtlas.LOCATION_BLOCKS, texture));
}
public static int getColor(@Nullable BlockAndTintGetter level, @Nullable BlockPos pos, FluidState state) {
if (state.getType() == Fluids.EMPTY) return -1;
return IClientFluidTypeExtensions.of(state).getTintColor(state, level, pos);
}
public static int getColor(FluidStack stack) {
if (stack.getFluid() == Fluids.EMPTY) return -1;
return IClientFluidTypeExtensions.of(stack.getFluid()).getTintColor(FluidStackHooksForge.toForge(stack));
}
public static int getColor(Fluid fluid) {
if (fluid == Fluids.EMPTY) return -1;
return IClientFluidTypeExtensions.of(fluid).getTintColor();
}
}

View File

@@ -21,26 +21,15 @@ package dev.architectury.hooks.fluid.forge;
import com.mojang.logging.LogUtils;
import dev.architectury.fluid.FluidStack;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.texture.TextureAtlas;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.core.BlockPos;
import net.minecraft.core.HolderLookup;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtOps;
import net.minecraft.nbt.Tag;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.RegistryFriendlyByteBuf;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.BlockAndTintGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.material.Fluid;
import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.level.material.Fluids;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.api.distmarker.OnlyIn;
import net.neoforged.neoforge.client.extensions.common.IClientFluidTypeExtensions;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
@@ -82,72 +71,6 @@ public class FluidStackHooksImpl {
return 1000;
}
@OnlyIn(Dist.CLIENT)
@Nullable
public static TextureAtlasSprite getStillTexture(@Nullable BlockAndTintGetter level, @Nullable BlockPos pos, FluidState state) {
if (state.getType() == Fluids.EMPTY) return null;
ResourceLocation texture = IClientFluidTypeExtensions.of(state).getStillTexture(state, level, pos);
return Minecraft.getInstance().getTextureAtlas(TextureAtlas.LOCATION_BLOCKS).apply(texture);
}
@OnlyIn(Dist.CLIENT)
@Nullable
public static TextureAtlasSprite getStillTexture(FluidStack stack) {
if (stack.getFluid() == Fluids.EMPTY) return null;
ResourceLocation texture = IClientFluidTypeExtensions.of(stack.getFluid()).getStillTexture(FluidStackHooksForge.toForge(stack));
return Minecraft.getInstance().getTextureAtlas(TextureAtlas.LOCATION_BLOCKS).apply(texture);
}
@OnlyIn(Dist.CLIENT)
@Nullable
public static TextureAtlasSprite getStillTexture(Fluid fluid) {
if (fluid == Fluids.EMPTY) return null;
ResourceLocation texture = IClientFluidTypeExtensions.of(fluid).getStillTexture();
return Minecraft.getInstance().getTextureAtlas(TextureAtlas.LOCATION_BLOCKS).apply(texture);
}
@OnlyIn(Dist.CLIENT)
@Nullable
public static TextureAtlasSprite getFlowingTexture(@Nullable BlockAndTintGetter level, @Nullable BlockPos pos, FluidState state) {
if (state.getType() == Fluids.EMPTY) return null;
ResourceLocation texture = IClientFluidTypeExtensions.of(state).getFlowingTexture(state, level, pos);
return Minecraft.getInstance().getTextureAtlas(TextureAtlas.LOCATION_BLOCKS).apply(texture);
}
@OnlyIn(Dist.CLIENT)
@Nullable
public static TextureAtlasSprite getFlowingTexture(FluidStack stack) {
if (stack.getFluid() == Fluids.EMPTY) return null;
ResourceLocation texture = IClientFluidTypeExtensions.of(stack.getFluid()).getFlowingTexture(FluidStackHooksForge.toForge(stack));
return Minecraft.getInstance().getTextureAtlas(TextureAtlas.LOCATION_BLOCKS).apply(texture);
}
@OnlyIn(Dist.CLIENT)
@Nullable
public static TextureAtlasSprite getFlowingTexture(Fluid fluid) {
if (fluid == Fluids.EMPTY) return null;
ResourceLocation texture = IClientFluidTypeExtensions.of(fluid).getFlowingTexture();
return Minecraft.getInstance().getTextureAtlas(TextureAtlas.LOCATION_BLOCKS).apply(texture);
}
@OnlyIn(Dist.CLIENT)
public static int getColor(@Nullable BlockAndTintGetter level, @Nullable BlockPos pos, FluidState state) {
if (state.getType() == Fluids.EMPTY) return -1;
return IClientFluidTypeExtensions.of(state).getTintColor(state, level, pos);
}
@OnlyIn(Dist.CLIENT)
public static int getColor(FluidStack stack) {
if (stack.getFluid() == Fluids.EMPTY) return -1;
return IClientFluidTypeExtensions.of(stack.getFluid()).getTintColor(FluidStackHooksForge.toForge(stack));
}
@OnlyIn(Dist.CLIENT)
public static int getColor(Fluid fluid) {
if (fluid == Fluids.EMPTY) return -1;
return IClientFluidTypeExtensions.of(fluid).getTintColor();
}
public static int getLuminosity(FluidStack fluid, @Nullable Level level, @Nullable BlockPos pos) {
return fluid.getFluid().getFluidType().getLightLevel(FluidStackHooksForge.toForge(fluid));
}

View File

@@ -20,11 +20,12 @@
package dev.architectury.neoforge;
import dev.architectury.event.EventHandler;
import dev.architectury.networking.ClientSpawnEntityPacket;
import dev.architectury.networking.SpawnEntityPacket;
import dev.architectury.platform.Platform;
import dev.architectury.registry.level.biome.forge.BiomeModificationsImpl;
import dev.architectury.utils.ArchitecturyConstants;
import dev.architectury.utils.Env;
import dev.architectury.utils.EnvExecutor;
import net.neoforged.fml.common.Mod;
@Mod(ArchitecturyConstants.MOD_ID)
@@ -33,7 +34,10 @@ public class ArchitecturyNeoForge {
EventHandler.init();
BiomeModificationsImpl.init();
EnvExecutor.runInEnv(Env.CLIENT, () -> SpawnEntityPacket.Client::register);
EnvExecutor.runInEnv(Env.SERVER, () -> SpawnEntityPacket::register);
if (Platform.getEnvironment() == Env.CLIENT) {
ClientSpawnEntityPacket.register();
} else {
SpawnEntityPacket.register();
}
}
}

View File

@@ -25,10 +25,10 @@ import dev.architectury.impl.NetworkAggregator;
import dev.architectury.networking.NetworkManager;
import dev.architectury.networking.NetworkManager.NetworkReceiver;
import dev.architectury.networking.SpawnEntityPacket;
import dev.architectury.networking.forge.client.ClientNetworkManagerImpl;
import dev.architectury.platform.hooks.EventBusesHooks;
import dev.architectury.utils.ArchitecturyConstants;
import dev.architectury.utils.Env;
import net.minecraft.client.Minecraft;
import net.minecraft.core.RegistryAccess;
import net.minecraft.network.RegistryFriendlyByteBuf;
import net.minecraft.network.codec.StreamCodec;
@@ -42,8 +42,6 @@ import net.minecraft.server.level.ServerEntity;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.player.Player;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.api.distmarker.OnlyIn;
import net.neoforged.neoforge.network.event.RegisterPayloadHandlersEvent;
import net.neoforged.neoforge.network.handling.IPayloadContext;
import org.slf4j.Logger;
@@ -120,19 +118,18 @@ public class NetworkManagerImpl {
};
}
@OnlyIn(Dist.CLIENT)
public static boolean canServerReceive(ResourceLocation id) {
if (Minecraft.getInstance().getConnection() != null) {
return Minecraft.getInstance().getConnection().hasChannel(id);
} else {
return false;
}
return ClientNetworkManagerImpl.canServerReceive(id);
}
public static boolean canPlayerReceive(ServerPlayer player, ResourceLocation id) {
return player.connection.hasChannel(id);
}
public static <T extends CustomPacketPayload> void sendToServer(T payload) {
ClientNetworkManagerImpl.sendToServer(payload);
}
public static Packet<ClientGamePacketListener> createAddEntityPacket(Entity entity, ServerEntity serverEntity) {
return SpawnEntityPacket.create(entity, serverEntity);
}

View File

@@ -1,8 +1,32 @@
/*
* This file is part of architectury.
* Copyright (C) 2020, 2021, 2022 architectury
*
* 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 dev.architectury.networking.forge.client;
import dev.architectury.networking.NetworkManager;
import dev.architectury.networking.transformers.PacketSink;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.ClientPacketListener;
import net.minecraft.core.RegistryAccess;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.network.protocol.common.custom.CustomPacketPayload;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.entity.player.Player;
public class ClientNetworkManagerImpl {
@@ -23,4 +47,18 @@ public class ClientNetworkManagerImpl {
// Fail-safe
return RegistryAccess.fromRegistryOfRegistries(BuiltInRegistries.REGISTRY);
}
public static boolean canServerReceive(ResourceLocation id) {
if (Minecraft.getInstance().getConnection() != null) {
return Minecraft.getInstance().getConnection().hasChannel(id);
} else {
return false;
}
}
public static <T extends CustomPacketPayload> void sendToServer(T payload) {
ClientPacketListener connection = Minecraft.getInstance().getConnection();
if (connection == null) return;
NetworkManager.collectPackets(PacketSink.client(), NetworkManager.clientToServer(), payload, connection.registryAccess());
}
}

View File

@@ -0,0 +1,33 @@
/*
* This file is part of architectury.
* Copyright (C) 2020, 2021, 2022 architectury
*
* 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 dev.architectury.platform.client.forge;
import dev.architectury.platform.Mod;
import dev.architectury.platform.client.ConfigurationScreenRegistry;
import net.neoforged.fml.ModList;
import net.neoforged.neoforge.client.gui.IConfigScreenFactory;
public class ConfigurationScreenRegistryImpl {
public static void register(Mod mod, ConfigurationScreenRegistry.ConfigurationScreenProvider provider) {
ModList.get().getModContainerById(mod.getModId())
.orElseThrow()
.registerExtensionPoint(IConfigScreenFactory.class, (container, screen) -> provider.provide(screen));
}
}

View File

@@ -25,10 +25,8 @@ import net.neoforged.api.distmarker.Dist;
import net.neoforged.fml.ModContainer;
import net.neoforged.fml.ModList;
import net.neoforged.fml.loading.FMLEnvironment;
import net.neoforged.fml.loading.FMLLoader;
import net.neoforged.fml.loading.FMLPaths;
import net.neoforged.fml.loading.moddiscovery.ModFileInfo;
import net.neoforged.neoforge.client.gui.IConfigScreenFactory;
import net.neoforged.neoforgespi.language.IModFileInfo;
import net.neoforged.neoforgespi.language.IModInfo;
import org.jetbrains.annotations.NotNull;
@@ -61,7 +59,7 @@ public class PlatformImpl {
}
public static Dist getEnv() {
return FMLEnvironment.dist;
return FMLEnvironment.getDist();
}
public static boolean isModLoaded(String id) {
@@ -84,7 +82,7 @@ public class PlatformImpl {
}
public static boolean isDevelopmentEnvironment() {
return !FMLLoader.isProduction();
return !FMLEnvironment.isProduction();
}
private static class ModImpl implements Mod {
@@ -135,12 +133,12 @@ public class PlatformImpl {
@Override
public Path getFilePath() {
return this.info.getOwningFile().getFile().getSecureJar().getRootPath();
return this.info.getOwningFile().getFile().getFilePath();
}
@Override
public Optional<Path> findResource(String... path) {
return Optional.of(this.info.getOwningFile().getFile().findResource(path)).filter(Files::exists);
return Optional.of(this.getFilePath().resolve(String.join("/", path))).filter(Files::exists);
}
@Override
@@ -175,10 +173,5 @@ public class PlatformImpl {
}
return Optional.empty();
}
@Override
public void registerConfigurationScreen(ConfigurationScreenProvider configurationScreenProvider) {
container.registerExtensionPoint(IConfigScreenFactory.class, (container, screen) -> configurationScreenProvider.provide(screen));
}
}
}

View File

@@ -0,0 +1,48 @@
/*
* This file is part of architectury.
* Copyright (C) 2020, 2021, 2022 architectury
*
* 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 dev.architectury.registry.client.forge;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.packs.resources.PreparableReloadListener;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.fml.common.EventBusSubscriber;
import net.neoforged.neoforge.client.event.AddClientReloadListenersEvent;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
@EventBusSubscriber(modid = "architectury", value = Dist.CLIENT)
public class ClientReloadListenerRegistryImpl {
private static Map<ResourceLocation, PreparableReloadListener> clientDataReloadListeners = new HashMap<>();
private static Map<ResourceLocation, Collection<ResourceLocation>> clientDataReloadListenerDependencies = new HashMap<>();
public static void register(PreparableReloadListener listener, ResourceLocation listenerId, Collection<ResourceLocation> dependencies) {
clientDataReloadListeners.put(listenerId, listener);
clientDataReloadListenerDependencies.put(listenerId, dependencies);
}
@SubscribeEvent
public static void addClientReloadListeners(AddClientReloadListenersEvent event) {
clientDataReloadListeners.forEach(event::addListener);
clientDataReloadListenerDependencies.forEach((listener, dependencies) -> dependencies.forEach(dependency -> event.addDependency(listener, dependency)));
}
}

View File

@@ -23,8 +23,6 @@ import dev.architectury.platform.hooks.EventBusesHooks;
import dev.architectury.utils.ArchitecturyConstants;
import net.minecraft.client.gui.screens.inventory.tooltip.ClientTooltipComponent;
import net.minecraft.world.inventory.tooltip.TooltipComponent;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.api.distmarker.OnlyIn;
import net.neoforged.bus.api.EventPriority;
import net.neoforged.neoforge.client.event.RegisterClientTooltipComponentFactoriesEvent;
import org.jetbrains.annotations.ApiStatus;
@@ -34,7 +32,6 @@ import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
@OnlyIn(Dist.CLIENT)
@ApiStatus.Internal
public class ClientTooltipComponentRegistryImpl {
@Nullable

View File

@@ -0,0 +1,37 @@
/*
* This file is part of architectury.
* Copyright (C) 2020, 2021, 2022 architectury
*
* 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 dev.architectury.registry.client.gui.forge;
import dev.architectury.platform.hooks.EventBusesHooks;
import dev.architectury.registry.client.gui.MenuScreenRegistry.ScreenFactory;
import dev.architectury.utils.ArchitecturyConstants;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.gui.screens.inventory.MenuAccess;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.inventory.MenuType;
import net.neoforged.neoforge.client.event.RegisterMenuScreensEvent;
public class MenuScreenRegistryImpl {
public static <H extends AbstractContainerMenu, S extends Screen & MenuAccess<H>> void registerScreenFactory(MenuType<? extends H> type, ScreenFactory<H, S> factory) {
EventBusesHooks.whenAvailable(ArchitecturyConstants.MOD_ID, bus -> {
bus.addListener(RegisterMenuScreensEvent.class, event -> event.register(type, factory::create));
});
}
}

View File

@@ -24,13 +24,13 @@ import dev.architectury.platform.hooks.EventBusesHooks;
import dev.architectury.registry.client.particle.ParticleProviderRegistry;
import dev.architectury.utils.ArchitecturyConstants;
import net.minecraft.client.Minecraft;
import net.minecraft.client.particle.ParticleEngine;
import net.minecraft.client.particle.ParticleProvider;
import net.minecraft.client.particle.SpriteSet;
import net.minecraft.client.particle.ParticleResources;
import net.minecraft.client.renderer.texture.TextureAtlas;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.core.particles.ParticleOptions;
import net.minecraft.core.particles.ParticleType;
import net.minecraft.data.AtlasIds;
import net.minecraft.util.RandomSource;
import net.neoforged.neoforge.client.event.RegisterParticleProvidersEvent;
import org.slf4j.Logger;
@@ -48,33 +48,30 @@ public class ParticleProviderRegistryImpl {
});
}
private static final class ExtendedSpriteSetImpl implements ParticleProviderRegistry.ExtendedSpriteSet {
private final ParticleEngine engine;
private final SpriteSet delegate;
private ExtendedSpriteSetImpl(ParticleEngine engine, SpriteSet delegate) {
this.engine = engine;
this.delegate = delegate;
}
private record ExtendedSpriteSetImpl(ParticleResources.MutableSpriteSet set) implements ParticleProviderRegistry.ExtendedSpriteSet {
@Override
public TextureAtlas getAtlas() {
return engine.textureAtlas;
return Minecraft.getInstance().getAtlasManager().getAtlasOrThrow(AtlasIds.PARTICLES);
}
@Override
public List<TextureAtlasSprite> getSprites() {
return ((ParticleEngine.MutableSpriteSet) delegate).sprites;
return set.sprites;
}
@Override
public TextureAtlasSprite get(int i, int j) {
return delegate.get(i, j);
return set.get(i, j);
}
@Override
public TextureAtlasSprite get(RandomSource random) {
return delegate.get(random);
return set.get(random);
}
@Override
public TextureAtlasSprite first() {
return set.first();
}
}
@@ -86,7 +83,7 @@ public class ParticleProviderRegistryImpl {
private static <T extends ParticleOptions> void doRegister(ParticleProviderRegistrar registrar, ParticleType<T> type, ParticleProviderRegistry.DeferredParticleProvider<T> provider) {
registrar.register(type, sprites ->
provider.create(new ExtendedSpriteSetImpl(Minecraft.getInstance().particleEngine, sprites)));
provider.create(new ExtendedSpriteSetImpl((ParticleResources.MutableSpriteSet) sprites)));
}
public static <T extends ParticleOptions> void register(ParticleType<T> type, ParticleProvider<T> provider) {
@@ -122,7 +119,7 @@ public class ParticleProviderRegistryImpl {
private interface ParticleProviderRegistrar {
<T extends ParticleOptions> void register(ParticleType<T> type, ParticleProvider<T> provider);
<T extends ParticleOptions> void register(ParticleType<T> type, ParticleEngine.SpriteParticleRegistration<T> registration);
<T extends ParticleOptions> void register(ParticleType<T> type, ParticleResources.SpriteParticleRegistration<T> registration);
static ParticleProviderRegistrar ofForge(RegisterParticleProvidersEvent event) {
return new ParticleProviderRegistrar() {
@@ -132,7 +129,7 @@ public class ParticleProviderRegistryImpl {
}
@Override
public <T extends ParticleOptions> void register(ParticleType<T> type, ParticleEngine.SpriteParticleRegistration<T> registration) {
public <T extends ParticleOptions> void register(ParticleType<T> type, ParticleResources.SpriteParticleRegistration<T> registration) {
event.registerSpriteSet(type, registration);
}
};
@@ -142,12 +139,12 @@ public class ParticleProviderRegistryImpl {
return new ParticleProviderRegistrar() {
@Override
public <T extends ParticleOptions> void register(ParticleType<T> type, ParticleProvider<T> provider) {
Minecraft.getInstance().particleEngine.register(type, provider);
Minecraft.getInstance().particleResources.register(type, provider);
}
@Override
public <T extends ParticleOptions> void register(ParticleType<T> type, ParticleEngine.SpriteParticleRegistration<T> registration) {
Minecraft.getInstance().particleEngine.register(type, registration);
public <T extends ParticleOptions> void register(ParticleType<T> type, ParticleResources.SpriteParticleRegistration<T> registration) {
Minecraft.getInstance().particleResources.register(type, registration);
}
};
}

View File

@@ -21,11 +21,12 @@ package dev.architectury.registry.client.rendering.forge;
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider;
import net.minecraft.client.renderer.blockentity.BlockEntityRenderers;
import net.minecraft.client.renderer.blockentity.state.BlockEntityRenderState;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType;
public class BlockEntityRendererRegistryImpl {
public static <T extends BlockEntity> void register(BlockEntityType<T> type, BlockEntityRendererProvider<? super T> provider) {
public static <E extends BlockEntity, S extends BlockEntityRenderState> void register(BlockEntityType<E> type, BlockEntityRendererProvider<? super E, ? super S> provider) {
BlockEntityRenderers.register(type, provider);
}
}

View File

@@ -19,20 +19,10 @@
package dev.architectury.registry.forge;
import dev.architectury.platform.Platform;
import dev.architectury.platform.hooks.EventBusesHooks;
import dev.architectury.utils.ArchitecturyConstants;
import dev.architectury.utils.Env;
import dev.architectury.utils.EnvExecutor;
import javax.annotation.Nullable;
import net.minecraft.client.Minecraft;
import dev.architectury.registry.client.forge.ClientReloadListenerRegistryImpl;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.packs.PackType;
import net.minecraft.server.packs.resources.PreparableReloadListener;
import net.minecraft.server.packs.resources.ReloadableResourceManager;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.api.distmarker.OnlyIn;
import net.neoforged.neoforge.client.event.AddClientReloadListenersEvent;
import net.neoforged.neoforge.common.NeoForge;
import net.neoforged.neoforge.event.AddServerReloadListenersEvent;
@@ -41,19 +31,10 @@ import java.util.HashMap;
import java.util.Map;
public class ReloadListenerRegistryImpl {
private static Map<ResourceLocation, PreparableReloadListener> clientDataReloadListeners = new HashMap<>();
private static Map<ResourceLocation, Collection<ResourceLocation>> clientDataReloadListenerDependencies = new HashMap<>();
private static Map<ResourceLocation, PreparableReloadListener> serverDataReloadListeners = new HashMap<>();
private static Map<ResourceLocation, Collection<ResourceLocation>> serverDataReloadListenerDependencies = new HashMap<>();
static {
EventBusesHooks.whenAvailable(ArchitecturyConstants.MOD_ID, bus -> {
if(Platform.getEnvironment() == Env.CLIENT) {
bus.addListener(ReloadListenerRegistryImpl::addClientReloadListeners);
}
});
NeoForge.EVENT_BUS.addListener(ReloadListenerRegistryImpl::addServerReloadListeners);
}
@@ -62,17 +43,10 @@ public class ReloadListenerRegistryImpl {
serverDataReloadListeners.put(listenerId, listener);
serverDataReloadListenerDependencies.put(listenerId, dependencies);
} else if (type == PackType.CLIENT_RESOURCES) {
clientDataReloadListeners.put(listenerId, listener);
clientDataReloadListenerDependencies.put(listenerId, dependencies);
ClientReloadListenerRegistryImpl.register(listener, listenerId, dependencies);
}
}
@OnlyIn(Dist.CLIENT)
public static void addClientReloadListeners(AddClientReloadListenersEvent event) {
clientDataReloadListeners.forEach(event::addListener);
clientDataReloadListenerDependencies.forEach((listener, dependencies) -> dependencies.forEach(dependency -> event.addDependency(listener, dependency)));
}
public static void addServerReloadListeners(AddServerReloadListenersEvent event) {
serverDataReloadListeners.forEach(event::addListener);
serverDataReloadListenerDependencies.forEach((listener, dependencies) -> dependencies.forEach(dependency -> event.addDependency(listener, dependency)));

View File

@@ -19,23 +19,13 @@
package dev.architectury.registry.menu.forge;
import dev.architectury.platform.hooks.EventBusesHooks;
import dev.architectury.registry.menu.ExtendedMenuProvider;
import dev.architectury.registry.menu.MenuRegistry.ExtendedMenuTypeFactory;
import dev.architectury.registry.menu.MenuRegistry.ScreenFactory;
import dev.architectury.registry.menu.MenuRegistry.SimpleMenuTypeFactory;
import dev.architectury.utils.ArchitecturyConstants;
import net.minecraft.client.gui.screens.MenuScreens;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.gui.screens.inventory.MenuAccess;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.flag.FeatureFlags;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.inventory.MenuType;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.api.distmarker.OnlyIn;
import net.neoforged.neoforge.client.event.RegisterMenuScreensEvent;
import net.neoforged.neoforge.common.NeoForge;
import net.neoforged.neoforge.common.extensions.IMenuTypeExtension;
public class MenuRegistryImpl {
@@ -51,12 +41,4 @@ public class MenuRegistryImpl {
public static <T extends AbstractContainerMenu> MenuType<T> ofExtended(ExtendedMenuTypeFactory<T> factory) {
return IMenuTypeExtension.create(factory::create);
}
@SuppressWarnings("CodeBlock2Expr") // It's neater this way
@OnlyIn(Dist.CLIENT)
public static <H extends AbstractContainerMenu, S extends Screen & MenuAccess<H>> void registerScreenFactory(MenuType<? extends H> type, ScreenFactory<H, S> factory) {
EventBusesHooks.whenAvailable(ArchitecturyConstants.MOD_ID, bus -> {
bus.addListener(RegisterMenuScreensEvent.class, event -> event.register(type, factory::create));
});
}
}

View File

@@ -19,12 +19,7 @@
package dev.architectury.test;
import com.mojang.brigadier.arguments.StringArgumentType;
import dev.architectury.event.events.client.ClientCommandRegistrationEvent;
import dev.architectury.event.events.client.ClientLifecycleEvent;
import dev.architectury.registry.CreativeTabRegistry;
import dev.architectury.registry.client.gui.ClientTooltipComponentRegistry;
import dev.architectury.registry.client.level.entity.EntityRendererRegistry;
import dev.architectury.test.debug.ConsoleMessageSink;
import dev.architectury.test.debug.MessageSink;
import dev.architectury.test.debug.client.ClientOverlayMessageSink;
@@ -35,16 +30,11 @@ import dev.architectury.test.loot.TestLoot;
import dev.architectury.test.networking.TestModNet;
import dev.architectury.test.particle.TestParticles;
import dev.architectury.test.registry.TestRegistries;
import dev.architectury.test.registry.client.TestKeybinds;
import dev.architectury.test.registry.objects.ItemWithTooltip;
import dev.architectury.test.tags.TestTags;
import dev.architectury.test.trade.TestTrades;
import dev.architectury.test.worldgen.TestWorldGeneration;
import dev.architectury.utils.Env;
import dev.architectury.utils.EnvExecutor;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.renderer.entity.CowRenderer;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.world.item.CreativeModeTabs;
import net.minecraft.world.item.ItemStack;
@@ -66,34 +56,11 @@ public class TestMod {
TestBlockInteractions.init();
TestLoot.init();
TestWorldGeneration.initialize();
EnvExecutor.runInEnv(Env.CLIENT, () -> TestMod.Client::initializeClient);
EnvExecutor.runInEnv(Env.CLIENT, () -> TestModClient::initializeClient);
CreativeTabRegistry.modifyBuiltin(BuiltInRegistries.CREATIVE_MODE_TAB.getValue(CreativeModeTabs.BUILDING_BLOCKS), (flags, output, canUseGameMasterBlocks) -> {
ItemStack sword = Items.DIAMOND_SWORD.getDefaultInstance();
output.acceptBefore(new ItemStack(Items.OAK_WOOD), sword);
output.acceptAfter(Blocks.STRIPPED_OAK_LOG, Items.BEDROCK);
});
}
@Environment(EnvType.CLIENT)
public static class Client {
@Environment(EnvType.CLIENT)
public static void initializeClient() {
ClientLifecycleEvent.CLIENT_STARTED.register((client) -> SINK.accept("Client started!"));
ClientLifecycleEvent.CLIENT_STOPPING.register((client) -> SINK.accept("Client stopping!"));
TestKeybinds.initialize();
TestModNet.initializeClient();
EntityRendererRegistry.register(TestRegistries.TEST_ENTITY, CowRenderer::new);
EntityRendererRegistry.register(TestRegistries.TEST_ENTITY_2, CowRenderer::new);
ClientTooltipComponentRegistry.register(ItemWithTooltip.MyTooltipComponent.class, ItemWithTooltip.MyClientTooltipComponent::new);
ClientCommandRegistrationEvent.EVENT.register((dispatcher, access) -> {
dispatcher.register(ClientCommandRegistrationEvent.literal("cool_client")
.then(ClientCommandRegistrationEvent.argument("string", StringArgumentType.string())
.executes(context -> {
String string = StringArgumentType.getString(context, "string");
SINK.accept("Cool client command for " + string);
return 0;
})));
});
}
}
}

View File

@@ -0,0 +1,55 @@
/*
* This file is part of architectury.
* Copyright (C) 2020, 2021, 2022 architectury
*
* 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 dev.architectury.test;
import com.mojang.brigadier.arguments.StringArgumentType;
import dev.architectury.event.events.client.ClientCommandRegistrationEvent;
import dev.architectury.event.events.client.ClientLifecycleEvent;
import dev.architectury.registry.client.gui.ClientTooltipComponentRegistry;
import dev.architectury.registry.client.level.entity.EntityRendererRegistry;
import dev.architectury.test.networking.TestModNet;
import dev.architectury.test.registry.TestRegistries;
import dev.architectury.test.registry.client.TestKeybinds;
import dev.architectury.test.registry.objects.ItemWithTooltip;
import dev.architectury.test.registry.objects.MyClientTooltipComponent;
import net.minecraft.client.renderer.entity.CowRenderer;
import static dev.architectury.test.TestMod.SINK;
public class TestModClient {
public static void initializeClient() {
ClientLifecycleEvent.CLIENT_STARTED.register((client) -> SINK.accept("Client started!"));
ClientLifecycleEvent.CLIENT_STOPPING.register((client) -> SINK.accept("Client stopping!"));
TestKeybinds.initialize();
TestModNet.initializeClient();
EntityRendererRegistry.register(TestRegistries.TEST_ENTITY, CowRenderer::new);
EntityRendererRegistry.register(TestRegistries.TEST_ENTITY_2, CowRenderer::new);
ClientTooltipComponentRegistry.register(ItemWithTooltip.MyTooltipComponent.class, MyClientTooltipComponent::new);
ClientCommandRegistrationEvent.EVENT.register((dispatcher, access) -> {
dispatcher.register(ClientCommandRegistrationEvent.literal("cool_client")
.then(ClientCommandRegistrationEvent.argument("string", StringArgumentType.string())
.executes(context -> {
String string = StringArgumentType.getString(context, "string");
SINK.accept("Cool client command for " + string);
return 0;
})));
});
}
}

View File

@@ -22,8 +22,6 @@ package dev.architectury.test.debug.client;
import com.google.common.collect.Lists;
import dev.architectury.event.events.client.ClientGuiEvent;
import dev.architectury.test.debug.ConsoleMessageSink;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.Util;
import net.minecraft.client.DeltaTracker;
import net.minecraft.client.Minecraft;
@@ -34,7 +32,6 @@ import net.minecraft.util.Mth;
import java.util.Collections;
import java.util.List;
@Environment(EnvType.CLIENT)
public class ClientOverlayMessageSink extends ConsoleMessageSink {
private final List<Message> messages = Collections.synchronizedList(Lists.newArrayList());
@@ -42,7 +39,7 @@ public class ClientOverlayMessageSink extends ConsoleMessageSink {
ClientGuiEvent.RENDER_POST.register((screen, graphics, mouseX, mouseY, delta) -> render(graphics, delta));
ClientGuiEvent.RENDER_HUD.register((graphics, delta) -> {
if (Minecraft.getInstance().screen == null && !Minecraft.getInstance().gui.getDebugOverlay().showDebugScreen()) {
render(graphics, delta);
render(graphics, delta.getRealtimeDeltaTicks());
}
});
}
@@ -53,7 +50,7 @@ public class ClientOverlayMessageSink extends ConsoleMessageSink {
messages.add(0, new Message(Component.literal(message), Util.getMillis()));
}
public void render(GuiGraphics graphics, DeltaTracker delta) {
public void render(GuiGraphics graphics, float delta) {
graphics.pose().pushMatrix();
graphics.pose().scale(0.5f, 0.5f);
var minecraft = Minecraft.getInstance();

View File

@@ -0,0 +1,143 @@
/*
* This file is part of architectury.
* Copyright (C) 2020, 2021, 2022 architectury
*
* 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 dev.architectury.test.events;
import com.mojang.blaze3d.platform.InputConstants;
import dev.architectury.event.CompoundEventResult;
import dev.architectury.event.EventResult;
import dev.architectury.event.events.client.*;
import dev.architectury.event.events.common.InteractionEvent;
import dev.architectury.test.TestMod;
import net.minecraft.client.gui.screens.inventory.AnvilScreen;
import net.minecraft.network.chat.Component;
import static dev.architectury.test.events.DebugEvents.logSide;
import static dev.architectury.test.events.DebugEvents.toSimpleName;
public class ClientDebugEvents {
public static void debugEventsClient() {
ClientTickEvent.CLIENT_LEVEL_PRE.register(instance -> {
try {
// Uncomment the following line to see the profiler spike for root.tick.level.architecturyClientLevelPreTick
//Thread.sleep(10);
} catch (Throwable e) {
e.printStackTrace();
}
});
ClientChatEvent.SEND.register((message, component) -> {
TestMod.SINK.accept("Client chat sent: " + message);
if (message.contains("error")) {
return EventResult.interruptFalse();
}
return EventResult.pass();
});
ClientChatEvent.RECEIVED.register((type, message) -> {
TestMod.SINK.accept("Client chat received: " + message.getString());
if (message.getString().contains("terraria")) {
return CompoundEventResult.interruptTrue(message.copy().append(" + terraria is a great game!"));
}
if (message.getString().contains("potato")) {
return CompoundEventResult.interruptFalse(Component.empty());
}
return CompoundEventResult.pass();
});
ClientLifecycleEvent.CLIENT_LEVEL_LOAD.register(world -> {
TestMod.SINK.accept("Client world loaded: " + world.dimension().location().toString());
});
ClientPlayerEvent.CLIENT_PLAYER_JOIN.register(player -> {
TestMod.SINK.accept(player.getScoreboardName() + " joined (client)");
});
ClientPlayerEvent.CLIENT_PLAYER_QUIT.register(player -> {
if (player != null) {
TestMod.SINK.accept(player.getScoreboardName() + " quit (client)");
}
});
ClientPlayerEvent.CLIENT_PLAYER_RESPAWN.register((oldPlayer, newPlayer) -> {
TestMod.SINK.accept(newPlayer.getScoreboardName() + " respawned (client)");
});
ClientGuiEvent.INIT_PRE.register((screen, access) -> {
TestMod.SINK.accept(toSimpleName(screen) + " initializes");
return EventResult.pass();
});
ClientGuiEvent.INIT_POST.register(((screen, access) -> {
TestMod.SINK.accept(toSimpleName(screen) + " initialized");
}));
InteractionEvent.CLIENT_LEFT_CLICK_AIR.register((player, hand) -> {
TestMod.SINK.accept(player.getScoreboardName() + " left clicks air" + logSide(player.level()));
});
InteractionEvent.CLIENT_RIGHT_CLICK_AIR.register((player, hand) -> {
TestMod.SINK.accept(player.getScoreboardName() + " right clicks air" + logSide(player.level()));
});
ClientRecipeUpdateEvent.EVENT.register(recipeManager -> {
TestMod.SINK.accept("Client recipes received");
});
// ClientTextureStitchEvent.POST.register(atlas -> {
// TestMod.SINK.accept("Client texture stitched: " + atlas.location());
// });
ClientScreenInputEvent.MOUSE_SCROLLED_PRE.register((client, screen, mouseX, mouseY, amountX, amountY) -> {
TestMod.SINK.accept("Screen Mouse scrolled: %.2f x-distance %.2f y-distance", amountX, amountY);
return EventResult.pass();
});
ClientScreenInputEvent.MOUSE_CLICKED_PRE.register((client, screen, event, doubleClick) -> {
TestMod.SINK.accept("Screen Mouse clicked: " + event.button());
return EventResult.pass();
});
ClientScreenInputEvent.MOUSE_RELEASED_PRE.register((client, screen, event) -> {
TestMod.SINK.accept("Screen Mouse released: " + event.button());
return EventResult.pass();
});
ClientScreenInputEvent.MOUSE_DRAGGED_PRE.register((client, screen, event, mouseX2, mouseY2) -> {
TestMod.SINK.accept("Screen Mouse dragged: %d (%d,%d) by (%d,%d)", event.button(), (int) event.x(), (int) event.y(), (int) mouseX2, (int) mouseY2);
return EventResult.pass();
});
ClientScreenInputEvent.CHAR_TYPED_PRE.register((client, screen, characterEvent) -> {
TestMod.SINK.accept("Screen Char typed: " + characterEvent.codepointAsString());
return EventResult.pass();
});
ClientScreenInputEvent.KEY_PRESSED_PRE.register((client, screen, keyEvent) -> {
TestMod.SINK.accept("Screen Key pressed: " + InputConstants.getKey(keyEvent).getDisplayName().getString());
return EventResult.pass();
});
ClientScreenInputEvent.KEY_RELEASED_PRE.register((client, screen, keyEvent) -> {
TestMod.SINK.accept("Screen Key released: " + InputConstants.getKey(keyEvent).getDisplayName().getString());
return EventResult.pass();
});
ClientRawInputEvent.MOUSE_SCROLLED.register((client, amountX, amountY) -> {
TestMod.SINK.accept("Raw Mouse scrolled: %.2f x-distance %.2f y-distance", amountX, amountY);
return EventResult.pass();
});
ClientRawInputEvent.MOUSE_CLICKED_PRE.register((client, event, action) -> {
TestMod.SINK.accept("Raw Mouse clicked: " + event.button());
return EventResult.pass();
});
ClientRawInputEvent.KEY_PRESSED.register((client, keyCode, keyEvent) -> {
TestMod.SINK.accept("Raw Key pressed: " + InputConstants.getKey(keyEvent).getDisplayName().getString());
return EventResult.pass();
});
ClientGuiEvent.SET_SCREEN.register(screen -> {
if (screen instanceof AnvilScreen) {
return CompoundEventResult.interruptFalse(screen);
}
TestMod.SINK.accept("Screen has been changed to " + toSimpleName(screen));
return CompoundEventResult.pass();
});
}
}

View File

@@ -19,19 +19,13 @@
package dev.architectury.test.events;
import com.mojang.blaze3d.platform.InputConstants;
import dev.architectury.event.CompoundEventResult;
import dev.architectury.event.EventResult;
import dev.architectury.event.events.client.*;
import dev.architectury.event.events.common.*;
import dev.architectury.platform.Platform;
import dev.architectury.test.TestMod;
import dev.architectury.utils.Env;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.ChatFormatting;
import net.minecraft.advancements.Advancement;
import net.minecraft.client.gui.screens.inventory.AnvilScreen;
import net.minecraft.core.Position;
import net.minecraft.core.Vec3i;
import net.minecraft.network.chat.Component;
@@ -50,7 +44,7 @@ public class DebugEvents {
public static void initialize() {
debugEvents();
if (Platform.getEnvironment() == Env.CLIENT)
debugEventsClient();
ClientDebugEvents.debugEventsClient();
}
public static void debugEvents() {
@@ -251,116 +245,6 @@ public class DebugEvents {
return " (server)";
}
@Environment(EnvType.CLIENT)
public static void debugEventsClient() {
ClientTickEvent.CLIENT_LEVEL_PRE.register(instance -> {
try {
// Uncomment the following line to see the profiler spike for root.tick.level.architecturyClientLevelPreTick
//Thread.sleep(10);
} catch (Throwable e) {
e.printStackTrace();
}
});
ClientChatEvent.SEND.register((message, component) -> {
TestMod.SINK.accept("Client chat sent: " + message);
if (message.contains("error")) {
return EventResult.interruptFalse();
}
return EventResult.pass();
});
ClientChatEvent.RECEIVED.register((type, message) -> {
TestMod.SINK.accept("Client chat received: " + message.getString());
if (message.getString().contains("terraria")) {
return CompoundEventResult.interruptTrue(message.copy().append(" + terraria is a great game!"));
}
if (message.getString().contains("potato")) {
return CompoundEventResult.interruptFalse(Component.empty());
}
return CompoundEventResult.pass();
});
ClientLifecycleEvent.CLIENT_LEVEL_LOAD.register(world -> {
TestMod.SINK.accept("Client world loaded: " + world.dimension().location().toString());
});
ClientPlayerEvent.CLIENT_PLAYER_JOIN.register(player -> {
TestMod.SINK.accept(player.getScoreboardName() + " joined (client)");
});
ClientPlayerEvent.CLIENT_PLAYER_QUIT.register(player -> {
if (player != null) {
TestMod.SINK.accept(player.getScoreboardName() + " quit (client)");
}
});
ClientPlayerEvent.CLIENT_PLAYER_RESPAWN.register((oldPlayer, newPlayer) -> {
TestMod.SINK.accept(newPlayer.getScoreboardName() + " respawned (client)");
});
ClientGuiEvent.INIT_PRE.register((screen, access) -> {
TestMod.SINK.accept(toSimpleName(screen) + " initializes");
return EventResult.pass();
});
ClientGuiEvent.INIT_POST.register(((screen, access) -> {
TestMod.SINK.accept(toSimpleName(screen) + " initialized");
}));
InteractionEvent.CLIENT_LEFT_CLICK_AIR.register((player, hand) -> {
TestMod.SINK.accept(player.getScoreboardName() + " left clicks air" + logSide(player.level()));
});
InteractionEvent.CLIENT_RIGHT_CLICK_AIR.register((player, hand) -> {
TestMod.SINK.accept(player.getScoreboardName() + " right clicks air" + logSide(player.level()));
});
ClientRecipeUpdateEvent.EVENT.register(recipeManager -> {
TestMod.SINK.accept("Client recipes received");
});
// ClientTextureStitchEvent.POST.register(atlas -> {
// TestMod.SINK.accept("Client texture stitched: " + atlas.location());
// });
ClientScreenInputEvent.MOUSE_SCROLLED_PRE.register((client, screen, mouseX, mouseY, amountX, amountY) -> {
TestMod.SINK.accept("Screen Mouse scrolled: %.2f x-distance %.2f y-distance", amountX, amountY);
return EventResult.pass();
});
ClientScreenInputEvent.MOUSE_CLICKED_PRE.register((client, screen, mouseX, mouseY, button) -> {
TestMod.SINK.accept("Screen Mouse clicked: " + button);
return EventResult.pass();
});
ClientScreenInputEvent.MOUSE_RELEASED_PRE.register((client, screen, mouseX, mouseY, button) -> {
TestMod.SINK.accept("Screen Mouse released: " + button);
return EventResult.pass();
});
ClientScreenInputEvent.MOUSE_DRAGGED_PRE.register((client, screen, mouseX1, mouseY1, button, mouseX2, mouseY2) -> {
TestMod.SINK.accept("Screen Mouse dragged: %d (%d,%d) by (%d,%d)", button, (int) mouseX1, (int) mouseY1, (int) mouseX2, (int) mouseY2);
return EventResult.pass();
});
ClientScreenInputEvent.CHAR_TYPED_PRE.register((client, screen, character, keyCode) -> {
TestMod.SINK.accept("Screen Char typed: " + character);
return EventResult.pass();
});
ClientScreenInputEvent.KEY_PRESSED_PRE.register((client, screen, keyCode, scanCode, modifiers) -> {
TestMod.SINK.accept("Screen Key pressed: " + InputConstants.getKey(keyCode, scanCode).getDisplayName().getString());
return EventResult.pass();
});
ClientScreenInputEvent.KEY_RELEASED_PRE.register((client, screen, keyCode, scanCode, modifiers) -> {
TestMod.SINK.accept("Screen Key released: " + InputConstants.getKey(keyCode, scanCode).getDisplayName().getString());
return EventResult.pass();
});
ClientRawInputEvent.MOUSE_SCROLLED.register((client, amountX, amountY) -> {
TestMod.SINK.accept("Raw Mouse scrolled: %.2f x-distance %.2f y-distance", amountX, amountY);
return EventResult.pass();
});
ClientRawInputEvent.MOUSE_CLICKED_PRE.register((client, button, action, mods) -> {
TestMod.SINK.accept("Raw Mouse clicked: " + button);
return EventResult.pass();
});
ClientRawInputEvent.KEY_PRESSED.register((client, keyCode, scanCode, action, modifiers) -> {
TestMod.SINK.accept("Raw Key pressed: " + InputConstants.getKey(keyCode, scanCode).getDisplayName().getString());
return EventResult.pass();
});
ClientGuiEvent.SET_SCREEN.register(screen -> {
if (screen instanceof AnvilScreen) {
return CompoundEventResult.interruptFalse(screen);
}
TestMod.SINK.accept("Screen has been changed to " + toSimpleName(screen));
return CompoundEventResult.pass();
});
}
private static String chunkPos(int x, int z) {
return "[" + x + ", " + z + "]";
}
@@ -369,7 +253,7 @@ public class DebugEvents {
return "[" + x + ", " + y + ", " + z + "]";
}
private static String toSimpleName(Object o) {
static String toSimpleName(Object o) {
return o == null ? "null" : o.getClass().getSimpleName() + "@" + Integer.toHexString(o.hashCode());
}
}

View File

@@ -38,7 +38,7 @@ public final class TestBlockInteractions {
return ctx.getLevel().isDarkOutside();
}, ctx -> {
BlockPos pos = ctx.getClickedPos();
if (!ctx.getLevel().isClientSide) {
if (!ctx.getLevel().isClientSide()) {
Player player = ctx.getPlayer();
if (player != null)
player.displayClientMessage(Component.literal("Thou has successfully committed the dark arts of alchemy!!"), false);

View File

@@ -20,36 +20,26 @@
package dev.architectury.test.networking;
import dev.architectury.networking.NetworkManager;
import dev.architectury.networking.simple.BaseC2SMessage;
import dev.architectury.networking.simple.MessageType;
import net.minecraft.network.RegistryFriendlyByteBuf;
import net.minecraft.network.chat.Component;
import net.minecraft.network.codec.ByteBufCodecs;
import net.minecraft.network.codec.StreamCodec;
import net.minecraft.network.protocol.common.custom.CustomPacketPayload;
import net.minecraft.resources.ResourceLocation;
public class ButtonClickedMessage extends BaseC2SMessage {
private final int buttonId;
/**
* To send this message from client to server, call new ButtonClickedMessage(id).sendToServer()
*/
public ButtonClickedMessage(int id) {
buttonId = id;
}
public ButtonClickedMessage(RegistryFriendlyByteBuf buf) {
buttonId = buf.readVarInt();
}
public record ButtonClickedMessage(int buttonId) implements CustomPacketPayload {
public static final Type<ButtonClickedMessage> TYPE = new Type<>(ResourceLocation.fromNamespaceAndPath("architectury", "button_clicked"));
public static final StreamCodec<RegistryFriendlyByteBuf, ButtonClickedMessage> STREAM_CODEC = StreamCodec.composite(
ByteBufCodecs.VAR_INT,
ButtonClickedMessage::buttonId,
ButtonClickedMessage::new
);
@Override
public MessageType getType() {
return TestModNet.BUTTON_CLICKED;
public Type<? extends CustomPacketPayload> type() {
return TYPE;
}
@Override
public void write(RegistryFriendlyByteBuf buf) {
buf.writeVarInt(buttonId);
}
@Override
public void handle(NetworkManager.PacketContext context) {
context.getPlayer().displayClientMessage(Component.literal("You clicked button #" + buttonId), false);
}

View File

@@ -20,39 +20,27 @@
package dev.architectury.test.networking;
import dev.architectury.networking.NetworkManager;
import dev.architectury.networking.simple.BaseS2CMessage;
import dev.architectury.networking.simple.MessageType;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.RegistryFriendlyByteBuf;
import net.minecraft.network.chat.Component;
import net.minecraft.network.codec.ByteBufCodecs;
import net.minecraft.network.codec.StreamCodec;
import net.minecraft.network.protocol.common.custom.CustomPacketPayload;
import net.minecraft.resources.ResourceLocation;
public class SyncDataMessage extends BaseS2CMessage {
private final CompoundTag serverData;
/**
* To send this message, call new SyncDataMessage(tag).sendToPlayer(player) / sendToAll(server) / etc.
*
* @see BaseS2CMessage
*/
public SyncDataMessage(CompoundTag tag) {
serverData = tag;
}
public SyncDataMessage(RegistryFriendlyByteBuf buf) {
serverData = buf.readNbt();
}
public record SyncDataMessage(CompoundTag serverData) implements CustomPacketPayload {
public static final Type<SyncDataMessage> TYPE = new Type<>(ResourceLocation.fromNamespaceAndPath("architectury", "sync_data"));
public static final StreamCodec<RegistryFriendlyByteBuf, SyncDataMessage> STREAM_CODEC = StreamCodec.composite(
ByteBufCodecs.COMPOUND_TAG,
SyncDataMessage::serverData,
SyncDataMessage::new
);
@Override
public MessageType getType() {
return TestModNet.SYNC_DATA;
public Type<? extends CustomPacketPayload> type() {
return TYPE;
}
@Override
public void write(RegistryFriendlyByteBuf buf) {
buf.writeNbt(serverData);
}
@Override
public void handle(NetworkManager.PacketContext context) {
context.getPlayer().displayClientMessage(Component.literal("Received data from server: " + serverData), false);
}

View File

@@ -22,8 +22,6 @@ package dev.architectury.test.networking;
import dev.architectury.event.events.client.ClientPlayerEvent;
import dev.architectury.event.events.common.PlayerEvent;
import dev.architectury.networking.NetworkManager;
import dev.architectury.networking.simple.MessageType;
import dev.architectury.networking.simple.SimpleNetworkManager;
import dev.architectury.networking.transformers.SplitPacketTransformer;
import dev.architectury.test.TestMod;
import io.netty.buffer.Unpooled;
@@ -37,13 +35,6 @@ import java.util.Collections;
import java.util.List;
public interface TestModNet {
SimpleNetworkManager NET = SimpleNetworkManager.create(TestMod.MOD_ID);
// An example Client to Server message
MessageType BUTTON_CLICKED = NET.registerC2S("button_clicked", ButtonClickedMessage::new);
// An example Server to Client message
MessageType SYNC_DATA = NET.registerS2C("sync_data", SyncDataMessage::new);
ResourceLocation BIG_DATA = ResourceLocation.fromNamespaceAndPath(TestMod.MOD_ID, "big_data");
ResourceLocation SERVER_TO_CLIENT_TEST = ResourceLocation.fromNamespaceAndPath(TestMod.MOD_ID, "s2c_test");
CustomPacketPayload.Type<ServerToClientTestPayload> SERVER_TO_CLIENT_TEST_PAYLOAD = new CustomPacketPayload.Type<>(ResourceLocation.fromNamespaceAndPath(TestMod.MOD_ID, "s2c_test_payload"));
@@ -51,6 +42,8 @@ public interface TestModNet {
String BIG_STRING = StringUtils.repeat('a', 100000);
static void initialize() {
NetworkManager.registerReceiver(NetworkManager.Side.C2S, ButtonClickedMessage.TYPE, ButtonClickedMessage.STREAM_CODEC, ButtonClickedMessage::handle);
NetworkManager.registerReceiver(NetworkManager.Side.C2S, SyncDataMessage.TYPE, SyncDataMessage.STREAM_CODEC, SyncDataMessage::handle);
NetworkManager.registerReceiver(NetworkManager.Side.C2S, BIG_DATA, Collections.singletonList(new SplitPacketTransformer()), (buf, context) -> {
String utf = buf.readUtf(Integer.MAX_VALUE / 4);
if (utf.equals(BIG_STRING)) {

View File

@@ -21,7 +21,6 @@ package dev.architectury.test.registry;
import dev.architectury.core.fluid.ArchitecturyFluidAttributes;
import dev.architectury.core.fluid.SimpleArchitecturyFluidAttributes;
import dev.architectury.core.item.ArchitecturySpawnEggItem;
import dev.architectury.hooks.level.entity.EntityHooks;
import dev.architectury.platform.Platform;
import dev.architectury.registry.CreativeTabRegistry;
@@ -45,10 +44,7 @@ import net.minecraft.world.effect.MobEffectCategory;
import net.minecraft.world.effect.MobEffectInstance;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.food.FoodProperties;
import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.CreativeModeTab;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.*;
import net.minecraft.world.item.component.Consumables;
import net.minecraft.world.item.consume_effects.ApplyStatusEffectsConsumeEffect;
import net.minecraft.world.item.crafting.CustomRecipe;
@@ -58,10 +54,12 @@ import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.LiquidBlock;
import net.minecraft.world.level.block.SoundType;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.material.FlowingFluid;
import net.minecraft.world.level.material.Fluid;
import net.minecraft.world.level.material.PushReaction;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape;
@@ -124,11 +122,9 @@ public class TestRegistries {
.setId(id(Registries.ITEM, "test_edible")));
});
public static final RegistrySupplier<Item> TEST_SPAWN_EGG = ITEMS.register("test_spawn_egg", () ->
new ArchitecturySpawnEggItem(TestRegistries.TEST_ENTITY,
new Item.Properties().arch$tab(TestRegistries.TEST_TAB).setId(id(Registries.ITEM, "test_spawn_egg"))));
new SpawnEggItem(new Item.Properties().arch$tab(TestRegistries.TEST_TAB).setId(id(Registries.ITEM, "test_spawn_egg")).spawnEgg(TestRegistries.TEST_ENTITY.get())));
public static final RegistrySupplier<Item> TEST_SPAWN_EGG_2 = ITEMS.register("test_spawn_egg_2", () ->
new ArchitecturySpawnEggItem(TestRegistries.TEST_ENTITY_2,
new Item.Properties().arch$tab(TestRegistries.TEST_TAB).setId(id(Registries.ITEM, "test_spawn_egg_2"))));
new SpawnEggItem(new Item.Properties().arch$tab(TestRegistries.TEST_TAB).setId(id(Registries.ITEM, "test_spawn_egg_2")).spawnEgg(TestRegistries.TEST_ENTITY_2.get())));
public static final RegistrySupplier<Item> TEST_FLUID_BUCKET = ITEMS.register("test_fluid_bucket", () -> {
try {
@@ -161,7 +157,7 @@ public class TestRegistries {
// In example mod the forge class isn't being replaced, this is not required in mods depending on architectury
return (LiquidBlock) Class.forName(!Platform.isForge() ? "dev.architectury.core.block.ArchitecturyLiquidBlock" : "dev.architectury.core.block.forge.imitator.ArchitecturyLiquidBlock")
.getDeclaredConstructor(Supplier.class, BlockBehaviour.Properties.class)
.newInstance(TestRegistries.TEST_FLUID, BlockBehaviour.Properties.ofLegacyCopy(Blocks.WATER).noCollission().strength(100.0F).noLootTable().setId(id(Registries.BLOCK, "test_fluid")));
.newInstance(TestRegistries.TEST_FLUID, BlockBehaviour.Properties.ofLegacyCopy(Blocks.WATER).replaceable().noCollision().strength(100.0F).pushReaction(PushReaction.DESTROY).noLootTable().liquid().sound(SoundType.EMPTY).setId(id(Registries.BLOCK, "test_fluid")));
} catch (InstantiationException | ClassNotFoundException | NoSuchMethodException | InvocationTargetException |
IllegalAccessException e) {
throw new RuntimeException(e);
@@ -212,10 +208,10 @@ public class TestRegistries {
public static void initialize() {
TABS.register();
MOB_EFFECTS.register();
ENTITY_TYPES.register();
FLUIDS.register();
BLOCKS.register();
ITEMS.register();
ENTITY_TYPES.register();
RECIPE_TYPES.register();
RECIPE_SERIALIZERS.register();
EntityAttributeRegistry.register(TEST_ENTITY, TestEntity::createAttributes);

View File

@@ -23,16 +23,15 @@ import com.mojang.blaze3d.platform.InputConstants;
import dev.architectury.event.events.client.ClientTickEvent;
import dev.architectury.registry.client.keymappings.KeyMappingRegistry;
import dev.architectury.test.TestMod;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.KeyMapping;
import net.minecraft.client.resources.language.I18n;
import net.minecraft.resources.ResourceLocation;
import org.lwjgl.glfw.GLFW;
public class TestKeybinds {
@Environment(EnvType.CLIENT)
public static void initialize() {
var mapping = new KeyMapping("key.architectury-test.test", InputConstants.Type.KEYSYM, GLFW.GLFW_KEY_O, "category.architectury-test");
var category = KeyMapping.Category.register(ResourceLocation.fromNamespaceAndPath("architectury", "architectury-test"));
var mapping = new KeyMapping("key.architectury-test.test", InputConstants.Type.KEYSYM, GLFW.GLFW_KEY_O, category);
KeyMappingRegistry.register(mapping);
ClientTickEvent.CLIENT_POST.register(instance -> {
while (mapping.consumeClick()) {

Some files were not shown because too many files have changed in this diff Show More