mirror of
https://github.com/architectury/architectury-api.git
synced 2026-04-03 05:57:40 -05:00
Refactor and 1.17-pre1 (#96)
* Fix #94 Signed-off-by: shedaniel <daniel@shedaniel.me> * Add Chunk data save and load events, closes #89 (#92) * Created Chunk save and load event. Closes #89 * Fixed missing licence * Update common/src/main/java/me/shedaniel/architectury/event/events/ChunkEvent.java * Update common/src/main/java/me/shedaniel/architectury/event/events/ChunkEvent.java * Update common/src/main/java/me/shedaniel/architectury/event/events/ChunkEvent.java * Supply ServerLevel in ChunkEvent.LOAD, style cleanup Signed-off-by: shedaniel <daniel@shedaniel.me> * Add "Data" suffix to Chunk IO Events and mark level as nullable for load * Update common/src/main/java/me/shedaniel/architectury/event/events/ChunkEvent.java * Bump to 1.16 Co-authored-by: shedaniel <daniel@shedaniel.me> Co-authored-by: Max <maxh2709@gmail.com> * Update pr.yml * Add NetworkManager hook for Entity spawn packets (#88) * New utility hook for creating a entity spawn packet. before every mod had to implement this in itself. * Apply suggestions from code review Co-authored-by: shedaniel <daniel@shedaniel.me> * Update common/src/main/java/me/shedaniel/architectury/networking/NetworkManager.java * Update common/src/main/java/me/shedaniel/architectury/networking/NetworkManager.java * Properly implement SpawnEntityPacket & Format style Signed-off-by: shedaniel <daniel@shedaniel.me> * Format Signed-off-by: shedaniel <daniel@shedaniel.me> * createEntitySpawnPacket -> createAddEntityPacket for mojmap consistency Signed-off-by: shedaniel <daniel@shedaniel.me> * Bump version to 1.17 Co-authored-by: Max <maxh2709@gmail.com> Co-authored-by: shedaniel <daniel@shedaniel.me> * Add Javadocs for all events (#91) * javadoc for ClientChatEvent * javadoc for ClientPlayerEvent * javadoc for ClientRawInputEvent * Added javadoc for ClientScreenInputEvent * Bit refactoring and removed javadoc @see to the caller methods * Add javadoc for BlockEvent * Add javadoc for ChatEvent * Add javadoc for CommandPerformEvent and CommandRegistrationEvent * Add javadoc for EntityEvent * Add javadoc for ExplosionEvent * Add javadoc for GuiEvent * Add javadoc for InteractionEvent * Add javadoc for LightningEvent, RecipeUpdateEvent & TextureStitchEvent * Add javadoc for LifecycleEvent & ClientLifecycleEvent * Add javadoc for TooltipEvent * Add javadoc for TickEvent and partly PlayerEvent * More javadoc for PlayerEvent * Finally all event have javadoc * Update common/src/main/java/me/shedaniel/architectury/event/events/CommandPerformEvent.java Co-authored-by: Juuxel <6596629+Juuxel@users.noreply.github.com> * Update common/src/main/java/me/shedaniel/architectury/event/events/CommandPerformEvent.java Co-authored-by: Juuxel <6596629+Juuxel@users.noreply.github.com> * Update common/src/main/java/me/shedaniel/architectury/event/events/CommandPerformEvent.java Co-authored-by: Juuxel <6596629+Juuxel@users.noreply.github.com> * Update common/src/main/java/me/shedaniel/architectury/event/events/ChatEvent.java Co-authored-by: Juuxel <6596629+Juuxel@users.noreply.github.com> * Update common/src/main/java/me/shedaniel/architectury/event/events/CommandRegistrationEvent.java Co-authored-by: Juuxel <6596629+Juuxel@users.noreply.github.com> * Update common/src/main/java/me/shedaniel/architectury/event/events/EntityEvent.java Co-authored-by: Juuxel <6596629+Juuxel@users.noreply.github.com> * Update common/src/main/java/me/shedaniel/architectury/event/events/EntityEvent.java Co-authored-by: Juuxel <6596629+Juuxel@users.noreply.github.com> * Update common/src/main/java/me/shedaniel/architectury/event/events/EntityEvent.java Co-authored-by: Juuxel <6596629+Juuxel@users.noreply.github.com> * Update common/src/main/java/me/shedaniel/architectury/event/events/EntityEvent.java Co-authored-by: Juuxel <6596629+Juuxel@users.noreply.github.com> * Update common/src/main/java/me/shedaniel/architectury/event/events/client/ClientScreenInputEvent.java Co-authored-by: Juuxel <6596629+Juuxel@users.noreply.github.com> * Update common/src/main/java/me/shedaniel/architectury/event/events/client/ClientScreenInputEvent.java Co-authored-by: Juuxel <6596629+Juuxel@users.noreply.github.com> * Update common/src/main/java/me/shedaniel/architectury/event/events/BlockEvent.java Co-authored-by: Max <maxh2709@gmail.com> * Update common/src/main/java/me/shedaniel/architectury/event/events/BlockEvent.java Co-authored-by: Max <maxh2709@gmail.com> * Update common/src/main/java/me/shedaniel/architectury/event/events/BlockEvent.java Co-authored-by: Max <maxh2709@gmail.com> * Update common/src/main/java/me/shedaniel/architectury/event/events/BlockEvent.java Co-authored-by: Max <maxh2709@gmail.com> * Update common/src/main/java/me/shedaniel/architectury/event/events/LifecycleEvent.java Co-authored-by: Max <maxh2709@gmail.com> * Update common/src/main/java/me/shedaniel/architectury/event/events/LifecycleEvent.java Co-authored-by: Max <maxh2709@gmail.com> * Update common/src/main/java/me/shedaniel/architectury/event/events/LifecycleEvent.java Co-authored-by: Max <maxh2709@gmail.com> * Update common/src/main/java/me/shedaniel/architectury/event/events/PlayerEvent.java Co-authored-by: Max <maxh2709@gmail.com> * Apply suggestions from code review Co-authored-by: Max <maxh2709@gmail.com> Co-authored-by: Juuxel <6596629+Juuxel@users.noreply.github.com> * Apply suggestions from code review Co-authored-by: Juuxel <6596629+Juuxel@users.noreply.github.com> Co-authored-by: Max <maxh2709@gmail.com> * Apply suggestions from code review Co-authored-by: Max <maxh2709@gmail.com> Co-authored-by: Juuxel <6596629+Juuxel@users.noreply.github.com> * Apply suggestions from code review Co-authored-by: Max <maxh2709@gmail.com> Co-authored-by: Juuxel <6596629+Juuxel@users.noreply.github.com> * Apply suggestions from code review Co-authored-by: Max <maxh2709@gmail.com> Co-authored-by: Juuxel <6596629+Juuxel@users.noreply.github.com> * Apply suggestions from code review * Apply suggestions from code review Co-authored-by: shedaniel <daniel@shedaniel.me> * Applied some more reviews * Applied some more reviews * Applied suggestions * Reformat and apply some minor suggestions * Apply suggestions from review (first batch) * Remove double return javadoc * Apply suggestions from code review Co-authored-by: shedaniel <daniel@shedaniel.me> * Add "scaled" to mouse coordinates * Final touches Signed-off-by: shedaniel <daniel@shedaniel.me> * Remove invalid tips Signed-off-by: shedaniel <daniel@shedaniel.me> Co-authored-by: Juuxel <6596629+Juuxel@users.noreply.github.com> Co-authored-by: Max <maxh2709@gmail.com> Co-authored-by: shedaniel <daniel@shedaniel.me> * Refactor Signed-off-by: shedaniel <daniel@shedaniel.me> * Update common/src/main/java/dev/architectury/event/events/common/InteractionEvent.java Co-authored-by: Max <maxh2709@gmail.com> * Apply suggestions from code review Co-authored-by: Max <maxh2709@gmail.com> * attack -> hurt Signed-off-by: shedaniel <daniel@shedaniel.me> * Update @param for InteractionEvent#FARMLAND_TRAMPLE Signed-off-by: shedaniel <daniel@shedaniel.me> * world -> level Signed-off-by: shedaniel <daniel@shedaniel.me> * Relocate hooks Signed-off-by: shedaniel <daniel@shedaniel.me> * Organize imports Signed-off-by: shedaniel <daniel@shedaniel.me> * Registry -> Registrar Please voice out your opinion!! Signed-off-by: shedaniel <daniel@shedaniel.me> * Some more renames itemOptional -> optionalItem RegistryBuilder -> RegistrarBuilder RegistryOption -> RegistrarOption Not forcing RegistryEntry on new registries, vanilla types don't have them Signed-off-by: shedaniel <daniel@shedaniel.me> * Java 16-ification Signed-off-by: shedaniel <daniel@shedaniel.me> * Optimise imports after the var change Signed-off-by: shedaniel <daniel@shedaniel.me> * Un-minimize architectury-common.mixins.json Signed-off-by: shedaniel <daniel@shedaniel.me> Co-authored-by: canitzp <12819060+canitzp@users.noreply.github.com> Co-authored-by: Max <maxh2709@gmail.com> Co-authored-by: Juuxel <6596629+Juuxel@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 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.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 java.util.Map;
|
||||
|
||||
public class ModMenuCompatibility implements ModMenuApi {
|
||||
private static final Map<String, ConfigScreenFactory<?>> FACTORIES = Maps.newHashMap();
|
||||
|
||||
@Override
|
||||
public Map<String, ConfigScreenFactory<?>> getProvidedConfigScreenFactories() {
|
||||
validateMap();
|
||||
return FACTORIES;
|
||||
}
|
||||
|
||||
private void validateMap() {
|
||||
for (var entry : PlatformImpl.CONFIG_SCREENS.entrySet()) {
|
||||
if (!FACTORIES.containsKey(entry.getKey())) {
|
||||
FACTORIES.put(entry.getKey(), entry.getValue()::provide);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 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.event.fabric;
|
||||
|
||||
import dev.architectury.event.Event;
|
||||
import dev.architectury.event.EventActor;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class EventFactoryImpl {
|
||||
public static <T> Event<Consumer<T>> attachToForge(Event<Consumer<T>> event) {
|
||||
return event;
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public static <T> Event<EventActor<T>> attachToForgeEventActor(Event<EventActor<T>> event) {
|
||||
return event;
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public static <T> Event<EventActor<T>> attachToForgeEventActorCancellable(Event<EventActor<T>> event) {
|
||||
return event;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 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.event.fabric;
|
||||
|
||||
import dev.architectury.event.events.client.ClientGuiEvent;
|
||||
import dev.architectury.event.events.client.ClientLifecycleEvent;
|
||||
import dev.architectury.event.events.client.ClientTickEvent;
|
||||
import dev.architectury.event.events.client.ClientTooltipEvent;
|
||||
import dev.architectury.event.events.common.CommandRegistrationEvent;
|
||||
import dev.architectury.event.events.common.InteractionEvent;
|
||||
import dev.architectury.event.events.common.LifecycleEvent;
|
||||
import dev.architectury.event.events.common.TickEvent;
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents;
|
||||
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
|
||||
import net.fabricmc.fabric.api.client.item.v1.ItemTooltipCallback;
|
||||
import net.fabricmc.fabric.api.client.rendering.v1.HudRenderCallback;
|
||||
import net.fabricmc.fabric.api.command.v1.CommandRegistrationCallback;
|
||||
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
|
||||
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents;
|
||||
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerWorldEvents;
|
||||
import net.fabricmc.fabric.api.event.player.AttackBlockCallback;
|
||||
import net.fabricmc.fabric.api.event.player.UseBlockCallback;
|
||||
import net.fabricmc.fabric.api.event.player.UseItemCallback;
|
||||
import net.minecraft.commands.Commands;
|
||||
|
||||
public class EventHandlerImpl {
|
||||
@Environment(EnvType.CLIENT)
|
||||
public static void registerClient() {
|
||||
ClientLifecycleEvents.CLIENT_STARTED.register(instance -> ClientLifecycleEvent.CLIENT_STARTED.invoker().stateChanged(instance));
|
||||
ClientLifecycleEvents.CLIENT_STOPPING.register(instance -> ClientLifecycleEvent.CLIENT_STOPPING.invoker().stateChanged(instance));
|
||||
|
||||
ClientTickEvents.START_CLIENT_TICK.register(instance -> ClientTickEvent.CLIENT_PRE.invoker().tick(instance));
|
||||
ClientTickEvents.END_CLIENT_TICK.register(instance -> ClientTickEvent.CLIENT_POST.invoker().tick(instance));
|
||||
ClientTickEvents.START_WORLD_TICK.register(instance -> ClientTickEvent.CLIENT_LEVEL_PRE.invoker().tick(instance));
|
||||
ClientTickEvents.END_WORLD_TICK.register(instance -> ClientTickEvent.CLIENT_LEVEL_POST.invoker().tick(instance));
|
||||
|
||||
ItemTooltipCallback.EVENT.register((itemStack, tooltipFlag, list) -> ClientTooltipEvent.ITEM.invoker().append(itemStack, list, tooltipFlag));
|
||||
HudRenderCallback.EVENT.register((matrices, tickDelta) -> ClientGuiEvent.RENDER_HUD.invoker().renderHud(matrices, tickDelta));
|
||||
}
|
||||
|
||||
public static void registerCommon() {
|
||||
ServerLifecycleEvents.SERVER_STARTING.register(instance -> LifecycleEvent.SERVER_BEFORE_START.invoker().stateChanged(instance));
|
||||
ServerLifecycleEvents.SERVER_STARTED.register(instance -> LifecycleEvent.SERVER_STARTED.invoker().stateChanged(instance));
|
||||
ServerLifecycleEvents.SERVER_STOPPING.register(instance -> LifecycleEvent.SERVER_STOPPING.invoker().stateChanged(instance));
|
||||
ServerLifecycleEvents.SERVER_STOPPED.register(instance -> LifecycleEvent.SERVER_STOPPED.invoker().stateChanged(instance));
|
||||
|
||||
ServerTickEvents.START_SERVER_TICK.register(instance -> TickEvent.SERVER_PRE.invoker().tick(instance));
|
||||
ServerTickEvents.END_SERVER_TICK.register(instance -> TickEvent.SERVER_POST.invoker().tick(instance));
|
||||
ServerTickEvents.START_WORLD_TICK.register(instance -> TickEvent.SERVER_LEVEL_PRE.invoker().tick(instance));
|
||||
ServerTickEvents.END_WORLD_TICK.register(instance -> TickEvent.SERVER_LEVEL_POST.invoker().tick(instance));
|
||||
|
||||
ServerWorldEvents.LOAD.register((server, world) -> LifecycleEvent.SERVER_LEVEL_LOAD.invoker().act(world));
|
||||
ServerWorldEvents.UNLOAD.register((server, world) -> LifecycleEvent.SERVER_LEVEL_UNLOAD.invoker().act(world));
|
||||
|
||||
CommandRegistrationCallback.EVENT.register((commandDispatcher, b) -> CommandRegistrationEvent.EVENT.invoker().register(commandDispatcher, b ? Commands.CommandSelection.DEDICATED : Commands.CommandSelection.INTEGRATED));
|
||||
|
||||
UseItemCallback.EVENT.register((player, world, hand) -> InteractionEvent.RIGHT_CLICK_ITEM.invoker().click(player, hand).asMinecraft());
|
||||
UseBlockCallback.EVENT.register((player, world, hand, hitResult) -> InteractionEvent.RIGHT_CLICK_BLOCK.invoker().click(player, hand, hitResult.getBlockPos(), hitResult.getDirection()).asMinecraft());
|
||||
AttackBlockCallback.EVENT.register((player, world, hand, pos, face) -> InteractionEvent.LEFT_CLICK_BLOCK.invoker().click(player, hand, pos, face).asMinecraft());
|
||||
}
|
||||
|
||||
@Environment(EnvType.SERVER)
|
||||
public static void registerServer() {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 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.block.fabric;
|
||||
|
||||
import net.fabricmc.fabric.api.block.entity.BlockEntityClientSerializable;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class BlockEntityHooksImpl {
|
||||
/*
|
||||
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
public static void syncData(BlockEntity entity) {
|
||||
if (entity instanceof BlockEntityClientSerializable) {
|
||||
((BlockEntityClientSerializable) entity).sync();
|
||||
} else {
|
||||
var world = Objects.requireNonNull(entity.getLevel());
|
||||
if (!(world instanceof ServerLevel)) {
|
||||
throw new IllegalStateException("Cannot call sync() on the logical client! Did you check world.isClient first?");
|
||||
} else {
|
||||
((ServerLevel) world).getChunkSource().blockChanged(entity.getBlockPos());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 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.screen.fabric;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
import net.minecraft.client.gui.components.AbstractWidget;
|
||||
import net.minecraft.client.gui.components.Widget;
|
||||
import net.minecraft.client.gui.components.events.GuiEventListener;
|
||||
import net.minecraft.client.gui.narration.NarratableEntry;
|
||||
import net.minecraft.client.gui.screens.Screen;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public class ScreenHooksImpl {
|
||||
public static List<NarratableEntry> getNarratables(Screen screen) {
|
||||
return screen.narratables;
|
||||
}
|
||||
|
||||
public static List<Widget> getRenderables(Screen screen) {
|
||||
return screen.renderables;
|
||||
}
|
||||
|
||||
public static <T extends AbstractWidget & Widget & NarratableEntry> T addRenderableWidget(Screen screen, T widget) {
|
||||
return screen.addRenderableWidget(widget);
|
||||
}
|
||||
|
||||
public static <T extends Widget> T addRenderableOnly(Screen screen, T listener) {
|
||||
return screen.addRenderableOnly(listener);
|
||||
}
|
||||
|
||||
public static <T extends GuiEventListener & NarratableEntry> T addWidget(Screen screen, T listener) {
|
||||
return screen.addWidget(listener);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 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.fabric;
|
||||
|
||||
import net.minecraft.world.item.DyeColor;
|
||||
|
||||
public class DyeColorHooksImpl {
|
||||
public static int getColorValue(DyeColor color) {
|
||||
var colors = color.getTextureDiffuseColors();
|
||||
return ((int) (colors[0] * 255.0F + 0.5D) & 255) << 16 | ((int) (colors[1] * 255.0F + 0.5D) & 255) << 8 | (int) (colors[2] * 255.0F + 0.5D);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 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.fabric;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import net.minecraft.server.packs.repository.PackRepository;
|
||||
import net.minecraft.server.packs.repository.RepositorySource;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class PackRepositoryHooksImpl {
|
||||
public static void addSource(PackRepository repository, RepositorySource source) {
|
||||
List<RepositorySource> set = new ArrayList<>(repository.sources);
|
||||
set.add(source);
|
||||
repository.sources = ImmutableSet.copyOf(set);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 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.fabric;
|
||||
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
|
||||
public interface PersistentEntitySectionManagerHooks {
|
||||
void architectury_attachLevel(ServerLevel level);
|
||||
}
|
||||
@@ -0,0 +1,191 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 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.fluid.fabric;
|
||||
|
||||
import dev.architectury.fluid.FluidStack;
|
||||
import dev.architectury.platform.Platform;
|
||||
import dev.architectury.utils.Env;
|
||||
import dev.architectury.utils.NbtType;
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
import net.fabricmc.fabric.api.client.render.fluid.v1.FluidRenderHandlerRegistry;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.TranslatableComponent;
|
||||
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 org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class FluidStackHooksImpl {
|
||||
public static Component getName(FluidStack stack) {
|
||||
if (Platform.getEnvironment() == Env.CLIENT) {
|
||||
return getNameClient(stack);
|
||||
}
|
||||
|
||||
return new TranslatableComponent(getTranslationKey(stack));
|
||||
}
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
private static Component getNameClient(FluidStack stack) {
|
||||
return stack.getFluid().defaultFluidState().createLegacyBlock().getBlock().getName();
|
||||
}
|
||||
|
||||
public static String getTranslationKey(FluidStack stack) {
|
||||
var id = Registry.FLUID.getKey(stack.getFluid());
|
||||
return "block." + id.getNamespace() + "." + id.getPath();
|
||||
}
|
||||
|
||||
public static FluidStack read(FriendlyByteBuf buf) {
|
||||
var fluid = Objects.requireNonNull(Registry.FLUID.get(buf.readResourceLocation()));
|
||||
var amount = buf.readVarLong();
|
||||
var tag = buf.readNbt();
|
||||
if (fluid == Fluids.EMPTY) return FluidStack.empty();
|
||||
return FluidStack.create(fluid, amount, tag);
|
||||
}
|
||||
|
||||
public static void write(FluidStack stack, FriendlyByteBuf buf) {
|
||||
buf.writeResourceLocation(Registry.FLUID.getKey(stack.getFluid()));
|
||||
buf.writeVarLong(stack.getAmount());
|
||||
buf.writeNbt(stack.getTag());
|
||||
}
|
||||
|
||||
public static FluidStack read(CompoundTag tag) {
|
||||
if (tag == null || !tag.contains("id", NbtType.STRING)) {
|
||||
return FluidStack.empty();
|
||||
}
|
||||
|
||||
var fluid = Registry.FLUID.get(new ResourceLocation(tag.getString("id")));
|
||||
if (fluid == null || fluid == Fluids.EMPTY) {
|
||||
return FluidStack.empty();
|
||||
}
|
||||
var amount = tag.getLong("amount");
|
||||
var stack = FluidStack.create(fluid, amount);
|
||||
|
||||
if (tag.contains("tag", NbtType.COMPOUND)) {
|
||||
stack.setTag(tag.getCompound("tag"));
|
||||
}
|
||||
return stack;
|
||||
}
|
||||
|
||||
public static CompoundTag write(FluidStack stack, CompoundTag tag) {
|
||||
tag.putString("id", Registry.FLUID.getKey(stack.getFluid()).toString());
|
||||
tag.putLong("amount", stack.getAmount());
|
||||
if (stack.hasTag()) {
|
||||
tag.put("tag", stack.getTag());
|
||||
}
|
||||
return tag;
|
||||
}
|
||||
|
||||
public static long bucketAmount() {
|
||||
return 81000;
|
||||
}
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
@Nullable
|
||||
public static TextureAtlasSprite getStillTexture(@Nullable BlockAndTintGetter level, @Nullable BlockPos pos, @NotNull FluidState state) {
|
||||
if (state.getType() == Fluids.EMPTY) return null;
|
||||
var sprites = FluidRenderHandlerRegistry.INSTANCE.get(state.getType()).getFluidSprites(level, pos, state);
|
||||
if (sprites == null) return null;
|
||||
return sprites[0];
|
||||
}
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
@Nullable
|
||||
public static TextureAtlasSprite getStillTexture(@NotNull FluidStack stack) {
|
||||
if (stack.getFluid() == Fluids.EMPTY) return null;
|
||||
var sprites = FluidRenderHandlerRegistry.INSTANCE.get(stack.getFluid()).getFluidSprites(null, null, stack.getFluid().defaultFluidState());
|
||||
if (sprites == null) return null;
|
||||
return sprites[0];
|
||||
}
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
@Nullable
|
||||
public static TextureAtlasSprite getStillTexture(@NotNull Fluid fluid) {
|
||||
if (fluid == Fluids.EMPTY) return null;
|
||||
var sprites = FluidRenderHandlerRegistry.INSTANCE.get(fluid).getFluidSprites(null, null, fluid.defaultFluidState());
|
||||
if (sprites == null) return null;
|
||||
return sprites[0];
|
||||
}
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
@Nullable
|
||||
public static TextureAtlasSprite getFlowingTexture(@Nullable BlockAndTintGetter level, @Nullable BlockPos pos, @NotNull 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(@NotNull FluidStack stack) {
|
||||
if (stack.getFluid() == Fluids.EMPTY) return null;
|
||||
var handler = FluidRenderHandlerRegistry.INSTANCE.get(stack.getFluid());
|
||||
if (handler == null) return null;
|
||||
var sprites = handler.getFluidSprites(null, null, stack.getFluid().defaultFluidState());
|
||||
if (sprites == null) return null;
|
||||
return sprites[1];
|
||||
}
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
@Nullable
|
||||
public static TextureAtlasSprite getFlowingTexture(@NotNull Fluid fluid) {
|
||||
if (fluid == Fluids.EMPTY) return null;
|
||||
var sprites = FluidRenderHandlerRegistry.INSTANCE.get(fluid).getFluidSprites(null, null, fluid.defaultFluidState());
|
||||
if (sprites == null) return null;
|
||||
return sprites[1];
|
||||
}
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public static int getColor(@Nullable BlockAndTintGetter level, @Nullable BlockPos pos, @NotNull 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(@NotNull FluidStack stack) {
|
||||
if (stack.getFluid() == Fluids.EMPTY) return -1;
|
||||
var handler = FluidRenderHandlerRegistry.INSTANCE.get(stack.getFluid());
|
||||
if (handler == null) return -1;
|
||||
return handler.getFluidColor(null, null, stack.getFluid().defaultFluidState());
|
||||
}
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public static int getColor(@NotNull 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());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 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.level.entity.fabric;
|
||||
|
||||
import dev.architectury.event.events.common.EntityEvent;
|
||||
import net.minecraft.core.SectionPos;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.level.entity.EntityInLevelCallback;
|
||||
import net.minecraft.world.phys.shapes.CollisionContext;
|
||||
import net.minecraft.world.phys.shapes.EntityCollisionContext;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class EntityHooksImpl {
|
||||
public static String getEncodeId(Entity entity) {
|
||||
return entity.getEncodeId();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static Entity fromCollision(CollisionContext ctx) {
|
||||
return ctx instanceof EntityCollisionContext ? ((EntityCollisionContext) ctx).getEntity().orElse(null) : null;
|
||||
}
|
||||
|
||||
public static EntityInLevelCallback wrapEntityInLevelCallback(Entity entity, EntityInLevelCallback callback) {
|
||||
if (callback == EntityInLevelCallback.NULL) return callback;
|
||||
if (callback == null) return callback;
|
||||
return new EntityInLevelCallback() {
|
||||
private long lastSectionKey = SectionPos.asLong(entity.blockPosition());
|
||||
|
||||
@Override
|
||||
public void onMove() {
|
||||
callback.onMove();
|
||||
var currentSectionKey = SectionPos.asLong(entity.blockPosition());
|
||||
if (currentSectionKey != lastSectionKey) {
|
||||
EntityEvent.ENTER_SECTION.invoker().enterSection(entity, SectionPos.x(lastSectionKey), SectionPos.y(lastSectionKey),
|
||||
SectionPos.z(lastSectionKey), SectionPos.x(currentSectionKey), SectionPos.y(currentSectionKey),
|
||||
SectionPos.z(currentSectionKey));
|
||||
lastSectionKey = currentSectionKey;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRemove(Entity.RemovalReason removalReason) {
|
||||
callback.onRemove(removalReason);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 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.level.entity.fabric;
|
||||
|
||||
import dev.architectury.utils.value.IntValue;
|
||||
import net.minecraft.world.entity.item.ItemEntity;
|
||||
|
||||
public class ItemEntityHooksImpl {
|
||||
public static IntValue lifespan(ItemEntity entity) {
|
||||
return new IntValue() {
|
||||
@Override
|
||||
public void accept(int value) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAsInt() {
|
||||
return 6000;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 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.level.entity.fabric;
|
||||
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
|
||||
public class PlayerHooksImpl {
|
||||
public static boolean isFake(Player player) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void closeContainer(Player player) {
|
||||
player.closeContainer();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 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.level.fabric;
|
||||
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.level.Explosion;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
public class ExplosionHooksImpl {
|
||||
public static Vec3 getPosition(Explosion explosion) {
|
||||
return ((ExplosionExtensions) explosion).architectury_getPosition();
|
||||
}
|
||||
|
||||
public static Entity getSource(Explosion explosion) {
|
||||
return ((ExplosionExtensions) explosion).architectury_getSource();
|
||||
}
|
||||
|
||||
public static float getRadius(Explosion explosion) {
|
||||
return ((ExplosionExtensions) explosion).architectury_getRadius();
|
||||
}
|
||||
|
||||
public static void setRadius(Explosion explosion, float radius) {
|
||||
((ExplosionExtensions) explosion).architectury_setRadius(radius);
|
||||
}
|
||||
|
||||
public interface ExplosionExtensions {
|
||||
Vec3 architectury_getPosition();
|
||||
|
||||
Entity architectury_getSource();
|
||||
|
||||
float architectury_getRadius();
|
||||
|
||||
void architectury_setRadius(float v);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 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.tags.fabric;
|
||||
|
||||
import net.fabricmc.fabric.api.tag.TagRegistry;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.tags.Tag;
|
||||
import net.minecraft.tags.TagCollection;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class TagHooksImpl {
|
||||
public static <T> Tag.Named<T> optional(ResourceLocation id, Supplier<TagCollection<T>> collection) {
|
||||
return TagRegistry.create(id, collection);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 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.impl.fabric;
|
||||
|
||||
import dev.architectury.event.events.common.ChatEvent;
|
||||
import net.minecraft.network.chat.Component;
|
||||
|
||||
public class ChatComponentImpl implements ChatEvent.ChatComponent {
|
||||
private Component raw;
|
||||
private Component filtered;
|
||||
|
||||
public ChatComponentImpl(Component raw, Component filtered) {
|
||||
this.raw = raw;
|
||||
this.filtered = filtered;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getRaw() {
|
||||
return raw;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getFiltered() {
|
||||
return filtered;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRaw(Component raw) {
|
||||
this.raw = raw;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFiltered(Component filtered) {
|
||||
this.filtered = filtered;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 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.impl.fabric;
|
||||
|
||||
import dev.architectury.event.events.client.ClientScreenInputEvent;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.screens.Screen;
|
||||
import net.minecraft.network.chat.TextComponent;
|
||||
|
||||
public interface ScreenInputDelegate {
|
||||
Screen architectury_delegateInputs();
|
||||
|
||||
class DelegateScreen extends Screen {
|
||||
private Screen parent;
|
||||
|
||||
public DelegateScreen(Screen parent) {
|
||||
super(TextComponent.EMPTY);
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseDragged(double d, double e, int i, double f, double g) {
|
||||
if (ClientScreenInputEvent.MOUSE_DRAGGED_PRE.invoker().mouseDragged(Minecraft.getInstance(), parent, d, e, i, f, g).isPresent())
|
||||
return true;
|
||||
if (parent.mouseDragged(d, e, i, f, g))
|
||||
return true;
|
||||
return ClientScreenInputEvent.MOUSE_DRAGGED_PRE.invoker().mouseDragged(Minecraft.getInstance(), parent, d, e, i, f, g).isPresent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean charTyped(char c, int i) {
|
||||
if (ClientScreenInputEvent.CHAR_TYPED_PRE.invoker().charTyped(Minecraft.getInstance(), parent, c, i).isPresent())
|
||||
return true;
|
||||
if (parent.charTyped(c, i))
|
||||
return true;
|
||||
return ClientScreenInputEvent.CHAR_TYPED_POST.invoker().charTyped(Minecraft.getInstance(), parent, c, i).isPresent();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 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.init.fabric;
|
||||
|
||||
import dev.architectury.event.events.client.ClientLifecycleEvent;
|
||||
import dev.architectury.networking.fabric.SpawnEntityPacket;
|
||||
import net.minecraft.client.Minecraft;
|
||||
|
||||
public class ArchitecturyClient {
|
||||
public static void init() {
|
||||
ClientLifecycleEvent.CLIENT_SETUP.invoker().stateChanged(Minecraft.getInstance());
|
||||
|
||||
SpawnEntityPacket.register();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 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.mixin.fabric;
|
||||
|
||||
import dev.architectury.event.events.common.ExplosionEvent;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.damagesource.DamageSource;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.level.Explosion;
|
||||
import net.minecraft.world.level.ExplosionDamageCalculator;
|
||||
import net.minecraft.world.level.Level;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
|
||||
|
||||
@Mixin(value = {Level.class, ServerLevel.class})
|
||||
public class ExplosionPreInvoker {
|
||||
@Inject(method = "explode(Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/damagesource/DamageSource;Lnet/minecraft/world/level/ExplosionDamageCalculator;DDDFZLnet/minecraft/world/level/Explosion$BlockInteraction;)Lnet/minecraft/world/level/Explosion;",
|
||||
at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Explosion;explode()V"), cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD)
|
||||
private void explodePre(Entity entity, DamageSource damageSource, ExplosionDamageCalculator explosionDamageCalculator, double d, double e, double f, float g, boolean bl, Explosion.BlockInteraction blockInteraction, CallbackInfoReturnable<Explosion> cir, Explosion explosion) {
|
||||
if (ExplosionEvent.PRE.invoker().explode((Level) (Object) this, explosion).isFalse()) {
|
||||
cir.setReturnValue(explosion);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 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.mixin.fabric;
|
||||
|
||||
import dev.architectury.event.events.common.EntityEvent;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.damagesource.DamageSource;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(value = {LivingEntity.class, Player.class, ServerPlayer.class})
|
||||
public class LivingDeathInvoker {
|
||||
@Inject(method = "die", at = @At("HEAD"), cancellable = true)
|
||||
private void die(DamageSource source, CallbackInfo ci) {
|
||||
if (EntityEvent.LIVING_DEATH.invoker().die((LivingEntity) (Object) this, source).isFalse()) {
|
||||
ci.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 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.mixin.fabric;
|
||||
|
||||
import dev.architectury.event.events.common.EntityEvent;
|
||||
import net.minecraft.world.entity.Mob;
|
||||
import net.minecraft.world.entity.MobSpawnType;
|
||||
import net.minecraft.world.level.BaseSpawner;
|
||||
import net.minecraft.world.level.LevelAccessor;
|
||||
import net.minecraft.world.level.LevelReader;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
|
||||
@Mixin(BaseSpawner.class)
|
||||
public abstract class MixinBaseSpawner {
|
||||
@Redirect(
|
||||
method = "serverTick",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "Lnet/minecraft/world/entity/Mob;checkSpawnRules(Lnet/minecraft/world/level/LevelAccessor;Lnet/minecraft/world/entity/MobSpawnType;)Z",
|
||||
ordinal = 0
|
||||
)
|
||||
)
|
||||
private boolean checkSpawnerSpawn(Mob mob, LevelAccessor level, MobSpawnType type) {
|
||||
var result = EntityEvent.LIVING_CHECK_SPAWN.invoker()
|
||||
.canSpawn(mob, level, mob.getX(), mob.getY(), mob.getZ(), type, (BaseSpawner) (Object) this);
|
||||
if (result.value() != null) {
|
||||
return result.value();
|
||||
}
|
||||
return mob.checkSpawnRules(level, type) && mob.checkSpawnObstruction(level);
|
||||
}
|
||||
|
||||
@Redirect(
|
||||
method = "serverTick",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "Lnet/minecraft/world/entity/Mob;checkSpawnObstruction(Lnet/minecraft/world/level/LevelReader;)Z",
|
||||
ordinal = 0
|
||||
)
|
||||
)
|
||||
private boolean skipDoubleObstruction(Mob mob, LevelReader levelReader) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 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.mixin.fabric;
|
||||
|
||||
import dev.architectury.extensions.BlockEntityExtension;
|
||||
import net.fabricmc.fabric.api.block.entity.BlockEntityClientSerializable;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
|
||||
@Mixin(BlockEntityExtension.class)
|
||||
public interface MixinBlockEntityExtension extends BlockEntityClientSerializable {
|
||||
@Override
|
||||
default void fromClientTag(CompoundTag tag) {
|
||||
var entity = (BlockEntity) this;
|
||||
if (entity.hasLevel()) {
|
||||
((BlockEntityExtension) this).loadClientData(entity.getBlockState(), tag);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
default CompoundTag toClientTag(CompoundTag tag) {
|
||||
return ((BlockEntityExtension) this).saveClientData(tag);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 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.mixin.fabric;
|
||||
|
||||
import dev.architectury.event.events.common.BlockEvent;
|
||||
import net.minecraft.world.InteractionResult;
|
||||
import net.minecraft.world.item.BlockItem;
|
||||
import net.minecraft.world.item.context.BlockPlaceContext;
|
||||
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;
|
||||
|
||||
@Mixin(BlockItem.class)
|
||||
public abstract class MixinBlockItem {
|
||||
@Inject(method = "place",
|
||||
at = @At(value = "INVOKE",
|
||||
target = "Lnet/minecraft/world/item/context/BlockPlaceContext;getClickedPos()Lnet/minecraft/core/BlockPos;"),
|
||||
cancellable = true)
|
||||
private void place(BlockPlaceContext context, CallbackInfoReturnable<InteractionResult> cir) {
|
||||
var result = BlockEvent.PLACE.invoker().placeBlock(context.getLevel(), context.getClickedPos(), context.getLevel().getBlockState(context.getClickedPos()), context.getPlayer());
|
||||
if (result.isPresent()) {
|
||||
cir.setReturnValue(result.isTrue() ? InteractionResult.SUCCESS : InteractionResult.FAIL);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 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.mixin.fabric;
|
||||
|
||||
import dev.architectury.event.events.common.PlayerEvent;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.InteractionResultHolder;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.BucketItem;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
|
||||
|
||||
@Mixin(BucketItem.class)
|
||||
public class MixinBucketItem {
|
||||
|
||||
@Inject(
|
||||
method = "use",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "Lnet/minecraft/world/phys/BlockHitResult;getType()Lnet/minecraft/world/phys/HitResult$Type;",
|
||||
ordinal = 0
|
||||
),
|
||||
locals = LocalCapture.CAPTURE_FAILHARD,
|
||||
cancellable = true
|
||||
)
|
||||
public void fillBucket(Level level, Player player, InteractionHand hand, CallbackInfoReturnable<InteractionResultHolder<ItemStack>> cir, ItemStack stack, BlockHitResult target) {
|
||||
var result = PlayerEvent.FILL_BUCKET.invoker().fill(player, level, stack, target);
|
||||
if (result.interruptsFurtherEvaluation() && result.value() != null) {
|
||||
cir.setReturnValue(result.asMinecraft());
|
||||
cir.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 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.mixin.fabric;
|
||||
|
||||
import dev.architectury.event.events.common.EntityEvent;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.entity.MobSpawnType;
|
||||
import net.minecraft.world.entity.animal.Cat;
|
||||
import net.minecraft.world.entity.npc.CatSpawner;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
|
||||
|
||||
@Mixin(CatSpawner.class)
|
||||
public abstract class MixinCatSpawner {
|
||||
@Inject(
|
||||
method = "spawnCat",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "Lnet/minecraft/world/entity/animal/Cat;finalizeSpawn(Lnet/minecraft/world/level/ServerLevelAccessor;Lnet/minecraft/world/DifficultyInstance;Lnet/minecraft/world/entity/MobSpawnType;Lnet/minecraft/world/entity/SpawnGroupData;Lnet/minecraft/nbt/CompoundTag;)Lnet/minecraft/world/entity/SpawnGroupData;",
|
||||
ordinal = 0
|
||||
),
|
||||
cancellable = true,
|
||||
locals = LocalCapture.CAPTURE_FAILHARD
|
||||
)
|
||||
private void checkCatSpawn(BlockPos pos, ServerLevel level, CallbackInfoReturnable<Integer> cir, Cat entity) {
|
||||
if (EntityEvent.LIVING_CHECK_SPAWN.invoker().canSpawn(entity, level, pos.getX(), pos.getY(), pos.getZ(), MobSpawnType.NATURAL, null).value() == Boolean.FALSE) {
|
||||
cir.setReturnValue(0);
|
||||
cir.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 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.mixin.fabric;
|
||||
|
||||
import dev.architectury.event.events.common.ChunkEvent;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.server.level.ChunkMap;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.level.ChunkPos;
|
||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||
import net.minecraft.world.level.chunk.ChunkStatus;
|
||||
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.CallbackInfoReturnable;
|
||||
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
|
||||
|
||||
@Mixin(ChunkMap.class)
|
||||
public class MixinChunkMap {
|
||||
@Shadow
|
||||
@Final
|
||||
ServerLevel level;
|
||||
|
||||
@Inject(
|
||||
method = "save",
|
||||
at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ChunkMap;write(Lnet/minecraft/world/level/ChunkPos;Lnet/minecraft/nbt/CompoundTag;)V", ordinal = 0),
|
||||
locals = LocalCapture.CAPTURE_FAILHARD
|
||||
)
|
||||
private void save(ChunkAccess chunkAccess, CallbackInfoReturnable<Boolean> cir, ChunkPos pos, ChunkStatus chunkStatus, CompoundTag nbt) {
|
||||
ChunkEvent.SAVE_DATA.invoker().save(chunkAccess, this.level, nbt);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 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.mixin.fabric;
|
||||
|
||||
import dev.architectury.event.events.common.ChunkEvent;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.ListTag;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.entity.ai.village.poi.PoiManager;
|
||||
import net.minecraft.world.level.ChunkPos;
|
||||
import net.minecraft.world.level.biome.BiomeSource;
|
||||
import net.minecraft.world.level.chunk.*;
|
||||
import net.minecraft.world.level.chunk.storage.ChunkSerializer;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureManager;
|
||||
import net.minecraft.world.level.lighting.LevelLightEngine;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
|
||||
|
||||
@Mixin(ChunkSerializer.class)
|
||||
public class MixinChunkSerializer {
|
||||
@Inject(method = "read", at = @At("RETURN"), locals = LocalCapture.CAPTURE_FAILHARD)
|
||||
private static void load(ServerLevel serverLevel, StructureManager structureManager, PoiManager poiManager, ChunkPos chunkPos, CompoundTag compoundTag,
|
||||
CallbackInfoReturnable<ProtoChunk> cir, ChunkGenerator chunkGenerator, BiomeSource biomeSource, CompoundTag compoundTagLevelData,
|
||||
ChunkBiomeContainer chunkBiomeContainer, UpgradeData upgradeData, ProtoTickList<?> protoTickList, ProtoTickList<?> protoTickList2,
|
||||
boolean bl, ListTag listTag, int i, LevelChunkSection[] levelChunkSections, boolean bl2, ChunkSource chunkSource,
|
||||
LevelLightEngine levelLightEngine, long l, ChunkStatus.ChunkType chunkType, ChunkAccess chunk) {
|
||||
ChunkEvent.LOAD_DATA.invoker().load(chunk, serverLevel, compoundTag);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 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.mixin.fabric;
|
||||
|
||||
import com.google.common.base.Throwables;
|
||||
import com.mojang.brigadier.CommandDispatcher;
|
||||
import com.mojang.brigadier.StringReader;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import dev.architectury.event.events.common.CommandPerformEvent;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.commands.Commands;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
|
||||
@Mixin(Commands.class)
|
||||
public class MixinCommands {
|
||||
@Redirect(method = "performCommand",
|
||||
at = @At(value = "INVOKE", target = "Lcom/mojang/brigadier/CommandDispatcher;execute(Lcom/mojang/brigadier/StringReader;Ljava/lang/Object;)I", remap = false))
|
||||
private int performCommand(CommandDispatcher<CommandSourceStack> dispatcher, StringReader input, Object source) throws CommandSyntaxException {
|
||||
var stack = (CommandSourceStack) source;
|
||||
var parse = dispatcher.parse(input, stack);
|
||||
var event = new CommandPerformEvent(parse, null);
|
||||
if (CommandPerformEvent.EVENT.invoker().act(event).isPresent()) {
|
||||
if (event.getThrowable() != null) {
|
||||
Throwables.throwIfUnchecked(event.getThrowable());
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return dispatcher.execute(event.getResults());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 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.mixin.fabric;
|
||||
|
||||
import dev.architectury.event.events.common.LifecycleEvent;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.dedicated.DedicatedServer;
|
||||
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;
|
||||
|
||||
@Mixin(DedicatedServer.class)
|
||||
public class MixinDedicatedServer {
|
||||
@Inject(method = "initServer", at = @At("RETURN"), cancellable = true)
|
||||
private void initServer(CallbackInfoReturnable<Boolean> cir) {
|
||||
if (cir.getReturnValueZ()) {
|
||||
LifecycleEvent.SERVER_STARTING.invoker().stateChanged((MinecraftServer) (Object) this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 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.mixin.fabric;
|
||||
|
||||
import dev.architectury.hooks.level.entity.fabric.EntityHooksImpl;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.level.entity.EntityInLevelCallback;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.ModifyVariable;
|
||||
|
||||
@Mixin(Entity.class)
|
||||
public class MixinEntity {
|
||||
@ModifyVariable(method = "setLevelCallback", argsOnly = true, ordinal = 0, at = @At("HEAD"))
|
||||
public EntityInLevelCallback modifyLevelCallback_setLevelCallback(EntityInLevelCallback callback) {
|
||||
return EntityHooksImpl.wrapEntityInLevelCallback((Entity) (Object) this, callback);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 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.mixin.fabric;
|
||||
|
||||
import dev.architectury.event.events.common.ExplosionEvent;
|
||||
import dev.architectury.hooks.level.fabric.ExplosionHooksImpl;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.level.Explosion;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.spongepowered.asm.mixin.*;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
@Mixin(Explosion.class)
|
||||
public class MixinExplosion implements ExplosionHooksImpl.ExplosionExtensions {
|
||||
@Shadow
|
||||
@Final
|
||||
private Level level;
|
||||
@Shadow
|
||||
@Final
|
||||
private double x;
|
||||
@Shadow
|
||||
@Final
|
||||
private double y;
|
||||
@Shadow
|
||||
@Final
|
||||
private double z;
|
||||
@Shadow
|
||||
@Final
|
||||
@Nullable
|
||||
private Entity source;
|
||||
@Shadow
|
||||
@Final
|
||||
@Mutable
|
||||
private float radius;
|
||||
@Unique
|
||||
Vec3 position;
|
||||
|
||||
@Inject(method = "explode", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/phys/Vec3;<init>(DDD)V", ordinal = 0),
|
||||
locals = LocalCapture.CAPTURE_FAILHARD)
|
||||
private void explodePost(CallbackInfo ci, Set<BlockPos> set, int i, float q, int r, int s, int t, int u, int v, int w, List<Entity> list) {
|
||||
ExplosionEvent.DETONATE.invoker().explode(level, (Explosion) (Object) this, list);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vec3 architectury_getPosition() {
|
||||
if (position == null) {
|
||||
return position = new Vec3(x, y, z);
|
||||
}
|
||||
return position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Entity architectury_getSource() {
|
||||
return source;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float architectury_getRadius() {
|
||||
return radius;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void architectury_setRadius(float v) {
|
||||
radius = v;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 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.mixin.fabric;
|
||||
|
||||
import dev.architectury.event.events.common.InteractionEvent;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.FarmBlock;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import org.apache.commons.lang3.tuple.Triple;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(FarmBlock.class)
|
||||
public abstract class MixinFarmBlock {
|
||||
@Unique
|
||||
private static ThreadLocal<Triple<Long, Float, Entity>> turnToDirtLocal = new ThreadLocal<>();
|
||||
|
||||
@Inject(
|
||||
method = "fallOn",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "Lnet/minecraft/world/level/block/FarmBlock;turnToDirt(Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;)V"
|
||||
)
|
||||
)
|
||||
private void fallOn(Level level, BlockState blockState, BlockPos blockPos, Entity entity, float f, CallbackInfo ci) {
|
||||
turnToDirtLocal.set(Triple.of(blockPos.asLong(), f, entity));
|
||||
}
|
||||
|
||||
@Inject(method = "turnToDirt", at = @At("HEAD"), cancellable = true)
|
||||
private static void turnToDirt(BlockState state, Level level, BlockPos pos, CallbackInfo ci) {
|
||||
var triple = turnToDirtLocal.get();
|
||||
turnToDirtLocal.remove();
|
||||
if (triple != null && triple.getLeft() == pos.asLong()) {
|
||||
if (InteractionEvent.FARMLAND_TRAMPLE.invoker().trample(level, pos, state, triple.getMiddle(), triple.getRight()).value() != null) {
|
||||
ci.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 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.mixin.fabric;
|
||||
|
||||
import dev.architectury.event.events.common.PlayerEvent;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.inventory.FurnaceResultSlot;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
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(FurnaceResultSlot.class)
|
||||
public class MixinFurnaceResultSlot {
|
||||
@Shadow
|
||||
@Final
|
||||
private Player player;
|
||||
|
||||
@Inject(method = "checkTakeAchievements", at = @At("RETURN"))
|
||||
private void checkTakeAchievements(ItemStack itemStack, CallbackInfo ci) {
|
||||
PlayerEvent.SMELT_ITEM.invoker().smelt(player, itemStack);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 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.mixin.fabric;
|
||||
|
||||
import dev.architectury.extensions.ItemExtension;
|
||||
import net.minecraft.core.NonNullList;
|
||||
import net.minecraft.world.entity.player.Inventory;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
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(Inventory.class)
|
||||
public class MixinInventory {
|
||||
@Shadow
|
||||
@Final
|
||||
public NonNullList<ItemStack> armor;
|
||||
|
||||
@Shadow
|
||||
@Final
|
||||
public Player player;
|
||||
|
||||
@Inject(method = "tick", at = @At("RETURN"))
|
||||
private void updateItems(CallbackInfo ci) {
|
||||
for (var stack : armor) {
|
||||
Item item = stack.getItem();
|
||||
if (item instanceof ItemExtension extension) {
|
||||
extension.tickArmor(stack, player);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 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.mixin.fabric;
|
||||
|
||||
import dev.architectury.event.events.common.PlayerEvent;
|
||||
import net.minecraft.world.entity.item.ItemEntity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(ItemEntity.class)
|
||||
public abstract class MixinItemEntity {
|
||||
@Shadow
|
||||
public abstract ItemStack getItem();
|
||||
|
||||
@Unique
|
||||
private ItemStack cache;
|
||||
|
||||
@Inject(method = "playerTouch",
|
||||
at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/ItemStack;getCount()I"), cancellable = true)
|
||||
private void prePickup(Player player, CallbackInfo ci) {
|
||||
cache = getItem().copy();
|
||||
var canPickUp = PlayerEvent.PICKUP_ITEM_PRE.invoker().canPickup(player, (ItemEntity) (Object) this, getItem());
|
||||
if (canPickUp.isFalse()) {
|
||||
ci.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "playerTouch",
|
||||
at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;take(Lnet/minecraft/world/entity/Entity;I)V"))
|
||||
private void pickup(Player player, CallbackInfo ci) {
|
||||
if (cache != null) {
|
||||
PlayerEvent.PICKUP_ITEM_POST.invoker().pickup(player, (ItemEntity) (Object) this, cache);
|
||||
}
|
||||
|
||||
this.cache = null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 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.mixin.fabric;
|
||||
|
||||
import dev.architectury.event.events.common.EntityEvent;
|
||||
import dev.architectury.extensions.ItemExtension;
|
||||
import net.minecraft.world.damagesource.DamageSource;
|
||||
import net.minecraft.world.entity.EquipmentSlot;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
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;
|
||||
|
||||
@Mixin(LivingEntity.class)
|
||||
public class MixinLivingEntity {
|
||||
@Inject(method = "hurt", at = @At("HEAD"), cancellable = true)
|
||||
private void hurt(DamageSource damageSource, float f, CallbackInfoReturnable<Boolean> cir) {
|
||||
if ((Object) this instanceof Player) return;
|
||||
if (EntityEvent.LIVING_HURT.invoker().hurt((LivingEntity) (Object) this, damageSource, f).isFalse()) {
|
||||
cir.setReturnValue(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "getEquipmentSlotForItem", at = @At("HEAD"), cancellable = true)
|
||||
private static void getEquipmentSlotForItem(ItemStack stack, CallbackInfoReturnable<EquipmentSlot> cir) {
|
||||
var item = stack.getItem();
|
||||
if (item instanceof ItemExtension extension) {
|
||||
var slot = extension.getCustomEquipmentSlot(stack);
|
||||
if (slot != null) {
|
||||
cir.setReturnValue(slot);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 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.mixin.fabric;
|
||||
|
||||
import dev.architectury.event.events.common.EntityEvent;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.entity.Mob;
|
||||
import net.minecraft.world.entity.MobSpawnType;
|
||||
import net.minecraft.world.level.LevelAccessor;
|
||||
import net.minecraft.world.level.NaturalSpawner;
|
||||
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.Redirect;
|
||||
|
||||
@Mixin(NaturalSpawner.class)
|
||||
public abstract class MixinNaturalSpawner {
|
||||
@Shadow
|
||||
private static boolean isValidPositionForMob(ServerLevel serverLevel, Mob mob, double d) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Redirect(
|
||||
method = "spawnCategoryForPosition(Lnet/minecraft/world/entity/MobCategory;Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/level/chunk/ChunkAccess;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/NaturalSpawner$SpawnPredicate;Lnet/minecraft/world/level/NaturalSpawner$AfterSpawnCallback;)V",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "Lnet/minecraft/world/level/NaturalSpawner;isValidPositionForMob(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/entity/Mob;D)Z",
|
||||
ordinal = 0
|
||||
)
|
||||
)
|
||||
private static boolean overrideNaturalSpawnCondition(ServerLevel level, Mob entity, double f) {
|
||||
var result = EntityEvent.LIVING_CHECK_SPAWN.invoker().canSpawn(entity, level, entity.xOld, entity.yOld, entity.zOld, MobSpawnType.NATURAL, null);
|
||||
if (result.value() != null) {
|
||||
return result.value();
|
||||
} else {
|
||||
return isValidPositionForMob(level, entity, f);
|
||||
}
|
||||
}
|
||||
|
||||
@Redirect(
|
||||
method = "spawnMobsForChunkGeneration",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "Lnet/minecraft/world/entity/Mob;checkSpawnRules(Lnet/minecraft/world/level/LevelAccessor;Lnet/minecraft/world/entity/MobSpawnType;)Z",
|
||||
ordinal = 0
|
||||
)
|
||||
)
|
||||
private static boolean overrideChunkGenSpawnCondition(Mob mob, LevelAccessor level, MobSpawnType type) {
|
||||
var result = EntityEvent.LIVING_CHECK_SPAWN.invoker().canSpawn(mob, level, mob.xOld, mob.yOld, mob.zOld, MobSpawnType.CHUNK_GENERATION, null);
|
||||
if (result.value() != null) {
|
||||
return result.value();
|
||||
} else {
|
||||
return mob.checkSpawnRules(level, type);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 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.mixin.fabric;
|
||||
|
||||
import dev.architectury.event.events.common.EntityEvent;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.entity.MobSpawnType;
|
||||
import net.minecraft.world.entity.monster.PatrollingMonster;
|
||||
import net.minecraft.world.level.levelgen.PatrolSpawner;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
@Mixin(PatrolSpawner.class)
|
||||
public abstract class MixinPatrolSpawner {
|
||||
|
||||
@Inject(
|
||||
method = "spawnPatrolMember",
|
||||
at = @At(
|
||||
value = "INVOKE_ASSIGN",
|
||||
target = "Lnet/minecraft/world/entity/EntityType;create(Lnet/minecraft/world/level/Level;)Lnet/minecraft/world/entity/Entity;",
|
||||
ordinal = 0,
|
||||
shift = At.Shift.BY,
|
||||
by = 2
|
||||
),
|
||||
cancellable = true,
|
||||
locals = LocalCapture.CAPTURE_FAILHARD
|
||||
)
|
||||
private void checkPatrolSpawn(ServerLevel level, BlockPos pos, Random r, boolean b, CallbackInfoReturnable<Boolean> cir, PatrollingMonster entity) {
|
||||
var result = EntityEvent.LIVING_CHECK_SPAWN.invoker().canSpawn(entity, level, pos.getX(), pos.getY(), pos.getZ(), MobSpawnType.PATROL, null);
|
||||
if (result.value() != null) {
|
||||
cir.setReturnValue(result.value());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 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.mixin.fabric;
|
||||
|
||||
import dev.architectury.event.events.common.EntityEvent;
|
||||
import dev.architectury.hooks.fabric.PersistentEntitySectionManagerHooks;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.level.entity.EntityAccess;
|
||||
import net.minecraft.world.level.entity.PersistentEntitySectionManager;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
@Mixin(PersistentEntitySectionManager.class)
|
||||
public class MixinPersistentEntitySectionManager<T extends EntityAccess> implements PersistentEntitySectionManagerHooks {
|
||||
@Unique
|
||||
private WeakReference<ServerLevel> levelRef;
|
||||
|
||||
@Override
|
||||
public void architectury_attachLevel(ServerLevel level) {
|
||||
levelRef = new WeakReference<>(level);
|
||||
}
|
||||
|
||||
@Inject(method = "addEntity", at = @At(value = "INVOKE",
|
||||
target = "Lnet/minecraft/core/SectionPos;asLong(Lnet/minecraft/core/BlockPos;)J"),
|
||||
cancellable = true)
|
||||
private void addEntity(T entityAccess, boolean bl, CallbackInfoReturnable<Boolean> cir) {
|
||||
// TODO: Check if other classes implements EntityAccess as well
|
||||
if (entityAccess instanceof Entity entity && levelRef != null) {
|
||||
var level = levelRef.get();
|
||||
levelRef = null;
|
||||
|
||||
if (level != null) {
|
||||
if (EntityEvent.ADD.invoker().add(entity, level).isFalse()) {
|
||||
cir.setReturnValue(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 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.mixin.fabric;
|
||||
|
||||
import dev.architectury.event.events.common.EntityEvent;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.DifficultyInstance;
|
||||
import net.minecraft.world.entity.MobSpawnType;
|
||||
import net.minecraft.world.entity.SpawnGroupData;
|
||||
import net.minecraft.world.entity.monster.Phantom;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.level.levelgen.PhantomSpawner;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Random;
|
||||
|
||||
@Mixin(PhantomSpawner.class)
|
||||
public abstract class MixinPhantomSpawner {
|
||||
|
||||
@Inject(
|
||||
method = "tick",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "Lnet/minecraft/world/entity/monster/Phantom;finalizeSpawn(Lnet/minecraft/world/level/ServerLevelAccessor;Lnet/minecraft/world/DifficultyInstance;Lnet/minecraft/world/entity/MobSpawnType;Lnet/minecraft/world/entity/SpawnGroupData;Lnet/minecraft/nbt/CompoundTag;)Lnet/minecraft/world/entity/SpawnGroupData;",
|
||||
ordinal = 0,
|
||||
shift = At.Shift.BEFORE
|
||||
),
|
||||
cancellable = true,
|
||||
locals = LocalCapture.CAPTURE_FAILSOFT // SOFT, because this will break in 2 seconds
|
||||
)
|
||||
private void checkPhantomSpawn(ServerLevel level, boolean bl, boolean bl2, CallbackInfoReturnable<Integer> cir,
|
||||
Random random, int i, Iterator<ServerPlayer> it, Player player, BlockPos pos, DifficultyInstance diff, BlockPos pos2,
|
||||
SpawnGroupData sgd, int l, int m, Phantom entity) {
|
||||
if (EntityEvent.LIVING_CHECK_SPAWN.invoker().canSpawn(entity, level, pos.getX(), pos.getY(), pos.getZ(), MobSpawnType.NATURAL, null).value() == Boolean.FALSE) {
|
||||
cir.setReturnValue(0);
|
||||
cir.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 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.mixin.fabric;
|
||||
|
||||
import dev.architectury.event.events.common.InteractionEvent;
|
||||
import dev.architectury.event.events.common.PlayerEvent;
|
||||
import dev.architectury.event.events.common.TickEvent;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.InteractionResult;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.item.ItemEntity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
@Mixin(Player.class)
|
||||
public class MixinPlayer {
|
||||
@Inject(method = "tick", at = @At("HEAD"))
|
||||
private void preTick(CallbackInfo ci) {
|
||||
TickEvent.PLAYER_PRE.invoker().tick((Player) (Object) this);
|
||||
}
|
||||
|
||||
@Inject(method = "tick", at = @At("RETURN"))
|
||||
private void postTick(CallbackInfo ci) {
|
||||
TickEvent.PLAYER_POST.invoker().tick((Player) (Object) this);
|
||||
}
|
||||
|
||||
@Inject(method = "drop(Lnet/minecraft/world/item/ItemStack;ZZ)Lnet/minecraft/world/entity/item/ItemEntity;", at = @At("RETURN"), cancellable = true)
|
||||
private void drop(ItemStack itemStack, boolean bl, boolean bl2, CallbackInfoReturnable<ItemEntity> cir) {
|
||||
if (cir.getReturnValue() != null && PlayerEvent.DROP_ITEM.invoker().drop((Player) (Object) this, cir.getReturnValue()).isFalse()) {
|
||||
cir.setReturnValue(null);
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "interactOn", at = @At(value = "INVOKE",
|
||||
target = "Lnet/minecraft/world/entity/player/Player;getItemInHand(Lnet/minecraft/world/InteractionHand;)Lnet/minecraft/world/item/ItemStack;",
|
||||
ordinal = 0),
|
||||
cancellable = true)
|
||||
private void entityInteract(Entity entity, InteractionHand interactionHand, CallbackInfoReturnable<InteractionResult> cir) {
|
||||
var result = InteractionEvent.INTERACT_ENTITY.invoker().interact((Player) (Object) this, entity, interactionHand);
|
||||
if (result.isPresent()) {
|
||||
cir.setReturnValue(result.asMinecraft());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 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.mixin.fabric;
|
||||
|
||||
import dev.architectury.event.events.common.PlayerEvent;
|
||||
import net.minecraft.advancements.Advancement;
|
||||
import net.minecraft.server.PlayerAdvancements;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
@Mixin(PlayerAdvancements.class)
|
||||
public class MixinPlayerAdvancements {
|
||||
@Shadow
|
||||
private ServerPlayer player;
|
||||
|
||||
@Inject(method = "award",
|
||||
at = @At(value = "INVOKE", target = "Lnet/minecraft/advancements/AdvancementRewards;grant(Lnet/minecraft/server/level/ServerPlayer;)V",
|
||||
shift = At.Shift.AFTER))
|
||||
private void award(Advancement advancement, String string, CallbackInfoReturnable<Boolean> cir) {
|
||||
PlayerEvent.PLAYER_ADVANCEMENT.invoker().award(player, advancement);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 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.mixin.fabric;
|
||||
|
||||
import dev.architectury.event.events.common.PlayerEvent;
|
||||
import net.minecraft.network.Connection;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.server.players.PlayerList;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
@Mixin(PlayerList.class)
|
||||
public class MixinPlayerList {
|
||||
@Inject(method = "placeNewPlayer", at = @At("RETURN"))
|
||||
private void placeNewPlayer(Connection connection, ServerPlayer serverPlayer, CallbackInfo ci) {
|
||||
PlayerEvent.PLAYER_JOIN.invoker().join(serverPlayer);
|
||||
}
|
||||
|
||||
@Inject(method = "remove", at = @At("HEAD"))
|
||||
private void remove(ServerPlayer serverPlayer, CallbackInfo ci) {
|
||||
PlayerEvent.PLAYER_QUIT.invoker().quit(serverPlayer);
|
||||
}
|
||||
|
||||
@Inject(method = "respawn", at = @At("RETURN"))
|
||||
private void respawn(ServerPlayer serverPlayer, boolean bl, CallbackInfoReturnable<ServerPlayer> cir) {
|
||||
PlayerEvent.PLAYER_RESPAWN.invoker().respawn(cir.getReturnValue(), bl);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 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.mixin.fabric;
|
||||
|
||||
import dev.architectury.event.events.common.PlayerEvent;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.inventory.CraftingContainer;
|
||||
import net.minecraft.world.inventory.ResultSlot;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
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(ResultSlot.class)
|
||||
public class MixinResultSlot {
|
||||
@Shadow
|
||||
@Final
|
||||
private Player player;
|
||||
|
||||
@Shadow
|
||||
@Final
|
||||
private CraftingContainer craftSlots;
|
||||
|
||||
@Inject(method = "checkTakeAchievements", at = @At(value = "INVOKE",
|
||||
target = "Lnet/minecraft/world/item/ItemStack;onCraftedBy(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/entity/player/Player;I)V",
|
||||
shift = At.Shift.AFTER))
|
||||
private void craft(ItemStack itemStack, CallbackInfo ci) {
|
||||
PlayerEvent.CRAFT_ITEM.invoker().craft(player, itemStack, craftSlots);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 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.mixin.fabric;
|
||||
|
||||
import dev.architectury.event.events.common.ChatEvent;
|
||||
import dev.architectury.impl.fabric.ChatComponentImpl;
|
||||
import net.minecraft.network.chat.ChatType;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.TranslatableComponent;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.server.network.ServerGamePacketListenerImpl;
|
||||
import net.minecraft.server.network.TextFilter;
|
||||
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;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
@Mixin(ServerGamePacketListenerImpl.class)
|
||||
public abstract class MixinServerGamePacketListenerImpl {
|
||||
@Shadow
|
||||
public ServerPlayer player;
|
||||
|
||||
@Shadow
|
||||
@Final
|
||||
private MinecraftServer server;
|
||||
|
||||
@Shadow
|
||||
private int chatSpamTickCount;
|
||||
|
||||
@Shadow
|
||||
public abstract void disconnect(Component component);
|
||||
|
||||
@Inject(method = "handleChat(Lnet/minecraft/server/network/TextFilter$FilteredText;)V",
|
||||
at = @At(value = "INVOKE",
|
||||
target = "Lnet/minecraft/server/players/PlayerList;broadcastMessage(Lnet/minecraft/network/chat/Component;Ljava/util/function/Function;Lnet/minecraft/network/chat/ChatType;Ljava/util/UUID;)V"),
|
||||
cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD)
|
||||
private void handleChat(TextFilter.FilteredText message, CallbackInfo ci, String string, Component component, Component component2) {
|
||||
var chatComponent = new ChatComponentImpl(component2, component);
|
||||
var process = ChatEvent.SERVER.invoker().process(this.player, message, chatComponent);
|
||||
if (process.isEmpty()) return;
|
||||
if (process.isFalse()) {
|
||||
ci.cancel();
|
||||
} else if (!Objects.equals(chatComponent.getRaw(), component2) || !Objects.equals(chatComponent.getFiltered(), component)) {
|
||||
this.server.getPlayerList().broadcastMessage(chatComponent.getRaw(), (serverPlayer) -> {
|
||||
return this.player.shouldFilterMessageTo(serverPlayer) ? chatComponent.getFiltered() : chatComponent.getRaw();
|
||||
}, ChatType.CHAT, this.player.getUUID());
|
||||
|
||||
this.chatSpamTickCount += 20;
|
||||
if (this.chatSpamTickCount > 200 && !this.server.getPlayerList().isOp(this.player.getGameProfile())) {
|
||||
this.disconnect(new TranslatableComponent("disconnect.spam"));
|
||||
}
|
||||
ci.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 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.mixin.fabric;
|
||||
|
||||
import dev.architectury.event.events.common.LifecycleEvent;
|
||||
import dev.architectury.hooks.fabric.PersistentEntitySectionManagerHooks;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.util.ProgressListener;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.level.entity.PersistentEntitySectionManager;
|
||||
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.CallbackInfoReturnable;
|
||||
|
||||
@Mixin(ServerLevel.class)
|
||||
public class MixinServerLevel {
|
||||
@Shadow
|
||||
@Final
|
||||
private PersistentEntitySectionManager<Entity> entityManager;
|
||||
|
||||
@Inject(method = "save", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerChunkCache;save(Z)V"))
|
||||
private void save(ProgressListener progressListener, boolean bl, boolean bl2, CallbackInfo ci) {
|
||||
LifecycleEvent.SERVER_LEVEL_SAVE.invoker().act((ServerLevel) (Object) this);
|
||||
}
|
||||
|
||||
@Inject(method = "addEntity", at = @At(value = "INVOKE",
|
||||
target = "Lnet/minecraft/world/level/entity/PersistentEntitySectionManager;addNewEntity(Lnet/minecraft/world/level/entity/EntityAccess;)Z"),
|
||||
cancellable = true)
|
||||
private void addEntity(Entity entity, CallbackInfoReturnable<Boolean> cir) {
|
||||
((PersistentEntitySectionManagerHooks) this.entityManager).architectury_attachLevel((ServerLevel) (Object) this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 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.mixin.fabric;
|
||||
|
||||
import dev.architectury.event.events.common.PlayerEvent;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.Container;
|
||||
import net.minecraft.world.MenuProvider;
|
||||
import net.minecraft.world.entity.animal.horse.AbstractHorse;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
import java.util.OptionalInt;
|
||||
|
||||
@Mixin(ServerPlayer.class)
|
||||
public class MixinServerPlayer {
|
||||
@Inject(method = "restoreFrom", at = @At("RETURN"))
|
||||
private void restoreFrom(ServerPlayer serverPlayer, boolean bl, CallbackInfo ci) {
|
||||
PlayerEvent.PLAYER_CLONE.invoker().clone((ServerPlayer) (Object) this, serverPlayer, bl);
|
||||
}
|
||||
|
||||
@Inject(method = "openMenu", at = @At("RETURN"))
|
||||
private void openMenu(MenuProvider menuProvider, CallbackInfoReturnable<OptionalInt> cir) {
|
||||
if (cir.getReturnValue().isPresent()) {
|
||||
PlayerEvent.OPEN_MENU.invoker().open((ServerPlayer) (Object) this, ((ServerPlayer) (Object) this).containerMenu);
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "openHorseInventory", at = @At("RETURN"))
|
||||
private void openHorseInventory(AbstractHorse abstractHorse, Container container, CallbackInfo ci) {
|
||||
PlayerEvent.OPEN_MENU.invoker().open((ServerPlayer) (Object) this, ((ServerPlayer) (Object) this).containerMenu);
|
||||
}
|
||||
|
||||
@Inject(method = "doCloseContainer",
|
||||
at = @At(value = "INVOKE", target = "Lnet/minecraft/world/inventory/AbstractContainerMenu;removed(Lnet/minecraft/world/entity/player/Player;)V",
|
||||
shift = At.Shift.AFTER))
|
||||
private void doCloseContainer(CallbackInfo ci) {
|
||||
PlayerEvent.CLOSE_MENU.invoker().close((ServerPlayer) (Object) this, ((ServerPlayer) (Object) this).containerMenu);
|
||||
}
|
||||
|
||||
@Inject(method = "triggerDimensionChangeTriggers", at = @At("HEAD"))
|
||||
private void changeDimension(ServerLevel serverLevel, CallbackInfo ci) {
|
||||
PlayerEvent.CHANGE_DIMENSION.invoker().change((ServerPlayer) (Object) this, serverLevel.dimension(), ((ServerPlayer) (Object) this).level.dimension());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 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.mixin.fabric;
|
||||
|
||||
import dev.architectury.event.events.common.BlockEvent;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.server.level.ServerPlayerGameMode;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
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.CallbackInfoReturnable;
|
||||
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
|
||||
|
||||
@Mixin(ServerPlayerGameMode.class)
|
||||
public class MixinServerPlayerGameMode {
|
||||
@Shadow
|
||||
protected ServerLevel level;
|
||||
|
||||
@Shadow
|
||||
@Final
|
||||
protected ServerPlayer player;
|
||||
|
||||
@Inject(method = "destroyBlock", at = @At(value = "INVOKE",
|
||||
target = "Lnet/minecraft/world/level/block/state/BlockState;getBlock()Lnet/minecraft/world/level/block/Block;",
|
||||
ordinal = 0),
|
||||
locals = LocalCapture.CAPTURE_FAILHARD, cancellable = true)
|
||||
private void onBreak(BlockPos blockPos, CallbackInfoReturnable<Boolean> cir, BlockState state) {
|
||||
if (BlockEvent.BREAK.invoker().breakBlock(this.level, blockPos, state, this.player, null).isFalse()) {
|
||||
cir.setReturnValue(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 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.mixin.fabric;
|
||||
|
||||
import dev.architectury.event.events.common.EntityEvent;
|
||||
import net.minecraft.client.player.LocalPlayer;
|
||||
import net.minecraft.client.player.RemotePlayer;
|
||||
import net.minecraft.world.damagesource.DamageSource;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
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;
|
||||
|
||||
@Mixin(value = {LocalPlayer.class, Player.class, RemotePlayer.class})
|
||||
public class PlayerAttackInvoker {
|
||||
@Inject(method = "hurt", at = @At("HEAD"), cancellable = true)
|
||||
private void hurt(DamageSource damageSource, float f, CallbackInfoReturnable<Boolean> cir) {
|
||||
if (EntityEvent.LIVING_HURT.invoker().hurt((LivingEntity) (Object) this, damageSource, f).isFalse() && (Object) this instanceof Player) {
|
||||
cir.setReturnValue(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 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.mixin.fabric.client;
|
||||
|
||||
import dev.architectury.event.events.client.ClientLifecycleEvent;
|
||||
import dev.architectury.event.events.common.EntityEvent;
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.client.multiplayer.ClientPacketListener;
|
||||
import net.minecraft.client.renderer.LevelRenderer;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.util.profiling.ProfilerFiller;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.dimension.DimensionType;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
@Mixin(ClientLevel.class)
|
||||
public class MixinClientLevel {
|
||||
@Inject(method = "<init>", at = @At("RETURN"))
|
||||
private void construct(ClientPacketListener clientPacketListener, ClientLevel.ClientLevelData clientLevelData, ResourceKey<Level> resourceKey, DimensionType dimensionType, int i, Supplier<ProfilerFiller> supplier, LevelRenderer levelRenderer, boolean bl, long l, CallbackInfo ci) {
|
||||
ClientLifecycleEvent.CLIENT_LEVEL_LOAD.invoker().act((ClientLevel) (Object) this);
|
||||
}
|
||||
|
||||
@Inject(method = "addEntity", at = @At("HEAD"), cancellable = true)
|
||||
private void addEntity(int i, Entity entity, CallbackInfo ci) {
|
||||
if (EntityEvent.ADD.invoker().add(entity, (ClientLevel) (Object) this).isFalse()) {
|
||||
ci.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 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.mixin.fabric.client;
|
||||
|
||||
import dev.architectury.event.events.client.ClientChatEvent;
|
||||
import dev.architectury.event.events.client.ClientPlayerEvent;
|
||||
import dev.architectury.event.events.client.ClientRecipeUpdateEvent;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.multiplayer.ClientPacketListener;
|
||||
import net.minecraft.client.player.LocalPlayer;
|
||||
import net.minecraft.network.protocol.game.ClientboundChatPacket;
|
||||
import net.minecraft.network.protocol.game.ClientboundLoginPacket;
|
||||
import net.minecraft.network.protocol.game.ClientboundRespawnPacket;
|
||||
import net.minecraft.network.protocol.game.ClientboundUpdateRecipesPacket;
|
||||
import net.minecraft.world.item.crafting.RecipeManager;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(ClientPacketListener.class)
|
||||
public class MixinClientPacketListener {
|
||||
@Shadow
|
||||
@Final
|
||||
private Minecraft minecraft;
|
||||
@Shadow
|
||||
@Final
|
||||
private RecipeManager recipeManager;
|
||||
@Unique
|
||||
private LocalPlayer tmpPlayer;
|
||||
|
||||
@Inject(method = "handleLogin", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/Options;broadcastOptions()V"))
|
||||
private void handleLogin(ClientboundLoginPacket packet, CallbackInfo ci) {
|
||||
ClientPlayerEvent.CLIENT_PLAYER_JOIN.invoker().join(minecraft.player);
|
||||
}
|
||||
|
||||
@Inject(method = "handleRespawn", at = @At("HEAD"))
|
||||
private void handleRespawnPre(ClientboundRespawnPacket packet, CallbackInfo ci) {
|
||||
this.tmpPlayer = minecraft.player;
|
||||
}
|
||||
|
||||
@Inject(method = "handleRespawn", at = @At(value = "INVOKE",
|
||||
target = "Lnet/minecraft/client/multiplayer/ClientLevel;addPlayer(ILnet/minecraft/client/player/AbstractClientPlayer;)V"))
|
||||
private void handleRespawn(ClientboundRespawnPacket packet, CallbackInfo ci) {
|
||||
ClientPlayerEvent.CLIENT_PLAYER_RESPAWN.invoker().respawn(tmpPlayer, minecraft.player);
|
||||
this.tmpPlayer = null;
|
||||
}
|
||||
|
||||
@Inject(method = "handleChat", at = @At(value = "INVOKE",
|
||||
target = "Lnet/minecraft/client/gui/Gui;handleChat(Lnet/minecraft/network/chat/ChatType;Lnet/minecraft/network/chat/Component;Ljava/util/UUID;)V"),
|
||||
cancellable = true)
|
||||
private void handleChat(ClientboundChatPacket packet, CallbackInfo ci) {
|
||||
var process = ClientChatEvent.RECEIVED.invoker().process(packet.getType(), packet.getMessage(), packet.getSender());
|
||||
if (process.isEmpty()) return;
|
||||
if (process.isFalse()) {
|
||||
ci.cancel();
|
||||
} else if (process.object() != null && !process.object().equals(packet.getMessage())) {
|
||||
this.minecraft.gui.handleChat(packet.getType(), packet.getMessage(), packet.getSender());
|
||||
ci.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "handleUpdateRecipes", at = @At("RETURN"))
|
||||
private void handleUpdateRecipes(ClientboundUpdateRecipesPacket clientboundUpdateRecipesPacket, CallbackInfo ci) {
|
||||
ClientRecipeUpdateEvent.EVENT.invoker().update(recipeManager);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 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.mixin.fabric.client;
|
||||
|
||||
import dev.architectury.event.events.client.ClientGuiEvent;
|
||||
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 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());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 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.mixin.fabric.client;
|
||||
|
||||
import com.mojang.blaze3d.shaders.Program;
|
||||
import net.minecraft.client.renderer.EffectInstance;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.packs.resources.ResourceManager;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
|
||||
@Unique
|
||||
@Mixin(value = EffectInstance.class, priority = 950)
|
||||
public class MixinEffectInstance {
|
||||
@Redirect(
|
||||
method = "<init>",
|
||||
at = @At(value = "NEW",
|
||||
target = "(Ljava/lang/String;)Lnet/minecraft/resources/ResourceLocation;",
|
||||
ordinal = 0)
|
||||
)
|
||||
private ResourceLocation mojangPls(String _0, ResourceManager rm, String str) {
|
||||
return mojangPls(new ResourceLocation(str), ".json");
|
||||
}
|
||||
|
||||
@Redirect(
|
||||
method = "getOrCreate",
|
||||
at = @At(value = "NEW",
|
||||
target = "(Ljava/lang/String;)Lnet/minecraft/resources/ResourceLocation;",
|
||||
ordinal = 0)
|
||||
)
|
||||
private static ResourceLocation mojangPls(String _0, ResourceManager rm, Program.Type type, String str) {
|
||||
return mojangPls(new ResourceLocation(str), type.getExtension());
|
||||
}
|
||||
|
||||
private static ResourceLocation mojangPls(ResourceLocation rl, String ext) {
|
||||
return new ResourceLocation(rl.getNamespace(), "shaders/program/" + rl.getPath() + ext);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 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.mixin.fabric.client;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import dev.architectury.event.events.client.ClientGuiEvent;
|
||||
import net.minecraft.client.Minecraft;
|
||||
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;
|
||||
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
|
||||
|
||||
@Mixin(GameRenderer.class)
|
||||
public abstract class MixinGameRenderer {
|
||||
@Shadow
|
||||
@Final
|
||||
private Minecraft minecraft;
|
||||
|
||||
@Inject(method = "render(FJZ)V",
|
||||
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screens/Screen;render(Lcom/mojang/blaze3d/vertex/PoseStack;IIF)V",
|
||||
ordinal = 0), locals = LocalCapture.CAPTURE_FAILEXCEPTION, cancellable = true)
|
||||
public void renderScreenPre(float tickDelta, long startTime, boolean tick, CallbackInfo ci, int mouseX, int mouseY, PoseStack matrices) {
|
||||
if (ClientGuiEvent.RENDER_PRE.invoker().render(minecraft.screen, matrices, mouseX, mouseY, minecraft.getDeltaFrameTime()).isFalse()) {
|
||||
ci.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "render(FJZ)V",
|
||||
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screens/Screen;render(Lcom/mojang/blaze3d/vertex/PoseStack;IIF)V",
|
||||
shift = At.Shift.AFTER, ordinal = 0), locals = LocalCapture.CAPTURE_FAILEXCEPTION)
|
||||
public void renderScreenPost(float tickDelta, long startTime, boolean tick, CallbackInfo ci, int mouseX, int mouseY, PoseStack matrices) {
|
||||
ClientGuiEvent.RENDER_POST.invoker().render(minecraft.screen, matrices, mouseX, mouseY, minecraft.getDeltaFrameTime());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 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.mixin.fabric.client;
|
||||
|
||||
import dev.architectury.event.events.common.LifecycleEvent;
|
||||
import net.minecraft.client.server.IntegratedServer;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
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;
|
||||
|
||||
@Mixin(IntegratedServer.class)
|
||||
public class MixinIntegratedServer {
|
||||
@Inject(method = "initServer", at = @At("RETURN"), cancellable = true)
|
||||
private void initServer(CallbackInfoReturnable<Boolean> cir) {
|
||||
if (cir.getReturnValueZ()) {
|
||||
LifecycleEvent.SERVER_STARTING.invoker().stateChanged((MinecraftServer) (Object) this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 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.mixin.fabric.client;
|
||||
|
||||
import dev.architectury.event.EventResult;
|
||||
import dev.architectury.event.events.client.ClientRawInputEvent;
|
||||
import dev.architectury.event.events.client.ClientScreenInputEvent;
|
||||
import dev.architectury.impl.fabric.ScreenInputDelegate;
|
||||
import net.minecraft.client.KeyboardHandler;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.components.events.GuiEventListener;
|
||||
import net.minecraft.client.gui.screens.Screen;
|
||||
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.ModifyVariable;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
|
||||
|
||||
@Mixin(KeyboardHandler.class)
|
||||
public class MixinKeyboardHandler {
|
||||
@Shadow
|
||||
@Final
|
||||
private Minecraft minecraft;
|
||||
|
||||
@Shadow
|
||||
private boolean sendRepeatsToGui;
|
||||
|
||||
@ModifyVariable(method = {"method_1458", "lambda$charTyped$5"}, at = @At("HEAD"), ordinal = 0, argsOnly = true)
|
||||
private static GuiEventListener wrapCharTypedFirst(GuiEventListener screen) {
|
||||
if (screen instanceof ScreenInputDelegate delegate) {
|
||||
return delegate.architectury_delegateInputs();
|
||||
}
|
||||
return screen;
|
||||
}
|
||||
|
||||
@ModifyVariable(method = {"method_1473", "lambda$charTyped$6"}, at = @At("HEAD"), ordinal = 0, argsOnly = true)
|
||||
private static GuiEventListener wrapCharTypedSecond(GuiEventListener screen) {
|
||||
if (screen instanceof ScreenInputDelegate delegate) {
|
||||
return delegate.architectury_delegateInputs();
|
||||
}
|
||||
return screen;
|
||||
}
|
||||
|
||||
@Inject(method = "keyPress", at = @At(value = "INVOKE",
|
||||
target = "Lnet/minecraft/client/gui/screens/Screen;wrapScreenError(Ljava/lang/Runnable;Ljava/lang/String;Ljava/lang/String;)V",
|
||||
ordinal = 0), cancellable = true)
|
||||
public void onKey(long long_1, int int_1, int int_2, int int_3, int int_4, CallbackInfo info) {
|
||||
if (!info.isCancelled()) {
|
||||
if (int_3 != 1 && (int_3 != 2 || !this.sendRepeatsToGui)) {
|
||||
if (int_3 == 0) {
|
||||
var result = ClientScreenInputEvent.KEY_RELEASED_PRE.invoker().keyReleased(minecraft, minecraft.screen, int_1, int_2, int_4);
|
||||
if (result.isPresent())
|
||||
info.cancel();
|
||||
}
|
||||
} else {
|
||||
var result = ClientScreenInputEvent.KEY_PRESSED_PRE.invoker().keyPressed(minecraft, minecraft.screen, int_1, int_2, int_4);
|
||||
if (result.isPresent())
|
||||
info.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "keyPress", at = @At(value = "INVOKE",
|
||||
target = "Lnet/minecraft/client/gui/screens/Screen;wrapScreenError(Ljava/lang/Runnable;Ljava/lang/String;Ljava/lang/String;)V",
|
||||
ordinal = 0, shift = At.Shift.AFTER), locals = LocalCapture.CAPTURE_FAILHARD,
|
||||
cancellable = true)
|
||||
public void onKeyAfter(long long_1, int int_1, int int_2, int int_3, int int_4, CallbackInfo info, Screen screen, boolean bls[]) {
|
||||
if (!info.isCancelled() && !bls[0]) {
|
||||
EventResult result;
|
||||
if (int_3 != 1 && (int_3 != 2 || !this.sendRepeatsToGui)) {
|
||||
result = ClientScreenInputEvent.KEY_RELEASED_POST.invoker().keyReleased(minecraft, screen, int_1, int_2, int_4);
|
||||
} else {
|
||||
result = ClientScreenInputEvent.KEY_PRESSED_POST.invoker().keyPressed(minecraft, screen, int_1, int_2, int_4);
|
||||
}
|
||||
if (result.isPresent())
|
||||
info.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
@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);
|
||||
if (result.isPresent())
|
||||
info.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 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.mixin.fabric.client;
|
||||
|
||||
import dev.architectury.event.events.client.ClientGuiEvent;
|
||||
import dev.architectury.event.events.client.ClientPlayerEvent;
|
||||
import dev.architectury.event.events.common.InteractionEvent;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.screens.Screen;
|
||||
import net.minecraft.client.player.LocalPlayer;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.phys.HitResult;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.ModifyVariable;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
|
||||
|
||||
@Unique
|
||||
@Mixin(Minecraft.class)
|
||||
public abstract class MixinMinecraft {
|
||||
@Shadow
|
||||
@Nullable
|
||||
public LocalPlayer player;
|
||||
|
||||
@Shadow
|
||||
@Nullable
|
||||
public HitResult hitResult;
|
||||
|
||||
@Shadow
|
||||
public abstract void setScreen(@Nullable Screen screen);
|
||||
|
||||
@Unique
|
||||
private ThreadLocal<Boolean> setScreenCancelled = new ThreadLocal<>();
|
||||
|
||||
@Inject(method = "clearLevel(Lnet/minecraft/client/gui/screens/Screen;)V",
|
||||
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/chat/NarratorChatListener;clear()V"))
|
||||
private void handleLogin(Screen screen, CallbackInfo ci) {
|
||||
ClientPlayerEvent.CLIENT_PLAYER_QUIT.invoker().quit(player);
|
||||
}
|
||||
|
||||
@Inject(method = "startUseItem", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/ItemStack;isEmpty()Z", ordinal = 1),
|
||||
locals = LocalCapture.CAPTURE_FAILHARD)
|
||||
private void rightClickAir(CallbackInfo ci, InteractionHand[] var1, int var2, int var3, InteractionHand interactionHand, ItemStack itemStack) {
|
||||
if (itemStack.isEmpty() && (this.hitResult == null || this.hitResult.getType() == HitResult.Type.MISS)) {
|
||||
InteractionEvent.CLIENT_RIGHT_CLICK_AIR.invoker().click(player, interactionHand);
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "startAttack", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/player/LocalPlayer;resetAttackStrengthTicker()V", ordinal = 0))
|
||||
private void leftClickAir(CallbackInfo ci) {
|
||||
InteractionEvent.CLIENT_LEFT_CLICK_AIR.invoker().click(player, InteractionHand.MAIN_HAND);
|
||||
}
|
||||
|
||||
@ModifyVariable(
|
||||
method = "setScreen",
|
||||
at = @At(value = "FIELD",
|
||||
opcode = Opcodes.PUTFIELD,
|
||||
target = "Lnet/minecraft/client/Minecraft;screen:Lnet/minecraft/client/gui/screens/Screen;",
|
||||
shift = At.Shift.BY,
|
||||
by = -1),
|
||||
argsOnly = true
|
||||
)
|
||||
public Screen modifyScreen(Screen screen) {
|
||||
var old = screen;
|
||||
var event = ClientGuiEvent.SET_SCREEN.invoker().modifyScreen(screen);
|
||||
if (event.isPresent()) {
|
||||
if (event.isFalse()) {
|
||||
setScreenCancelled.set(true);
|
||||
return old;
|
||||
} else {
|
||||
screen = event.object();
|
||||
if (old != null && screen != old) {
|
||||
old.removed();
|
||||
}
|
||||
}
|
||||
}
|
||||
setScreenCancelled.set(false);
|
||||
return screen;
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "setScreen",
|
||||
at = @At(value = "FIELD",
|
||||
opcode = Opcodes.PUTFIELD,
|
||||
target = "Lnet/minecraft/client/Minecraft;screen:Lnet/minecraft/client/gui/screens/Screen;",
|
||||
shift = At.Shift.BY,
|
||||
by = -1),
|
||||
cancellable = true
|
||||
)
|
||||
public void cancelSetScreen(@Nullable Screen screen, CallbackInfo ci) {
|
||||
if (setScreenCancelled.get()) {
|
||||
ci.cancel();
|
||||
setScreenCancelled.set(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,163 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 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.mixin.fabric.client;
|
||||
|
||||
import dev.architectury.event.events.client.ClientRawInputEvent;
|
||||
import dev.architectury.event.events.client.ClientScreenInputEvent;
|
||||
import dev.architectury.impl.fabric.ScreenInputDelegate;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.MouseHandler;
|
||||
import net.minecraft.client.gui.screens.Screen;
|
||||
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.ModifyVariable;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
|
||||
|
||||
@Mixin(MouseHandler.class)
|
||||
public class MixinMouseHandler {
|
||||
@Shadow
|
||||
@Final
|
||||
private Minecraft minecraft;
|
||||
|
||||
@Shadow
|
||||
private int activeButton;
|
||||
|
||||
@Shadow
|
||||
private double xpos;
|
||||
|
||||
@Shadow
|
||||
private double ypos;
|
||||
|
||||
@Inject(method = "onScroll",
|
||||
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screens/Screen;mouseScrolled(DDD)Z",
|
||||
ordinal = 0), cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD)
|
||||
public void onMouseScrolled(long handle, double xOffset, double yOffset, CallbackInfo info, double amount, double x, double y) {
|
||||
if (!info.isCancelled()) {
|
||||
var result = ClientScreenInputEvent.MOUSE_SCROLLED_PRE.invoker().mouseScrolled(minecraft, minecraft.screen, x, y, amount);
|
||||
if (result.isPresent())
|
||||
info.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "onScroll",
|
||||
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screens/Screen;mouseScrolled(DDD)Z",
|
||||
ordinal = 0, shift = At.Shift.AFTER), cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD)
|
||||
public void onMouseScrolledPost(long handle, double xOffset, double yOffset, CallbackInfo info, double amount, double x, double y) {
|
||||
if (!info.isCancelled()) {
|
||||
var result = ClientScreenInputEvent.MOUSE_SCROLLED_POST.invoker().mouseScrolled(minecraft, minecraft.screen, x, y, amount);
|
||||
}
|
||||
}
|
||||
|
||||
@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, double amount) {
|
||||
if (!info.isCancelled()) {
|
||||
var result = ClientRawInputEvent.MOUSE_SCROLLED.invoker().mouseScrolled(minecraft, amount);
|
||||
if (result.isPresent())
|
||||
info.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("UnresolvedMixinReference")
|
||||
@Inject(method = {"lambda$onPress$0", "method_1611"}, at = @At("HEAD"), cancellable = true, remap = false)
|
||||
private static void onGuiMouseClicked(boolean[] bls, Screen screen, double d, double e, int button, CallbackInfo info) {
|
||||
var minecraft = Minecraft.getInstance();
|
||||
if (!info.isCancelled()) {
|
||||
var result = ClientScreenInputEvent.MOUSE_CLICKED_PRE.invoker().mouseClicked(minecraft, screen, d, e, button);
|
||||
if (result.isPresent()) {
|
||||
bls[0] = true;
|
||||
info.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("UnresolvedMixinReference")
|
||||
@Inject(method = {"lambda$onPress$0", "method_1611"}, at = @At("RETURN"), cancellable = true, remap = false)
|
||||
private static void onGuiMouseClickedPost(boolean[] bls, Screen screen, double d, double e, int button, CallbackInfo info) {
|
||||
var minecraft = Minecraft.getInstance();
|
||||
if (!info.isCancelled() && !bls[0]) {
|
||||
var result = ClientScreenInputEvent.MOUSE_CLICKED_POST.invoker().mouseClicked(minecraft, screen, d, e, button);
|
||||
if (result.isPresent()) {
|
||||
bls[0] = true;
|
||||
info.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "onPress", 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) {
|
||||
if (!info.isCancelled()) {
|
||||
var result = ClientRawInputEvent.MOUSE_CLICKED_PRE.invoker().mouseClicked(minecraft, button, action, mods);
|
||||
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);
|
||||
if (result.isPresent())
|
||||
info.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("UnresolvedMixinReference")
|
||||
@Inject(method = {"lambda$onPress$1", "method_1605"}, at = @At("HEAD"), cancellable = true, remap = false)
|
||||
private static void onGuiMouseReleased(boolean[] bls, Screen screen, double d, double e, int button, CallbackInfo info) {
|
||||
var minecraft = Minecraft.getInstance();
|
||||
if (!info.isCancelled()) {
|
||||
var result = ClientScreenInputEvent.MOUSE_RELEASED_PRE.invoker().mouseReleased(minecraft, screen, d, e, button);
|
||||
if (result.isPresent()) {
|
||||
bls[0] = true;
|
||||
info.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("UnresolvedMixinReference")
|
||||
@Inject(method = {"lambda$onPress$1", "method_1605"}, at = @At("RETURN"), cancellable = true, remap = false)
|
||||
private static void onGuiMouseReleasedPost(boolean[] bls, Screen screen, double d, double e, int button, CallbackInfo info) {
|
||||
var minecraft = Minecraft.getInstance();
|
||||
if (!info.isCancelled() && !bls[0]) {
|
||||
var result = ClientScreenInputEvent.MOUSE_RELEASED_POST.invoker().mouseReleased(minecraft, screen, d, e, button);
|
||||
if (result.isPresent()) {
|
||||
bls[0] = true;
|
||||
info.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("UnresolvedMixinReference")
|
||||
@ModifyVariable(method = {"method_1602", "lambda$onMove$11"}, at = @At("HEAD"), ordinal = 0, argsOnly = true)
|
||||
private Screen wrapMouseDragged(Screen screen) {
|
||||
if (screen instanceof ScreenInputDelegate delegate) {
|
||||
return delegate.architectury_delegateInputs();
|
||||
}
|
||||
return screen;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 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.mixin.fabric.client;
|
||||
|
||||
import dev.architectury.event.events.common.InteractionEvent;
|
||||
import net.minecraft.client.multiplayer.MultiPlayerGameMode;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.InteractionResult;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
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;
|
||||
|
||||
@Mixin(MultiPlayerGameMode.class)
|
||||
public class MixinMultiPlayerGameMode {
|
||||
@Inject(method = "interact",
|
||||
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/multiplayer/ClientPacketListener;send(Lnet/minecraft/network/protocol/Packet;)V",
|
||||
shift = At.Shift.AFTER),
|
||||
cancellable = true)
|
||||
private void entityInteract(Player player, Entity entity, InteractionHand interactionHand, CallbackInfoReturnable<InteractionResult> cir) {
|
||||
var result = InteractionEvent.INTERACT_ENTITY.invoker().interact(player, entity, interactionHand);
|
||||
if (result.isPresent()) {
|
||||
cir.setReturnValue(result.asMinecraft());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 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.mixin.fabric.client;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import dev.architectury.event.events.client.ClientChatEvent;
|
||||
import dev.architectury.event.events.client.ClientGuiEvent;
|
||||
import dev.architectury.event.events.client.ClientTooltipEvent;
|
||||
import dev.architectury.hooks.client.screen.ScreenAccess;
|
||||
import dev.architectury.impl.ScreenAccessImpl;
|
||||
import dev.architectury.impl.TooltipEventColorContextImpl;
|
||||
import dev.architectury.impl.TooltipEventPositionContextImpl;
|
||||
import dev.architectury.impl.fabric.ScreenInputDelegate;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.components.events.GuiEventListener;
|
||||
import net.minecraft.client.gui.screens.Screen;
|
||||
import net.minecraft.util.FormattedCharSequence;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.*;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mixin(Screen.class)
|
||||
public abstract class MixinScreen implements ScreenInputDelegate {
|
||||
@Unique
|
||||
private static ThreadLocal<TooltipEventPositionContextImpl> tooltipPositionContext = ThreadLocal.withInitial(TooltipEventPositionContextImpl::new);
|
||||
@Unique
|
||||
private static ThreadLocal<TooltipEventColorContextImpl> tooltipColorContext = ThreadLocal.withInitial(TooltipEventColorContextImpl::new);
|
||||
@Unique
|
||||
private ScreenAccessImpl access;
|
||||
|
||||
@Shadow
|
||||
public abstract List<? extends GuiEventListener> children();
|
||||
|
||||
@Unique
|
||||
private Screen inputDelegate;
|
||||
|
||||
@Unique
|
||||
private ScreenAccess getAccess() {
|
||||
if (access == null) {
|
||||
return access = new ScreenAccessImpl((Screen) (Object) this);
|
||||
}
|
||||
|
||||
access.setScreen((Screen) (Object) this); // Preventive set
|
||||
return access;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Screen architectury_delegateInputs() {
|
||||
if (inputDelegate == null) {
|
||||
inputDelegate = new DelegateScreen((Screen) (Object) this);
|
||||
}
|
||||
return inputDelegate;
|
||||
}
|
||||
|
||||
@Inject(method = "init(Lnet/minecraft/client/Minecraft;II)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screens/Screen;clearWidgets()V", ordinal = 0),
|
||||
cancellable = true)
|
||||
private void preInit(Minecraft minecraft, int i, int j, CallbackInfo ci) {
|
||||
if (ClientGuiEvent.INIT_PRE.invoker().init((Screen) (Object) this, getAccess()).isFalse()) {
|
||||
ci.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "init(Lnet/minecraft/client/Minecraft;II)V", at = @At(value = "RETURN"))
|
||||
private void postInit(Minecraft minecraft, int i, int j, CallbackInfo ci) {
|
||||
ClientGuiEvent.INIT_POST.invoker().init((Screen) (Object) this, getAccess());
|
||||
}
|
||||
|
||||
@ModifyVariable(method = "sendMessage(Ljava/lang/String;Z)V", at = @At("HEAD"), argsOnly = true, ordinal = 0)
|
||||
private String modifyMessage(String message) {
|
||||
var process = ClientChatEvent.PROCESS.invoker().process(message);
|
||||
if (process.isPresent()) {
|
||||
if (process.isFalse())
|
||||
return "";
|
||||
if (process.object() != null)
|
||||
return process.object();
|
||||
}
|
||||
return message;
|
||||
}
|
||||
|
||||
@Inject(method = "renderTooltipInternal", at = @At("HEAD"), cancellable = true)
|
||||
private void renderTooltip(PoseStack poseStack, List<? extends FormattedCharSequence> list, int x, int y, CallbackInfo ci) {
|
||||
if (!list.isEmpty()) {
|
||||
var colorContext = tooltipColorContext.get();
|
||||
colorContext.reset();
|
||||
var positionContext = tooltipPositionContext.get();
|
||||
positionContext.reset(x, y);
|
||||
if (ClientTooltipEvent.RENDER_VANILLA_PRE.invoker().renderTooltip(poseStack, list, x, y).isFalse()) {
|
||||
ci.cancel();
|
||||
} else {
|
||||
ClientTooltipEvent.RENDER_MODIFY_COLOR.invoker().renderTooltip(poseStack, x, y, colorContext);
|
||||
ClientTooltipEvent.RENDER_MODIFY_POSITION.invoker().renderTooltip(poseStack, positionContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ModifyVariable(method = "renderTooltipInternal",
|
||||
at = @At(value = "HEAD"), ordinal = 0)
|
||||
private int modifyTooltipX(int original) {
|
||||
return tooltipPositionContext.get().getTooltipX();
|
||||
}
|
||||
|
||||
@ModifyVariable(method = "renderTooltipInternal",
|
||||
at = @At(value = "HEAD"), ordinal = 1)
|
||||
private int modifyTooltipY(int original) {
|
||||
return tooltipPositionContext.get().getTooltipY();
|
||||
}
|
||||
|
||||
@ModifyConstant(method = "renderTooltipInternal", constant = @Constant(intValue = 0xf0100010))
|
||||
private int modifyTooltipBackgroundColor(int original) {
|
||||
return tooltipColorContext.get().getBackgroundColor();
|
||||
}
|
||||
|
||||
@ModifyConstant(method = "renderTooltipInternal", constant = @Constant(intValue = 0x505000ff))
|
||||
private int modifyTooltipOutlineGradientTopColor(int original) {
|
||||
return tooltipColorContext.get().getOutlineGradientTopColor();
|
||||
}
|
||||
|
||||
@ModifyConstant(method = "renderTooltipInternal", constant = @Constant(intValue = 0x5028007f))
|
||||
private int modifyTooltipOutlineGradientBottomColor(int original) {
|
||||
return tooltipColorContext.get().getOutlineGradientBottomColor();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 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.mixin.fabric.client;
|
||||
|
||||
import dev.architectury.event.events.client.ClientTextureStitchEvent;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlas;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.packs.resources.ResourceManager;
|
||||
import net.minecraft.util.profiling.ProfilerFiller;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@Mixin(TextureAtlas.class)
|
||||
public class MixinTextureAtlas {
|
||||
@Inject(method = "prepareToStitch",
|
||||
at = @At(value = "INVOKE", target = "Lnet/minecraft/util/profiling/ProfilerFiller;popPush(Ljava/lang/String;)V", ordinal = 0,
|
||||
shift = At.Shift.AFTER), locals = LocalCapture.CAPTURE_FAILHARD)
|
||||
private void preStitch(ResourceManager resourceManager, Stream<ResourceLocation> stream, ProfilerFiller profilerFiller, int i, CallbackInfoReturnable<TextureAtlas.Preparations> cir, Set<ResourceLocation> set) {
|
||||
ClientTextureStitchEvent.PRE.invoker().stitch((TextureAtlas) (Object) this, set::add);
|
||||
}
|
||||
|
||||
@Inject(method = "reload", at = @At("RETURN"))
|
||||
private void postStitch(TextureAtlas.Preparations preparations, CallbackInfo ci) {
|
||||
ClientTextureStitchEvent.POST.invoker().stitch((TextureAtlas) (Object) this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 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.fabric;
|
||||
|
||||
import dev.architectury.networking.NetworkManager;
|
||||
import dev.architectury.networking.NetworkManager.NetworkReceiver;
|
||||
import dev.architectury.utils.Env;
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
import net.fabricmc.fabric.api.network.ClientSidePacketRegistry;
|
||||
import net.fabricmc.fabric.api.network.PacketContext;
|
||||
import net.fabricmc.fabric.api.network.ServerSidePacketRegistry;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.network.protocol.Packet;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
|
||||
public class NetworkManagerImpl {
|
||||
public static void registerReceiver(NetworkManager.Side side, ResourceLocation id, NetworkReceiver receiver) {
|
||||
if (side == NetworkManager.Side.C2S) {
|
||||
registerC2SReceiver(id, receiver);
|
||||
} else if (side == NetworkManager.Side.S2C) {
|
||||
registerS2CReceiver(id, receiver);
|
||||
}
|
||||
}
|
||||
|
||||
private static void registerC2SReceiver(ResourceLocation id, NetworkReceiver receiver) {
|
||||
ServerSidePacketRegistry.INSTANCE.register(id, (packetContext, buf) -> receiver.receive(buf, to(packetContext)));
|
||||
}
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
private static void registerS2CReceiver(ResourceLocation id, NetworkReceiver receiver) {
|
||||
ClientSidePacketRegistry.INSTANCE.register(id, (packetContext, buf) -> receiver.receive(buf, to(packetContext)));
|
||||
}
|
||||
|
||||
private static NetworkManager.PacketContext to(PacketContext context) {
|
||||
return new NetworkManager.PacketContext() {
|
||||
@Override
|
||||
public Player getPlayer() {
|
||||
return context.getPlayer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void queue(Runnable runnable) {
|
||||
context.getTaskQueue().execute(runnable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Env getEnvironment() {
|
||||
return Env.fromPlatform(context.getPacketEnvironment());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static Packet<?> toPacket(NetworkManager.Side side, ResourceLocation id, FriendlyByteBuf buf) {
|
||||
if (side == NetworkManager.Side.C2S) {
|
||||
return toC2SPacket(id, buf);
|
||||
} else if (side == NetworkManager.Side.S2C) {
|
||||
return toS2CPacket(id, buf);
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("Invalid side: " + side);
|
||||
}
|
||||
|
||||
public static boolean canServerReceive(ResourceLocation id) {
|
||||
return ClientSidePacketRegistry.INSTANCE.canServerReceive(id);
|
||||
}
|
||||
|
||||
public static boolean canPlayerReceive(ServerPlayer player, ResourceLocation id) {
|
||||
return ServerSidePacketRegistry.INSTANCE.canPlayerReceive(player, id);
|
||||
}
|
||||
|
||||
public static Packet<?> createAddEntityPacket(Entity entity) {
|
||||
return SpawnEntityPacket.create(entity);
|
||||
}
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
private static Packet<?> toC2SPacket(ResourceLocation id, FriendlyByteBuf buf) {
|
||||
return ClientSidePacketRegistry.INSTANCE.toPacket(id, buf);
|
||||
}
|
||||
|
||||
private static Packet<?> toS2CPacket(ResourceLocation id, FriendlyByteBuf buf) {
|
||||
return ServerSidePacketRegistry.INSTANCE.toPacket(id, buf);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 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.fabric;
|
||||
|
||||
import dev.architectury.networking.NetworkManager;
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
import net.fabricmc.fabric.api.networking.v1.PacketByteBufs;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.network.protocol.Packet;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
|
||||
/**
|
||||
* @see net.minecraft.network.protocol.game.ClientboundAddEntityPacket
|
||||
*/
|
||||
public class SpawnEntityPacket {
|
||||
private static final ResourceLocation PACKET_ID = new ResourceLocation("architectury", "spawn_entity_packet");
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public static void register() {
|
||||
NetworkManager.registerReceiver(NetworkManager.s2c(), PACKET_ID, SpawnEntityPacket::receive);
|
||||
}
|
||||
|
||||
public static Packet<?> create(Entity entity) {
|
||||
if (entity.level.isClientSide()) {
|
||||
throw new IllegalStateException("SpawnPacketUtil.create called on the logical client!");
|
||||
}
|
||||
var buffer = PacketByteBufs.create();
|
||||
buffer.writeVarInt(Registry.ENTITY_TYPE.getId(entity.getType()));
|
||||
buffer.writeUUID(entity.getUUID());
|
||||
buffer.writeVarInt(entity.getId());
|
||||
var position = entity.position();
|
||||
buffer.writeDouble(position.x);
|
||||
buffer.writeDouble(position.y);
|
||||
buffer.writeDouble(position.z);
|
||||
buffer.writeFloat(entity.getXRot());
|
||||
buffer.writeFloat(entity.getYRot());
|
||||
buffer.writeFloat(entity.getYHeadRot());
|
||||
var deltaMovement = entity.getDeltaMovement();
|
||||
buffer.writeDouble(deltaMovement.x);
|
||||
buffer.writeDouble(deltaMovement.y);
|
||||
buffer.writeDouble(deltaMovement.z);
|
||||
return NetworkManager.toPacket(NetworkManager.s2c(), PACKET_ID, buffer);
|
||||
}
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public static void receive(FriendlyByteBuf buf, NetworkManager.PacketContext context) {
|
||||
var entityTypeId = buf.readVarInt();
|
||||
var uuid = buf.readUUID();
|
||||
var id = buf.readVarInt();
|
||||
var x = buf.readDouble();
|
||||
var y = buf.readDouble();
|
||||
var z = buf.readDouble();
|
||||
var xRot = buf.readFloat();
|
||||
var yRot = buf.readFloat();
|
||||
var yHeadRot = buf.readFloat();
|
||||
var deltaX = buf.readDouble();
|
||||
var deltaY = buf.readDouble();
|
||||
var deltaZ = buf.readDouble();
|
||||
context.queue(() -> {
|
||||
var entityType = Registry.ENTITY_TYPE.byId(entityTypeId);
|
||||
if (entityType == null) {
|
||||
throw new IllegalStateException("Entity type (" + entityTypeId + ") is unknown, spawning at (" + x + ", " + y + ", " + z + ")");
|
||||
}
|
||||
if (Minecraft.getInstance().level == null) {
|
||||
throw new IllegalStateException("Client world is null!");
|
||||
}
|
||||
var entity = entityType.create(Minecraft.getInstance().level);
|
||||
if (entity == null) {
|
||||
throw new IllegalStateException("Created entity is null!");
|
||||
}
|
||||
entity.setUUID(uuid);
|
||||
entity.setId(id);
|
||||
entity.setPacketCoordinates(x, y, z);
|
||||
entity.absMoveTo(x, y, z, xRot, yRot);
|
||||
entity.setYHeadRot(yHeadRot);
|
||||
entity.setYBodyRot(yHeadRot);
|
||||
Minecraft.getInstance().level.putNonPlayerEntity(id, entity);
|
||||
entity.lerpMotion(deltaX, deltaY, deltaZ);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 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.fabric;
|
||||
|
||||
import dev.architectury.platform.Mod;
|
||||
import dev.architectury.utils.Env;
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.loader.api.FabricLoader;
|
||||
import net.fabricmc.loader.api.ModContainer;
|
||||
import net.fabricmc.loader.api.metadata.ModMetadata;
|
||||
import net.fabricmc.loader.api.metadata.Person;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
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() {
|
||||
return FabricLoader.getInstance().getGameDir();
|
||||
}
|
||||
|
||||
public static Path getConfigFolder() {
|
||||
return FabricLoader.getInstance().getConfigDir();
|
||||
}
|
||||
|
||||
public static Path getModsFolder() {
|
||||
return getGameFolder().resolve("mods");
|
||||
}
|
||||
|
||||
public static Env getEnvironment() {
|
||||
return Env.fromPlatform(getEnv());
|
||||
}
|
||||
|
||||
public static EnvType getEnv() {
|
||||
return FabricLoader.getInstance().getEnvironmentType();
|
||||
}
|
||||
|
||||
public static boolean isModLoaded(String id) {
|
||||
return FabricLoader.getInstance().isModLoaded(id);
|
||||
}
|
||||
|
||||
public static Mod getMod(String id) {
|
||||
return mods.computeIfAbsent(id, ModImpl::new);
|
||||
}
|
||||
|
||||
public static Collection<Mod> getMods() {
|
||||
for (var mod : FabricLoader.getInstance().getAllMods()) {
|
||||
getMod(mod.getMetadata().getId());
|
||||
}
|
||||
return mods.values();
|
||||
}
|
||||
|
||||
public static Collection<String> getModIds() {
|
||||
return FabricLoader.getInstance().getAllMods().stream().map(ModContainer::getMetadata).map(ModMetadata::getId).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public static boolean isDevelopmentEnvironment() {
|
||||
return FabricLoader.getInstance().isDevelopmentEnvironment();
|
||||
}
|
||||
|
||||
private static class ModImpl implements Mod {
|
||||
private final ModContainer container;
|
||||
private final ModMetadata metadata;
|
||||
|
||||
public ModImpl(String id) {
|
||||
this.container = FabricLoader.getInstance().getModContainer(id).get();
|
||||
this.metadata = this.container.getMetadata();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getModId() {
|
||||
return metadata.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getVersion() {
|
||||
return metadata.getVersion().getFriendlyString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getName() {
|
||||
return metadata.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getDescription() {
|
||||
return metadata.getDescription();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Optional<String> getLogoFile(int preferredSize) {
|
||||
return metadata.getIconPath(preferredSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Path getFilePath() {
|
||||
return container.getRootPath();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Collection<String> getAuthors() {
|
||||
return metadata.getAuthors().stream()
|
||||
.map(Person::getName)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Collection<String> getLicense() {
|
||||
return metadata.getLicense();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Optional<String> getHomepage() {
|
||||
return metadata.getContact().get("homepage");
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Optional<String> getSources() {
|
||||
return metadata.getContact().get("issues");
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 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.plugin.fabric;
|
||||
|
||||
import net.fabricmc.loader.api.FabricLoader;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin;
|
||||
import org.spongepowered.asm.mixin.extensibility.IMixinInfo;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class ArchitecturyMixinPlugin implements IMixinConfigPlugin {
|
||||
@Override
|
||||
public void onLoad(String mixinPackage) {
|
||||
// noop
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRefMapperConfig() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldApplyMixin(String targetClassName, String mixinClassName) {
|
||||
if ("me.shedaniel.architectury.mixin.fabric.client.MixinEffectInstance".equals(mixinClassName)) {
|
||||
return !FabricLoader.getInstance().isModLoaded("satin");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptTargets(Set<String> myTargets, Set<String> otherTargets) {
|
||||
// noop
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getMixins() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) {
|
||||
// noop
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) {
|
||||
// noop
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 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.block.fabric;
|
||||
|
||||
import dev.architectury.registry.block.BlockProperties;
|
||||
import dev.architectury.registry.block.ToolType;
|
||||
import net.fabricmc.fabric.impl.object.builder.BlockSettingsInternals;
|
||||
import net.fabricmc.fabric.impl.object.builder.FabricBlockInternals;
|
||||
import net.minecraft.world.level.block.state.BlockBehaviour;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.material.Material;
|
||||
import net.minecraft.world.level.material.MaterialColor;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
public class BlockPropertiesImpl {
|
||||
public static BlockProperties of(Material material, MaterialColor color) {
|
||||
return new Impl(material, (state) -> color);
|
||||
}
|
||||
|
||||
public static BlockProperties of(Material material, Function<BlockState, MaterialColor> color) {
|
||||
return new Impl(material, color);
|
||||
}
|
||||
|
||||
public static BlockProperties copy(BlockBehaviour old) {
|
||||
return copy(old.properties);
|
||||
}
|
||||
|
||||
public static BlockProperties copy(BlockBehaviour.Properties old) {
|
||||
var properties = of(old.material, old.materialColor);
|
||||
properties.material = old.material;
|
||||
properties.destroyTime = old.destroyTime;
|
||||
properties.explosionResistance = old.explosionResistance;
|
||||
properties.hasCollision = old.hasCollision;
|
||||
properties.isRandomlyTicking = old.isRandomlyTicking;
|
||||
properties.lightEmission = old.lightEmission;
|
||||
properties.materialColor = old.materialColor;
|
||||
properties.soundType = old.soundType;
|
||||
properties.friction = old.friction;
|
||||
properties.speedFactor = old.speedFactor;
|
||||
properties.dynamicShape = old.dynamicShape;
|
||||
properties.canOcclude = old.canOcclude;
|
||||
properties.isAir = old.isAir;
|
||||
properties.requiresCorrectToolForDrops = old.requiresCorrectToolForDrops;
|
||||
var otherInternals = (BlockSettingsInternals) old;
|
||||
var extraData = otherInternals.getExtraData();
|
||||
if (extraData != null) {
|
||||
((BlockSettingsInternals) properties).setExtraData(extraData);
|
||||
}
|
||||
return properties;
|
||||
}
|
||||
|
||||
private static final class Impl extends BlockProperties {
|
||||
public Impl(Material material, Function<BlockState, MaterialColor> function) {
|
||||
super(material, function);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockProperties tool(ToolType type, int level) {
|
||||
FabricBlockInternals.computeExtraData(this).addMiningLevel(type.fabricTag.get(), level);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 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.block.fabric;
|
||||
|
||||
import net.fabricmc.fabric.api.tool.attribute.v1.FabricToolTags;
|
||||
import net.minecraft.tags.Tag;
|
||||
import net.minecraft.world.item.Item;
|
||||
|
||||
public class ToolTypeImpl {
|
||||
public static Tag<Item> pickaxeTag() {
|
||||
return FabricToolTags.PICKAXES;
|
||||
}
|
||||
|
||||
public static Tag<Item> axeTag() {
|
||||
return FabricToolTags.AXES;
|
||||
}
|
||||
|
||||
public static Tag<Item> hoeTag() {
|
||||
return FabricToolTags.HOES;
|
||||
}
|
||||
|
||||
public static Tag<Item> shovelTag() {
|
||||
return FabricToolTags.SHOVELS;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 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.keymappings.fabric;
|
||||
|
||||
import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper;
|
||||
import net.minecraft.client.KeyMapping;
|
||||
|
||||
public class KeyMappingRegistryImpl {
|
||||
public static void register(KeyMapping mapping) {
|
||||
KeyBindingHelper.registerKeyBinding(mapping);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 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.rendering.fabric;
|
||||
|
||||
import net.fabricmc.fabric.api.client.rendereregistry.v1.BlockEntityRendererRegistry;
|
||||
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider;
|
||||
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) {
|
||||
BlockEntityRendererRegistry.INSTANCE.register(type, provider);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 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.rendering.fabric;
|
||||
|
||||
import net.fabricmc.fabric.api.client.rendering.v1.ColorProviderRegistry;
|
||||
import net.minecraft.client.color.block.BlockColor;
|
||||
import net.minecraft.client.color.item.ItemColor;
|
||||
import net.minecraft.world.level.ItemLike;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class ColorHandlerRegistryImpl {
|
||||
@SafeVarargs
|
||||
public static void registerItemColors(ItemColor itemColor, Supplier<ItemLike>... items) {
|
||||
Objects.requireNonNull(itemColor, "color is null!");
|
||||
ColorProviderRegistry.ITEM.register(itemColor, unpackItems(items));
|
||||
}
|
||||
|
||||
@SafeVarargs
|
||||
public static void registerBlockColors(BlockColor blockColor, Supplier<Block>... blocks) {
|
||||
Objects.requireNonNull(blockColor, "color is null!");
|
||||
ColorProviderRegistry.BLOCK.register(blockColor, unpackBlocks(blocks));
|
||||
}
|
||||
|
||||
private static ItemLike[] unpackItems(Supplier<ItemLike>[] items) {
|
||||
var array = new ItemLike[items.length];
|
||||
for (var i = 0; i < items.length; i++) {
|
||||
array[i] = Objects.requireNonNull(items[i].get());
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
private static Block[] unpackBlocks(Supplier<Block>[] blocks) {
|
||||
var array = new Block[blocks.length];
|
||||
for (var i = 0; i < blocks.length; i++) {
|
||||
array[i] = Objects.requireNonNull(blocks[i].get());
|
||||
}
|
||||
return array;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 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.rendering.fabric;
|
||||
|
||||
import net.fabricmc.fabric.api.blockrenderlayer.v1.BlockRenderLayerMap;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.material.Fluid;
|
||||
|
||||
public class RenderTypeRegistryImpl {
|
||||
public static void register(RenderType type, Block... blocks) {
|
||||
BlockRenderLayerMap.INSTANCE.putBlocks(type, blocks);
|
||||
}
|
||||
|
||||
public static void register(RenderType type, Fluid... fluids) {
|
||||
BlockRenderLayerMap.INSTANCE.putFluids(type, fluids);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 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.fabric;
|
||||
|
||||
import net.fabricmc.fabric.api.client.itemgroup.FabricItemGroupBuilder;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.CreativeModeTab;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class CreativeTabRegistryImpl {
|
||||
public static CreativeModeTab create(ResourceLocation name, Supplier<ItemStack> icon) {
|
||||
return FabricItemGroupBuilder.build(name, icon);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 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.fabric;
|
||||
|
||||
import com.google.common.primitives.Longs;
|
||||
import net.fabricmc.fabric.api.resource.IdentifiableResourceReloadListener;
|
||||
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 java.security.SecureRandom;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
public class ReloadListenerRegistryImpl {
|
||||
private static final SecureRandom RANDOM = new SecureRandom();
|
||||
|
||||
public static void register(PackType type, PreparableReloadListener listener) {
|
||||
var bytes = new byte[8];
|
||||
RANDOM.nextBytes(bytes);
|
||||
var id = new ResourceLocation("architectury:reload_" + StringUtils.leftPad(Math.abs(Longs.fromByteArray(bytes)) + "", 19, '0'));
|
||||
ResourceManagerHelper.get(type).registerReloadListener(new IdentifiableResourceReloadListener() {
|
||||
@Override
|
||||
public ResourceLocation getFabricId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return listener.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> reload(PreparationBarrier preparationBarrier, ResourceManager resourceManager, ProfilerFiller profilerFiller, ProfilerFiller profilerFiller2, Executor executor, Executor executor2) {
|
||||
return listener.reload(preparationBarrier, resourceManager, profilerFiller, profilerFiller2, executor, executor2);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 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.fuel.fabric;
|
||||
|
||||
import net.fabricmc.fabric.api.registry.FuelRegistry;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.ItemLike;
|
||||
|
||||
public class FuelRegistryImpl {
|
||||
public static void register(int time, ItemLike... items) {
|
||||
for (var item : items) {
|
||||
if (time >= 0) {
|
||||
FuelRegistry.INSTANCE.add(item, time);
|
||||
} else {
|
||||
FuelRegistry.INSTANCE.remove(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static int get(ItemStack stack) {
|
||||
var time = FuelRegistry.INSTANCE.get(stack.getItem());
|
||||
return time == null ? 0 : time;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 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.level.advancement.fabric;
|
||||
|
||||
import net.minecraft.advancements.CriteriaTriggers;
|
||||
import net.minecraft.advancements.CriterionTrigger;
|
||||
|
||||
public class CriteriaTriggersRegistryImpl {
|
||||
public static <T extends CriterionTrigger<?>> T register(T trigger) {
|
||||
return CriteriaTriggers.register(trigger);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,370 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 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.level.biome.fabric;
|
||||
|
||||
import com.google.common.base.Predicates;
|
||||
import com.google.common.collect.Lists;
|
||||
import dev.architectury.hooks.level.biome.*;
|
||||
import dev.architectury.registry.level.biome.BiomeModifications.BiomeContext;
|
||||
import net.fabricmc.fabric.api.biome.v1.BiomeModification;
|
||||
import net.fabricmc.fabric.api.biome.v1.BiomeModificationContext;
|
||||
import net.fabricmc.fabric.api.biome.v1.BiomeModificationContext.GenerationSettingsContext;
|
||||
import net.fabricmc.fabric.api.biome.v1.BiomeModificationContext.SpawnSettingsContext;
|
||||
import net.fabricmc.fabric.api.biome.v1.BiomeSelectionContext;
|
||||
import net.fabricmc.fabric.api.biome.v1.ModificationPhase;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.sounds.Music;
|
||||
import net.minecraft.sounds.SoundEvent;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.entity.MobCategory;
|
||||
import net.minecraft.world.level.biome.*;
|
||||
import net.minecraft.world.level.biome.Biome.BiomeCategory;
|
||||
import net.minecraft.world.level.biome.Biome.Precipitation;
|
||||
import net.minecraft.world.level.biome.Biome.TemperatureModifier;
|
||||
import net.minecraft.world.level.biome.BiomeSpecialEffects.GrassColorModifier;
|
||||
import net.minecraft.world.level.levelgen.GenerationStep;
|
||||
import net.minecraft.world.level.levelgen.carver.ConfiguredWorldCarver;
|
||||
import net.minecraft.world.level.levelgen.feature.ConfiguredFeature;
|
||||
import net.minecraft.world.level.levelgen.feature.ConfiguredStructureFeature;
|
||||
import net.minecraft.world.level.levelgen.surfacebuilders.ConfiguredSurfaceBuilder;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.BiPredicate;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public class BiomeModificationsImpl {
|
||||
private static final ResourceLocation FABRIC_MODIFICATION = new ResourceLocation("architectury", "fabric_modification");
|
||||
private static final List<Pair<Predicate<BiomeContext>, BiConsumer<BiomeContext, BiomeProperties.Mutable>>> ADDITIONS = Lists.newArrayList();
|
||||
private static final List<Pair<Predicate<BiomeContext>, BiConsumer<BiomeContext, BiomeProperties.Mutable>>> POST_PROCESSING = Lists.newArrayList();
|
||||
private static final List<Pair<Predicate<BiomeContext>, BiConsumer<BiomeContext, BiomeProperties.Mutable>>> REMOVALS = Lists.newArrayList();
|
||||
private static final List<Pair<Predicate<BiomeContext>, BiConsumer<BiomeContext, BiomeProperties.Mutable>>> REPLACEMENTS = Lists.newArrayList();
|
||||
|
||||
public static void addProperties(Predicate<BiomeContext> predicate, BiConsumer<BiomeContext, BiomeProperties.Mutable> modifier) {
|
||||
ADDITIONS.add(Pair.of(predicate, modifier));
|
||||
}
|
||||
|
||||
public static void postProcessProperties(Predicate<BiomeContext> predicate, BiConsumer<BiomeContext, BiomeProperties.Mutable> modifier) {
|
||||
ADDITIONS.add(Pair.of(predicate, modifier));
|
||||
}
|
||||
|
||||
public static void removeProperties(Predicate<BiomeContext> predicate, BiConsumer<BiomeContext, BiomeProperties.Mutable> modifier) {
|
||||
ADDITIONS.add(Pair.of(predicate, modifier));
|
||||
}
|
||||
|
||||
public static void replaceProperties(Predicate<BiomeContext> predicate, BiConsumer<BiomeContext, BiomeProperties.Mutable> modifier) {
|
||||
ADDITIONS.add(Pair.of(predicate, modifier));
|
||||
}
|
||||
|
||||
static {
|
||||
var modification = net.fabricmc.fabric.api.biome.v1.BiomeModifications.create(FABRIC_MODIFICATION);
|
||||
registerModification(modification, ModificationPhase.ADDITIONS, ADDITIONS);
|
||||
registerModification(modification, ModificationPhase.POST_PROCESSING, POST_PROCESSING);
|
||||
registerModification(modification, ModificationPhase.REMOVALS, REMOVALS);
|
||||
registerModification(modification, ModificationPhase.REPLACEMENTS, REPLACEMENTS);
|
||||
}
|
||||
|
||||
private static void registerModification(BiomeModification modification, ModificationPhase phase, List<Pair<Predicate<BiomeContext>, BiConsumer<BiomeContext, BiomeProperties.Mutable>>> list) {
|
||||
modification.add(phase, Predicates.alwaysTrue(), (biomeSelectionContext, biomeModificationContext) -> {
|
||||
var biomeContext = wrapSelectionContext(biomeSelectionContext);
|
||||
var mutableBiome = wrapMutableBiome(biomeSelectionContext.getBiome(), biomeModificationContext);
|
||||
for (var pair : list) {
|
||||
if (pair.getLeft().test(biomeContext)) {
|
||||
pair.getRight().accept(biomeContext, mutableBiome);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static BiomeContext wrapSelectionContext(BiomeSelectionContext context) {
|
||||
return new BiomeContext() {
|
||||
BiomeProperties properties = BiomeHooks.getBiomeProperties(context.getBiome());
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public ResourceLocation getKey() {
|
||||
return context.getBiomeKey().location();
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public BiomeProperties getProperties() {
|
||||
return properties;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static BiomeProperties.Mutable wrapMutableBiome(Biome biome, BiomeModificationContext context) {
|
||||
return new BiomeHooks.MutableBiomeWrapped(
|
||||
biome,
|
||||
wrapWeather(biome, context.getWeather()),
|
||||
wrapEffects(biome, context.getEffects()),
|
||||
new MutableGenerationProperties(biome, context.getGenerationSettings()),
|
||||
new MutableSpawnProperties(biome, context.getSpawnSettings())
|
||||
) {
|
||||
@Override
|
||||
@NotNull
|
||||
public BiomeProperties.Mutable setCategory(@NotNull BiomeCategory category) {
|
||||
context.setCategory(category);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public BiomeProperties.Mutable setDepth(float depth) {
|
||||
context.setDepth(depth);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public BiomeProperties.Mutable setScale(float scale) {
|
||||
context.setScale(scale);
|
||||
return this;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static class MutableGenerationProperties extends BiomeHooks.GenerationSettingsWrapped implements GenerationProperties.Mutable {
|
||||
protected final GenerationSettingsContext context;
|
||||
|
||||
public MutableGenerationProperties(Biome biome, GenerationSettingsContext context) {
|
||||
super(biome);
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mutable setSurfaceBuilder(ConfiguredSurfaceBuilder<?> builder) {
|
||||
this.context.setBuiltInSurfaceBuilder(builder);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mutable addFeature(GenerationStep.Decoration decoration, ConfiguredFeature<?, ?> feature) {
|
||||
this.context.addBuiltInFeature(decoration, feature);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mutable addCarver(GenerationStep.Carving carving, ConfiguredWorldCarver<?> feature) {
|
||||
context.addBuiltInCarver(carving, feature);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mutable addStructure(ConfiguredStructureFeature<?, ?> feature) {
|
||||
context.addBuiltInStructure(feature);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mutable removeFeature(GenerationStep.Decoration decoration, ConfiguredFeature<?, ?> feature) {
|
||||
context.removeBuiltInFeature(decoration, feature);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mutable removeCarver(GenerationStep.Carving carving, ConfiguredWorldCarver<?> feature) {
|
||||
context.removeBuiltInCarver(carving, feature);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mutable removeStructure(ConfiguredStructureFeature<?, ?> feature) {
|
||||
context.removeBuiltInStructure(feature);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
private static class MutableSpawnProperties extends BiomeHooks.SpawnSettingsWrapped implements SpawnProperties.Mutable {
|
||||
protected final SpawnSettingsContext context;
|
||||
|
||||
public MutableSpawnProperties(Biome biome, SpawnSettingsContext context) {
|
||||
super(biome);
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Mutable setCreatureProbability(float probability) {
|
||||
context.setCreatureSpawnProbability(probability);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mutable addSpawn(MobCategory category, MobSpawnSettings.SpawnerData data) {
|
||||
context.addSpawn(category, data);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeSpawns(BiPredicate<MobCategory, MobSpawnSettings.SpawnerData> predicate) {
|
||||
return context.removeSpawns(predicate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mutable setSpawnCost(EntityType<?> entityType, MobSpawnSettings.MobSpawnCost cost) {
|
||||
context.setSpawnCost(entityType, cost.getCharge(), cost.getEnergyBudget());
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mutable setSpawnCost(EntityType<?> entityType, double mass, double gravityLimit) {
|
||||
context.setSpawnCost(entityType, mass, gravityLimit);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mutable clearSpawnCost(EntityType<?> entityType) {
|
||||
context.clearSpawnCost(entityType);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Mutable setPlayerSpawnFriendly(boolean friendly) {
|
||||
context.setPlayerSpawnFriendly(friendly);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
private static ClimateProperties.Mutable wrapWeather(Biome biome, BiomeModificationContext.WeatherContext context) {
|
||||
return new BiomeHooks.ClimateWrapped(biome) {
|
||||
@Override
|
||||
@NotNull
|
||||
public ClimateProperties.Mutable setPrecipitation(@NotNull Precipitation precipitation) {
|
||||
context.setPrecipitation(precipitation);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public ClimateProperties.Mutable setTemperature(float temperature) {
|
||||
context.setTemperature(temperature);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public ClimateProperties.Mutable setTemperatureModifier(@NotNull TemperatureModifier temperatureModifier) {
|
||||
context.setTemperatureModifier(temperatureModifier);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public ClimateProperties.Mutable setDownfall(float downfall) {
|
||||
context.setDownfall(downfall);
|
||||
return this;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static EffectsProperties.Mutable wrapEffects(Biome biome, BiomeModificationContext.EffectsContext context) {
|
||||
return new BiomeHooks.EffectsWrapped(biome) {
|
||||
@Override
|
||||
@NotNull
|
||||
public EffectsProperties.Mutable setFogColor(int color) {
|
||||
context.setFogColor(color);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public EffectsProperties.Mutable setWaterColor(int color) {
|
||||
context.setWaterColor(color);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public EffectsProperties.Mutable setWaterFogColor(int color) {
|
||||
context.setWaterFogColor(color);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public EffectsProperties.Mutable setSkyColor(int color) {
|
||||
context.setSkyColor(color);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public EffectsProperties.Mutable setFoliageColorOverride(@Nullable Integer colorOverride) {
|
||||
context.setFoliageColor(Optional.ofNullable(colorOverride));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public EffectsProperties.Mutable setGrassColorOverride(@Nullable Integer colorOverride) {
|
||||
context.setGrassColor(Optional.ofNullable(colorOverride));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public EffectsProperties.Mutable setGrassColorModifier(@NotNull GrassColorModifier modifier) {
|
||||
context.setGrassColorModifier(modifier);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public EffectsProperties.Mutable setAmbientParticle(@Nullable AmbientParticleSettings settings) {
|
||||
context.setParticleConfig(Optional.ofNullable(settings));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public EffectsProperties.Mutable setAmbientLoopSound(@Nullable SoundEvent sound) {
|
||||
context.setAmbientSound(Optional.ofNullable(sound));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public EffectsProperties.Mutable setAmbientMoodSound(@Nullable AmbientMoodSettings settings) {
|
||||
context.setMoodSound(Optional.ofNullable(settings));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public EffectsProperties.Mutable setAmbientAdditionsSound(@Nullable AmbientAdditionsSettings settings) {
|
||||
context.setAdditionsSound(Optional.ofNullable(settings));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public EffectsProperties.Mutable setBackgroundMusic(@Nullable Music music) {
|
||||
context.setMusic(Optional.ofNullable(music));
|
||||
return this;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 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.level.entity.fabric;
|
||||
|
||||
import net.fabricmc.fabric.api.object.builder.v1.entity.FabricDefaultAttributeRegistry;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.ai.attributes.AttributeSupplier;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class EntityAttributeRegistryImpl {
|
||||
public static void register(Supplier<EntityType<? extends LivingEntity>> type, Supplier<AttributeSupplier.Builder> attribute) {
|
||||
FabricDefaultAttributeRegistry.register(type.get(), attribute.get());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 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.level.entity.fabric;
|
||||
|
||||
import net.fabricmc.fabric.api.client.rendereregistry.v1.EntityRendererRegistry;
|
||||
import net.minecraft.client.renderer.entity.EntityRendererProvider;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
|
||||
public class EntityRendererRegistryImpl {
|
||||
public static <T extends Entity> void register(EntityType<? extends T> type, EntityRendererProvider<T> provider) {
|
||||
EntityRendererRegistry.INSTANCE.register(type, provider);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 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.level.entity.trade.fabric;
|
||||
|
||||
import net.fabricmc.fabric.api.object.builder.v1.trade.TradeOfferHelper;
|
||||
import net.minecraft.world.entity.npc.VillagerProfession;
|
||||
import net.minecraft.world.entity.npc.VillagerTrades;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
public class TradeRegistryImpl {
|
||||
public static void registerVillagerTrade0(VillagerProfession profession, int level, VillagerTrades.ItemListing... trades) {
|
||||
TradeOfferHelper.registerVillagerOffers(profession, level, allTradesList -> Collections.addAll(allTradesList, trades));
|
||||
}
|
||||
|
||||
public static void registerTradeForWanderingTrader(boolean rare, VillagerTrades.ItemListing... trades) {
|
||||
TradeOfferHelper.registerWanderingTraderOffers(rare ? 2 : 1, allTradesList -> Collections.addAll(allTradesList, trades));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 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.level.fabric;
|
||||
|
||||
import net.fabricmc.fabric.api.gamerule.v1.GameRuleFactory;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.world.level.GameRules;
|
||||
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
public class GameRuleFactoryImpl {
|
||||
public static GameRules.Type<GameRules.BooleanValue> createBooleanRule(boolean defaultValue) {
|
||||
return GameRuleFactory.createBooleanRule(defaultValue);
|
||||
}
|
||||
|
||||
public static GameRules.Type<GameRules.BooleanValue> createBooleanRule(boolean defaultValue, BiConsumer<MinecraftServer, GameRules.BooleanValue> changedCallback) {
|
||||
return GameRuleFactory.createBooleanRule(defaultValue, changedCallback);
|
||||
}
|
||||
|
||||
public static GameRules.Type<GameRules.IntegerValue> createIntRule(int defaultValue) {
|
||||
return GameRuleFactory.createIntRule(defaultValue);
|
||||
}
|
||||
|
||||
public static GameRules.Type<GameRules.IntegerValue> createIntRule(int defaultValue, BiConsumer<MinecraftServer, GameRules.IntegerValue> changedCallback) {
|
||||
return GameRuleFactory.createIntRule(defaultValue, changedCallback);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 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.level.fabric;
|
||||
|
||||
import net.fabricmc.fabric.api.gamerule.v1.GameRuleRegistry;
|
||||
import net.minecraft.world.level.GameRules;
|
||||
|
||||
public class GameRuleRegistryImpl {
|
||||
public static <T extends GameRules.Value<T>> GameRules.Key<T> register(String name, GameRules.Category category, GameRules.Type<T> type) {
|
||||
return GameRuleRegistry.register(name, category, type);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 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.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 net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
import net.fabricmc.fabric.api.client.screenhandler.v1.ScreenRegistry;
|
||||
import net.fabricmc.fabric.api.screenhandler.v1.ExtendedScreenHandlerFactory;
|
||||
import net.fabricmc.fabric.impl.screenhandler.ExtendedScreenHandlerType;
|
||||
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;
|
||||
import net.minecraft.world.entity.player.Inventory;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu;
|
||||
import net.minecraft.world.inventory.MenuType;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class MenuRegistryImpl {
|
||||
public static void openExtendedMenu(ServerPlayer player, ExtendedMenuProvider provider) {
|
||||
player.openMenu(new ExtendedScreenHandlerFactory() {
|
||||
@Override
|
||||
public void writeScreenOpeningData(ServerPlayer player, FriendlyByteBuf buf) {
|
||||
provider.saveExtraData(buf);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getDisplayName() {
|
||||
return provider.getDisplayName();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public AbstractContainerMenu createMenu(int i, Inventory inventory, Player player) {
|
||||
return provider.createMenu(i, inventory, player);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static <T extends AbstractContainerMenu> MenuType<T> of(SimpleMenuTypeFactory<T> factory) {
|
||||
return new MenuType<>(factory::create);
|
||||
}
|
||||
|
||||
public static <T extends AbstractContainerMenu> MenuType<T> ofExtended(ExtendedMenuTypeFactory<T> factory) {
|
||||
return new ExtendedScreenHandlerType<>(factory::create);
|
||||
}
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public static <H extends AbstractContainerMenu, S extends Screen & MenuAccess<H>> void registerScreenFactory(MenuType<? extends H> type, ScreenFactory<H, S> factory) {
|
||||
ScreenRegistry.register(type, factory::create);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,218 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 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.registries.fabric;
|
||||
|
||||
import com.google.common.base.Objects;
|
||||
import com.google.common.base.Suppliers;
|
||||
import dev.architectury.registry.registries.Registrar;
|
||||
import dev.architectury.registry.registries.RegistrarBuilder;
|
||||
import dev.architectury.registry.registries.Registries;
|
||||
import dev.architectury.registry.registries.RegistrySupplier;
|
||||
import dev.architectury.registry.registries.options.RegistrarOption;
|
||||
import dev.architectury.registry.registries.options.StandardRegistrarOption;
|
||||
import net.fabricmc.fabric.api.event.registry.FabricRegistryBuilder;
|
||||
import net.fabricmc.fabric.api.event.registry.RegistryAttribute;
|
||||
import net.minecraft.core.MappedRegistry;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class RegistriesImpl {
|
||||
public static Registries.RegistryProvider _get(String modId) {
|
||||
return RegistryProviderImpl.INSTANCE;
|
||||
}
|
||||
|
||||
public static <T> ResourceLocation getId(T object, ResourceKey<Registry<T>> fallback) {
|
||||
if (fallback == null)
|
||||
return null;
|
||||
return RegistryProviderImpl.INSTANCE.get(fallback).getId(object);
|
||||
}
|
||||
|
||||
public static <T> ResourceLocation getId(T object, Registry<T> fallback) {
|
||||
if (fallback == null)
|
||||
return null;
|
||||
return RegistryProviderImpl.INSTANCE.get(fallback).getId(object);
|
||||
}
|
||||
|
||||
public enum RegistryProviderImpl implements Registries.RegistryProvider {
|
||||
INSTANCE;
|
||||
|
||||
@Override
|
||||
public <T> Registrar<T> get(ResourceKey<Registry<T>> key) {
|
||||
return new RegistrarImpl<>((Registry<T>) Registry.REGISTRY.get(key.location()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> Registrar<T> get(Registry<T> registry) {
|
||||
return new RegistrarImpl<>(registry);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public <T> RegistrarBuilder<T> builder(Class<T> type, ResourceLocation registryId) {
|
||||
return new RegistrarBuilderWrapper<>(FabricRegistryBuilder.createSimple(type, registryId));
|
||||
}
|
||||
}
|
||||
|
||||
public static class RegistrarBuilderWrapper<T> implements RegistrarBuilder<T> {
|
||||
@NotNull
|
||||
private FabricRegistryBuilder<T, MappedRegistry<T>> builder;
|
||||
|
||||
public RegistrarBuilderWrapper(@NotNull FabricRegistryBuilder<T, MappedRegistry<T>> builder) {
|
||||
this.builder = builder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Registrar<T> build() {
|
||||
return RegistryProviderImpl.INSTANCE.get(builder.buildAndRegister());
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull RegistrarBuilder<T> option(@NotNull RegistrarOption option) {
|
||||
if (option == StandardRegistrarOption.SAVE_TO_DISC) {
|
||||
this.builder.attribute(RegistryAttribute.PERSISTED);
|
||||
} else if (option == StandardRegistrarOption.SYNC_TO_CLIENTS) {
|
||||
this.builder.attribute(RegistryAttribute.SYNCED);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
public static class RegistrarImpl<T> implements Registrar<T> {
|
||||
private Registry<T> delegate;
|
||||
|
||||
public RegistrarImpl(Registry<T> delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull RegistrySupplier<T> delegate(ResourceLocation id) {
|
||||
Supplier<T> value = Suppliers.memoize(() -> get(id));
|
||||
return new RegistrySupplier<>() {
|
||||
@Override
|
||||
public @NotNull ResourceLocation getRegistryId() {
|
||||
return delegate.key().location();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ResourceLocation getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPresent() {
|
||||
return contains(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T get() {
|
||||
return value.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(getRegistryId(), getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) return true;
|
||||
if (!(obj instanceof RegistrySupplier<?> other)) return false;
|
||||
return other.getRegistryId().equals(getRegistryId()) && other.getId().equals(getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getRegistryId().toString() + "@" + id.toString();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull <E extends T> RegistrySupplier<E> register(ResourceLocation id, Supplier<E> supplier) {
|
||||
Registry.register(delegate, id, supplier.get());
|
||||
return (RegistrySupplier<E>) delegate(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable ResourceLocation getId(T obj) {
|
||||
return delegate.getKey(obj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRawId(T obj) {
|
||||
return delegate.getId(obj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<ResourceKey<T>> getKey(T obj) {
|
||||
return delegate.getResourceKey(obj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable T get(ResourceLocation id) {
|
||||
return delegate.get(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T byRawId(int rawId) {
|
||||
return delegate.byId(rawId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(ResourceLocation id) {
|
||||
return delegate.keySet().contains(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsValue(T obj) {
|
||||
return delegate.getResourceKey(obj).isPresent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<ResourceLocation> getIds() {
|
||||
return delegate.keySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Map.Entry<ResourceKey<T>, T>> entrySet() {
|
||||
return delegate.entrySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceKey<? extends Registry<T>> key() {
|
||||
return delegate.key();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Iterator<T> iterator() {
|
||||
return delegate.iterator();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 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.utils.fabric;
|
||||
|
||||
import dev.architectury.event.EventHandler;
|
||||
import dev.architectury.event.events.common.LifecycleEvent;
|
||||
import dev.architectury.platform.Platform;
|
||||
import dev.architectury.utils.Env;
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
|
||||
public class GameInstanceImpl {
|
||||
private static MinecraftServer server = null;
|
||||
|
||||
public static MinecraftServer getServer() {
|
||||
MinecraftServer server = null;
|
||||
if (GameInstanceImpl.server != null) server = GameInstanceImpl.server;
|
||||
if (Platform.getEnvironment() == Env.CLIENT) {
|
||||
server = getServerFromClient();
|
||||
}
|
||||
return server;
|
||||
}
|
||||
|
||||
public static void init() {
|
||||
EventHandler.init();
|
||||
LifecycleEvent.SERVER_BEFORE_START.register(server -> GameInstanceImpl.server = server);
|
||||
LifecycleEvent.SERVER_STOPPED.register(server -> GameInstanceImpl.server = null);
|
||||
}
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
private static MinecraftServer getServerFromClient() {
|
||||
return Minecraft.getInstance().getSingleplayerServer();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user