Merge remote-tracking branch 'architectury/1.16' into 1.17

# Conflicts:
#	fabric/src/main/resources/architectury.mixins.json
#	gradle.properties
#	settings.gradle
This commit is contained in:
shedaniel
2021-02-11 21:35:32 +08:00
111 changed files with 2971 additions and 404 deletions

View File

@@ -4,12 +4,16 @@ plugins {
}
loom {
silentMojangMappingsLicense()
mixinConfig = "architectury.mixins.json"
}
configurations {
shadow
dev
}
artifacts {
dev(jar)
}
architectury {
@@ -17,19 +21,19 @@ architectury {
}
dependencies {
minecraft("com.mojang:minecraft:${rootProject.architect.minecraft}")
mappings(minecraft.officialMojangMappings())
forge("net.minecraftforge:forge:${rootProject.architect.minecraft}-${rootProject.forge_version}")
minecraft "com.mojang:minecraft:${rootProject.architectury.minecraft}"
mappings loom.officialMojangMappings()
forge "net.minecraftforge:forge:${rootProject.architectury.minecraft}-${rootProject.forge_version}"
implementation "net.jodah:typetools:0.6.2"
shadow "net.jodah:typetools:0.6.2"
compileOnly(project(path: ":common")) {
transitive = false
}
runtimeOnly(project(path: ":common", configuration: "transformForgeFakeMod")) {
runtimeOnly(project(path: ":common", configuration: "transformDevelopmentForge")) {
transitive = false
}
shadow(project(path: ":common", configuration: "transformForge")) {
shadow(project(path: ":common", configuration: "transformProductionForge")) {
transitive = false
}
}
@@ -65,6 +69,18 @@ publishing {
}
}
}
repositories {
if (System.getenv("MAVEN_PASS") != null) {
maven {
url = "https://deploy.shedaniel.me/"
credentials {
username = "shedaniel"
password = System.getenv("MAVEN_PASS")
}
}
}
}
}
curseforge {
@@ -76,6 +92,7 @@ curseforge {
changelogType = "html"
changelog = releaseChangelog()
addGameVersion "1.16.4"
addGameVersion "1.16.5"
addGameVersion "Java 8"
addGameVersion "Forge"
mainArtifact(remapJar.archivePath) {
@@ -92,4 +109,4 @@ curseforge {
}
}
rootProject.tasks.getByName("curseforgePublish").dependsOn tasks.getByName("curseforge")
rootProject.tasks.getByName("curseforgePublish").dependsOn tasks.getByName("curseforge")

View File

@@ -27,6 +27,7 @@ import me.shedaniel.architectury.impl.TooltipEventColorContextImpl;
import me.shedaniel.architectury.impl.TooltipEventPositionContextImpl;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.components.events.GuiEventListener;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.network.chat.Component;
import net.minecraft.world.InteractionResult;
@@ -38,6 +39,7 @@ import net.minecraftforge.event.entity.player.ItemTooltipEvent;
import net.minecraftforge.event.entity.player.PlayerInteractEvent;
import net.minecraftforge.event.world.WorldEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
import java.util.List;
@@ -123,6 +125,18 @@ public class EventHandlerImplClient {
}
}
@SubscribeEvent
public static void event(GuiOpenEvent event) {
InteractionResultHolder<Screen> result = GuiEvent.SET_SCREEN.invoker().modifyScreen(event.getGui());
switch (result.getResult()) {
case FAIL:
event.setCanceled(true);
return;
case SUCCESS:
event.setGui(result.getObject());
}
}
@SubscribeEvent
public static void event(GuiScreenEvent.DrawScreenEvent.Pre event) {
if (GuiEvent.RENDER_PRE.invoker().render(event.getGui(), event.getMatrixStack(), event.getMouseX(), event.getMouseY(), event.getRenderPartialTicks()) == InteractionResult.FAIL) {
@@ -264,6 +278,30 @@ public class EventHandlerImplClient {
ClientScreenInputEvent.KEY_RELEASED_POST.invoker().keyReleased(Minecraft.getInstance(), event.getGui(), event.getKeyCode(), event.getScanCode(), event.getModifiers());
}
@SubscribeEvent
public static void event(InputEvent.MouseScrollEvent event) {
if (ClientRawInputEvent.MOUSE_SCROLLED.invoker().mouseScrolled(Minecraft.getInstance(), event.getScrollDelta()) == InteractionResult.FAIL) {
event.setCanceled(true);
}
}
@SubscribeEvent
public static void event(InputEvent.RawMouseEvent event) {
if (ClientRawInputEvent.MOUSE_CLICKED_PRE.invoker().mouseClicked(Minecraft.getInstance(), event.getButton(), event.getAction(), event.getMods()) == InteractionResult.FAIL) {
event.setCanceled(true);
}
}
@SubscribeEvent
public static void event(InputEvent.MouseInputEvent event) {
ClientRawInputEvent.MOUSE_CLICKED_POST.invoker().mouseClicked(Minecraft.getInstance(), event.getButton(), event.getAction(), event.getMods());
}
@SubscribeEvent
public static void event(InputEvent.KeyInputEvent event) {
ClientRawInputEvent.KEY_PRESSED.invoker().keyPressed(Minecraft.getInstance(), event.getKey(), event.getScanCode(), event.getAction(), event.getModifiers());
}
@OnlyIn(Dist.CLIENT)
public static class ModBasedEventHandler {
@SubscribeEvent
@@ -275,5 +313,10 @@ public class EventHandlerImplClient {
public static void event(net.minecraftforge.client.event.TextureStitchEvent.Post event) {
TextureStitchEvent.POST.invoker().stitch(event.getMap());
}
@SubscribeEvent
public static void event(FMLClientSetupEvent event) {
ClientLifecycleEvent.CLIENT_SETUP.invoker().stateChanged(event.getMinecraftSupplier().get());
}
}
}

View File

@@ -322,6 +322,13 @@ public class EventHandlerImplCommon {
LifecycleEvent.SERVER_BEFORE_START.invoker().stateChanged(event.getServer());
}
@SubscribeEvent
public static void event(PlayerChangedDimensionEvent event) {
if (event.getPlayer() instanceof ServerPlayer) {
PlayerEvent.CHANGE_DIMENSION.invoker().change((ServerPlayer) event.getPlayer(), event.getFrom(), event.getTo());
}
}
public static class ModBasedEventHandler {
}

View File

@@ -1,49 +0,0 @@
/*
* This file is part of architectury.
* Copyright (C) 2020, 2021 shedaniel
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package me.shedaniel.architectury.event.forge;
import me.shedaniel.architectury.event.events.TextureStitchEvent;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.eventbus.api.SubscribeEvent;
public class ModBasedEventHandlerImpl {
@OnlyIn(Dist.CLIENT)
public static class Client {
@SubscribeEvent
public static void event(net.minecraftforge.client.event.TextureStitchEvent.Pre event) {
TextureStitchEvent.PRE.invoker().stitch(event.getMap(), event::addSprite);
}
@SubscribeEvent
public static void event(net.minecraftforge.client.event.TextureStitchEvent.Post event) {
TextureStitchEvent.POST.invoker().stitch(event.getMap());
}
}
public static class Common {
}
@OnlyIn(Dist.DEDICATED_SERVER)
public static class Server {
}
}

View File

@@ -0,0 +1,52 @@
/*
* This file is part of architectury.
* Copyright (C) 2020, 2021 shedaniel
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package me.shedaniel.architectury.hooks.forge;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.Level;
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) {
Level 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());
}
}
}

View File

@@ -21,9 +21,22 @@ package me.shedaniel.architectury.hooks.forge;
import me.shedaniel.architectury.fluid.FluidStack;
import me.shedaniel.architectury.utils.Fraction;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.texture.TextureAtlas;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.BlockAndTintGetter;
import net.minecraft.world.level.material.Fluid;
import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.level.material.Fluids;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class FluidStackHooksImpl {
public static Component getName(FluidStack stack) {
@@ -53,4 +66,70 @@ public class FluidStackHooksImpl {
public static Fraction bucketAmount() {
return Fraction.ofWhole(1000);
}
@OnlyIn(Dist.CLIENT)
@Nullable
public static TextureAtlasSprite getStillTexture(@Nullable BlockAndTintGetter level, @Nullable BlockPos pos, @NotNull FluidState state) {
if (state.getType() == Fluids.EMPTY) return null;
ResourceLocation texture = state.getType().getAttributes().getStillTexture(level, pos);
return Minecraft.getInstance().getTextureAtlas(TextureAtlas.LOCATION_BLOCKS).apply(texture);
}
@OnlyIn(Dist.CLIENT)
@Nullable
public static TextureAtlasSprite getStillTexture(@NotNull FluidStack stack) {
if (stack.getFluid() == Fluids.EMPTY) return null;
ResourceLocation texture = stack.getFluid().getAttributes().getStillTexture(FluidStackHooksForge.toForge(stack));
return Minecraft.getInstance().getTextureAtlas(TextureAtlas.LOCATION_BLOCKS).apply(texture);
}
@OnlyIn(Dist.CLIENT)
@Nullable
public static TextureAtlasSprite getStillTexture(@NotNull Fluid fluid) {
if (fluid == Fluids.EMPTY) return null;
ResourceLocation texture = fluid.getAttributes().getStillTexture();
return Minecraft.getInstance().getTextureAtlas(TextureAtlas.LOCATION_BLOCKS).apply(texture);
}
@OnlyIn(Dist.CLIENT)
@Nullable
public static TextureAtlasSprite getFlowingTexture(@Nullable BlockAndTintGetter level, @Nullable BlockPos pos, @NotNull FluidState state) {
if (state.getType() == Fluids.EMPTY) return null;
ResourceLocation texture = state.getType().getAttributes().getFlowingTexture(level, pos);
return Minecraft.getInstance().getTextureAtlas(TextureAtlas.LOCATION_BLOCKS).apply(texture);
}
@OnlyIn(Dist.CLIENT)
@Nullable
public static TextureAtlasSprite getFlowingTexture(@NotNull FluidStack stack) {
if (stack.getFluid() == Fluids.EMPTY) return null;
ResourceLocation texture = stack.getFluid().getAttributes().getFlowingTexture(FluidStackHooksForge.toForge(stack));
return Minecraft.getInstance().getTextureAtlas(TextureAtlas.LOCATION_BLOCKS).apply(texture);
}
@OnlyIn(Dist.CLIENT)
@Nullable
public static TextureAtlasSprite getFlowingTexture(@NotNull Fluid fluid) {
if (fluid == Fluids.EMPTY) return null;
ResourceLocation texture = fluid.getAttributes().getFlowingTexture();
return Minecraft.getInstance().getTextureAtlas(TextureAtlas.LOCATION_BLOCKS).apply(texture);
}
@OnlyIn(Dist.CLIENT)
public static int getColor(@Nullable BlockAndTintGetter level, @Nullable BlockPos pos, @NotNull FluidState state) {
if (state.getType() == Fluids.EMPTY) return -1;
return state.getType().getAttributes().getColor(level, pos);
}
@OnlyIn(Dist.CLIENT)
public static int getColor(@NotNull FluidStack stack) {
if (stack.getFluid() == Fluids.EMPTY) return -1;
return stack.getFluid().getAttributes().getColor(FluidStackHooksForge.toForge(stack));
}
@OnlyIn(Dist.CLIENT)
public static int getColor(@NotNull Fluid fluid) {
if (fluid == Fluids.EMPTY) return -1;
return fluid.getAttributes().getColor();
}
}

View File

@@ -0,0 +1,52 @@
/*
* This file is part of architectury.
* Copyright (C) 2020, 2021 shedaniel
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package me.shedaniel.architectury.mixin.forge;
import me.shedaniel.architectury.extensions.BlockEntityExtension;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket;
import net.minecraft.world.level.block.entity.BlockEntity;
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(BlockEntity.class)
public abstract class MixinBlockEntity {
@Inject(method = "getUpdatePacket", at = @At("HEAD"), cancellable = true)
public void getUpdatePacket(CallbackInfoReturnable<ClientboundBlockEntityDataPacket> cir) {
if (this instanceof BlockEntityExtension) {
BlockEntityExtension entity = (BlockEntityExtension) this;
BlockEntity be = (BlockEntity) entity;
cir.setReturnValue(new ClientboundBlockEntityDataPacket(be.getBlockPos(), 10, be.getUpdateTag()));
cir.cancel();
}
}
@Inject(method = "getUpdateTag", at = @At("HEAD"), cancellable = true)
public void getUpdateTag(CallbackInfoReturnable<CompoundTag> cir) {
if (this instanceof BlockEntityExtension) {
BlockEntityExtension entity = (BlockEntityExtension) this;
BlockEntity be = (BlockEntity) entity;
cir.setReturnValue(entity.saveClientData(new CompoundTag()));
cir.cancel();
}
}
}

View File

@@ -0,0 +1,39 @@
/*
* This file is part of architectury.
* Copyright (C) 2020, 2021 shedaniel
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package me.shedaniel.architectury.mixin.forge;
import me.shedaniel.architectury.extensions.BlockEntityExtension;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraftforge.common.extensions.IForgeTileEntity;
import org.jetbrains.annotations.NotNull;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@Mixin(BlockEntityExtension.class)
public interface MixinBlockEntityExtension extends IForgeTileEntity {
@Shadow(remap = false)
void loadClientData(@NotNull BlockState pos, @NotNull CompoundTag tag);
@Override
default void handleUpdateTag(BlockState state, CompoundTag tag) {
loadClientData(state, tag);
}
}

View File

@@ -0,0 +1,27 @@
/*
* This file is part of architectury.
* Copyright (C) 2020, 2021 shedaniel
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package me.shedaniel.architectury.mixin.forge;
import me.shedaniel.architectury.core.RegistryEntry;
import org.spongepowered.asm.mixin.Mixin;
@Mixin(RegistryEntry.class)
public class MixinRegistryEntry<T> {
}

View File

@@ -41,6 +41,8 @@ import net.minecraftforge.fml.network.NetworkEvent;
import net.minecraftforge.fml.network.NetworkRegistry;
import net.minecraftforge.fml.network.event.EventNetworkChannel;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.util.List;
import java.util.Map;
@@ -63,6 +65,7 @@ public class NetworkManagerImpl {
return (side == NetworkManager.Side.C2S ? NetworkDirection.PLAY_TO_SERVER : NetworkDirection.PLAY_TO_CLIENT).buildPacket(Pair.of(packetBuffer, 0), CHANNEL_ID).getThis();
}
private static final Logger LOGGER = LogManager.getLogger();
private static final ResourceLocation CHANNEL_ID = new ResourceLocation("architectury:network");
static final ResourceLocation SYNC_IDS = new ResourceLocation("architectury:sync_ids");
static final EventNetworkChannel CHANNEL = NetworkRegistry.newEventChannel(CHANNEL_ID, () -> "1", version -> true, version -> true);
@@ -94,7 +97,8 @@ public class NetworkManagerImpl {
if (event.getClass() != clazz) return;
NetworkEvent.Context context = event.getSource().get();
if (context.getPacketHandled()) return;
FriendlyByteBuf buffer = new FriendlyByteBuf(event.getPayload().copy());
FriendlyByteBuf buffer = event.getPayload();
if (buffer == null) return;
ResourceLocation type = buffer.readResourceLocation();
NetworkReceiver receiver = map.get(type);
@@ -119,7 +123,10 @@ public class NetworkManagerImpl {
return DistExecutor.unsafeCallWhenOn(Dist.CLIENT, () -> ClientNetworkingManager::getClientPlayer);
}
});
} else {
LOGGER.error("Unknown message ID: " + type);
}
context.setPacketHandled(true);
};
}

View File

@@ -21,15 +21,14 @@ package me.shedaniel.architectury.platform.forge;
import net.minecraftforge.eventbus.api.IEventBus;
import javax.annotation.Nullable;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.*;
import java.util.function.Consumer;
public final class EventBuses {
private EventBuses() {}
private static final Map<String, IEventBus> EVENT_BUS_MAP = new HashMap<>();
private static final Map<String, List<Consumer<IEventBus>>> ON_REGISTERED = new HashMap<>();
public static void registerModEventBus(String modId, IEventBus bus) {
IEventBus previous = EVENT_BUS_MAP.put(modId, bus);
@@ -37,6 +36,20 @@ public final class EventBuses {
EVENT_BUS_MAP.put(modId, previous);
throw new IllegalStateException("Can't register event bus for mod '" + modId + "' because it was previously registered!");
}
for (Consumer<IEventBus> runnable : ON_REGISTERED.getOrDefault(modId, Collections.emptyList())) {
runnable.accept(bus);
}
}
public static void onRegistered(String modId, Consumer<IEventBus> busConsumer) {
if (EVENT_BUS_MAP.containsKey(modId)) {
busConsumer.accept(EVENT_BUS_MAP.get(modId));
} else {
synchronized (ON_REGISTERED) {
ON_REGISTERED.computeIfAbsent(modId, s -> new ArrayList<>()).add(busConsumer);
}
}
}
public static Optional<IEventBus> getModEventBus(String modId) {

View File

@@ -0,0 +1,88 @@
/*
* This file is part of architectury.
* Copyright (C) 2020, 2021 shedaniel
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package me.shedaniel.architectury.plugin.forge;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.MethodInsnNode;
import org.objectweb.asm.tree.MethodNode;
import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin;
import org.spongepowered.asm.mixin.extensibility.IMixinInfo;
import java.util.List;
import java.util.Objects;
import java.util.Set;
public class ArchitecturyMixinPlugin implements IMixinConfigPlugin {
@Override
public void onLoad(String mixinPackage) {
}
@Override
public String getRefMapperConfig() {
return null;
}
@Override
public boolean shouldApplyMixin(String targetClassName, String mixinClassName) {
return true;
}
@Override
public void acceptTargets(Set<String> myTargets, Set<String> otherTargets) {
}
@Override
public List<String> getMixins() {
return null;
}
@Override
public void preApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) {
// Inject our own sugar
switch (mixinClassName) {
case "me.shedaniel.architectury.mixin.forge.MixinRegistryEntry":
targetClass.superName = "net/minecraftforge/registries/ForgeRegistryEntry";
for (MethodNode method : targetClass.methods) {
if (Objects.equals(method.name, "<init>")) {
for (AbstractInsnNode insnNode : method.instructions) {
if (insnNode.getOpcode() == Opcodes.INVOKESPECIAL && insnNode instanceof MethodInsnNode) {
MethodInsnNode node = (MethodInsnNode) insnNode;
if (Objects.equals(node.name, "<init>") && Objects.equals(node.owner, "java/lang/Object")) {
node.owner = "net/minecraftforge/registries/ForgeRegistryEntry";
break;
}
}
}
}
}
targetClass.signature = "<T::Lnet/minecraftforge/registries/IForgeRegistryEntry<TT;>;>Lnet/minecraftforge/registries/ForgeRegistryEntry<TT;>;";
break;
}
}
@Override
public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) {
}
}

View File

@@ -20,47 +20,72 @@
package me.shedaniel.architectury.registry.forge;
import com.google.common.collect.Lists;
import me.shedaniel.architectury.forge.ArchitecturyForge;
import me.shedaniel.architectury.platform.forge.EventBuses;
import net.minecraft.client.Minecraft;
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 net.minecraftforge.client.event.ColorHandlerEvent;
import net.minecraftforge.common.MinecraftForge;
import org.apache.commons.lang3.tuple.Pair;
import java.util.List;
import java.util.Objects;
import java.util.function.Supplier;
public class ColorHandlersImpl {
private static final List<Pair<ItemColor, ItemLike[]>> ITEM_COLORS = Lists.newArrayList();
private static final List<Pair<BlockColor, Block[]>> BLOCK_COLORS = Lists.newArrayList();
private static final List<Pair<ItemColor, Supplier<ItemLike>[]>> ITEM_COLORS = Lists.newArrayList();
private static final List<Pair<BlockColor, Supplier<Block>[]>> BLOCK_COLORS = Lists.newArrayList();
static {
MinecraftForge.EVENT_BUS.<ColorHandlerEvent.Item>addListener(event -> {
for (Pair<ItemColor, ItemLike[]> pair : ITEM_COLORS) {
event.getItemColors().register(pair.getLeft(), pair.getRight());
}
});
MinecraftForge.EVENT_BUS.<ColorHandlerEvent.Block>addListener(event -> {
for (Pair<BlockColor, Block[]> pair : BLOCK_COLORS) {
event.getBlockColors().register(pair.getLeft(), pair.getRight());
}
EventBuses.onRegistered(ArchitecturyForge.MOD_ID, bus -> {
bus.<ColorHandlerEvent.Item>addListener(event -> {
for (Pair<ItemColor, Supplier<ItemLike>[]> pair : ITEM_COLORS) {
event.getItemColors().register(pair.getLeft(), unpackItems(pair.getRight()));
}
});
bus.<ColorHandlerEvent.Block>addListener(event -> {
for (Pair<BlockColor, Supplier<Block>[]> pair : BLOCK_COLORS) {
event.getBlockColors().register(pair.getLeft(), unpackBlocks(pair.getRight()));
}
});
});
}
public static void registerItemColors(ItemColor itemColor, ItemLike... items) {
@SafeVarargs
public static void registerItemColors(ItemColor itemColor, Supplier<ItemLike>... items) {
Objects.requireNonNull(itemColor, "color is null!");
if (Minecraft.getInstance().getItemColors() == null) {
ITEM_COLORS.add(Pair.of(itemColor, items));
} else {
Minecraft.getInstance().getItemColors().register(itemColor, items);
Minecraft.getInstance().getItemColors().register(itemColor, unpackItems(items));
}
}
public static void registerBlockColors(BlockColor blockColor, Block... blocks) {
@SafeVarargs
public static void registerBlockColors(BlockColor blockColor, Supplier<Block>... blocks) {
Objects.requireNonNull(blockColor, "color is null!");
if (Minecraft.getInstance().getBlockColors() == null) {
BLOCK_COLORS.add(Pair.of(blockColor, blocks));
} else {
Minecraft.getInstance().getBlockColors().register(blockColor, blocks);
Minecraft.getInstance().getBlockColors().register(blockColor, unpackBlocks(blocks));
}
}
private static ItemLike[] unpackItems(Supplier<ItemLike>[] items) {
ItemLike[] array = new ItemLike[items.length];
for (int i = 0; i < items.length; i++) {
array[i] = Objects.requireNonNull(items[i].get());
}
return array;
}
private static Block[] unpackBlocks(Supplier<Block>[] blocks) {
Block[] array = new Block[blocks.length];
for (int i = 0; i < blocks.length; i++) {
array[i] = Objects.requireNonNull(blocks[i].get());
}
return array;
}
}

View File

@@ -0,0 +1,45 @@
/*
* This file is part of architectury.
* Copyright (C) 2020, 2021 shedaniel
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package me.shedaniel.architectury.registry.forge;
import net.minecraft.server.MinecraftServer;
import net.minecraft.world.level.GameRules;
import java.util.function.BiConsumer;
public class GameRuleFactoryImpl {
private GameRuleFactoryImpl() {}
public static GameRules.Type<GameRules.BooleanValue> createBooleanRule(boolean defaultValue) {
return GameRules.BooleanValue.create(defaultValue);
}
public static GameRules.Type<GameRules.BooleanValue> createBooleanRule(boolean defaultValue, BiConsumer<MinecraftServer, GameRules.BooleanValue> changedCallback) {
return GameRules.BooleanValue.create(defaultValue, changedCallback);
}
public static GameRules.Type<GameRules.IntegerValue> createIntRule(int defaultValue) {
return GameRules.IntegerValue.create(defaultValue);
}
public static GameRules.Type<GameRules.IntegerValue> createIntRule(int defaultValue, BiConsumer<MinecraftServer, GameRules.IntegerValue> changedCallback) {
return GameRules.IntegerValue.create(defaultValue, changedCallback);
}
}

View File

@@ -0,0 +1,28 @@
/*
* This file is part of architectury.
* Copyright (C) 2020, 2021 shedaniel
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package me.shedaniel.architectury.registry.forge;
import net.minecraft.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 GameRules.register(name, category, type);
}
}

View File

@@ -35,15 +35,15 @@ import net.minecraftforge.common.extensions.IForgeContainerType;
import net.minecraftforge.fml.network.NetworkHooks;
public class MenuRegistryImpl {
public static void openMenu(ServerPlayer player, ExtendedMenuProvider provider) {
public static void openExtendedMenu(ServerPlayer player, ExtendedMenuProvider provider) {
NetworkHooks.openGui(player, provider, provider::saveExtraData);
}
public static <T extends AbstractContainerMenu> MenuType<T> registerMenuType(SimpleMenuTypeFactory<T> factory) {
public static <T extends AbstractContainerMenu> MenuType<T> of(SimpleMenuTypeFactory<T> factory) {
return new MenuType<>(factory::create);
}
public static <T extends AbstractContainerMenu> MenuType<T> registerExtendedMenuType(ExtendedMenuTypeFactory<T> factory) {
public static <T extends AbstractContainerMenu> MenuType<T> ofExtended(ExtendedMenuTypeFactory<T> factory) {
return IForgeContainerType.create(factory::create);
}

View File

@@ -22,10 +22,14 @@ package me.shedaniel.architectury.registry.forge;
import com.google.common.base.Objects;
import com.google.common.collect.HashBasedTable;
import com.google.common.collect.Table;
import me.shedaniel.architectury.core.RegistryEntry;
import me.shedaniel.architectury.platform.forge.EventBuses;
import me.shedaniel.architectury.registry.Registries;
import me.shedaniel.architectury.registry.Registry;
import me.shedaniel.architectury.registry.RegistrySupplier;
import me.shedaniel.architectury.registry.registries.RegistryBuilder;
import me.shedaniel.architectury.registry.registries.RegistryOption;
import me.shedaniel.architectury.registry.registries.StandardRegistryOption;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.LazyLoadedValue;
@@ -33,6 +37,7 @@ import net.minecraftforge.event.RegistryEvent;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.RegistryObject;
import net.minecraftforge.registries.ForgeRegistry;
import net.minecraftforge.registries.IForgeRegistry;
import net.minecraftforge.registries.IForgeRegistryEntry;
import net.minecraftforge.registries.RegistryManager;
@@ -76,7 +81,11 @@ public class RegistriesImpl {
@Override
public <T> Registry<T> get(ResourceKey<net.minecraft.core.Registry<T>> registryKey) {
return new ForgeBackedRegistryImpl<>(registry, (IForgeRegistry) RegistryManager.ACTIVE.getRegistry(registryKey.location()));
return get(RegistryManager.ACTIVE.getRegistry(registryKey.location()));
}
public <T> Registry<T> get(IForgeRegistry registry) {
return new ForgeBackedRegistryImpl<>(this.registry, registry);
}
@Override
@@ -84,6 +93,13 @@ public class RegistriesImpl {
return new VanillaBackedRegistryImpl<>(registry);
}
@Override
public <T extends RegistryEntry<T>> RegistryBuilder<T> builder(Class<T> type, ResourceLocation registryId) {
return new RegistryBuilderWrapper<>(this, new net.minecraftforge.registries.RegistryBuilder<>()
.setName(registryId)
.setType((Class) type));
}
public class EventListener {
@SubscribeEvent
public void handleEvent(RegistryEvent.Register event) {
@@ -101,6 +117,37 @@ public class RegistriesImpl {
}
}
public static class RegistryBuilderWrapper<T extends RegistryEntry<T>> implements RegistryBuilder<T> {
@NotNull
private final RegistryProviderImpl provider;
@NotNull
private final net.minecraftforge.registries.RegistryBuilder<?> builder;
private boolean saveToDisk = false;
private boolean syncToClients = false;
public RegistryBuilderWrapper(@NotNull RegistryProviderImpl provider, @NotNull net.minecraftforge.registries.RegistryBuilder<?> builder) {
this.provider = provider;
this.builder = builder;
}
@Override
public @NotNull Registry<T> build() {
if (!syncToClients) builder.disableSync();
if (!saveToDisk) builder.disableSaving();
return provider.get(builder.create());
}
@Override
public @NotNull RegistryBuilder<T> option(@NotNull RegistryOption option) {
if (option == StandardRegistryOption.SAVE_TO_DISC) {
this.saveToDisk = true;
} else if (option == StandardRegistryOption.SYNC_TO_CLIENTS) {
this.syncToClients = true;
}
return this;
}
}
public static class VanillaBackedRegistryImpl<T> implements Registry<T> {
private net.minecraft.core.Registry<T> delegate;
@@ -116,27 +163,27 @@ public class RegistriesImpl {
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;
@@ -144,7 +191,7 @@ public class RegistriesImpl {
RegistrySupplier<?> other = (RegistrySupplier<?>) obj;
return other.getRegistryId().equals(getRegistryId()) && other.getId().equals(getId());
}
@Override
public String toString() {
return getRegistryId().toString() + "@" + id.toString();
@@ -164,6 +211,11 @@ public class RegistriesImpl {
return delegate.getKey(obj);
}
@Override
public int getRawId(T obj) {
return delegate.getId(obj);
}
@Override
public Optional<ResourceKey<T>> getKey(T t) {
return delegate.getResourceKey(t);
@@ -175,9 +227,14 @@ public class RegistriesImpl {
return delegate.get(id);
}
@Override
public T byRawId(int rawId) {
return delegate.byId(rawId);
}
@Override
public boolean contains(ResourceLocation resourceLocation) {
return delegate.containsKey(resourceLocation);
return delegate.keySet().contains(resourceLocation);
}
@Override
@@ -223,27 +280,27 @@ public class RegistriesImpl {
public @NotNull ResourceLocation getRegistryId() {
return delegate.getRegistryName();
}
@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;
@@ -251,7 +308,7 @@ public class RegistriesImpl {
RegistrySupplier<?> other = (RegistrySupplier<?>) obj;
return other.getRegistryId().equals(getRegistryId()) && other.getId().equals(getId());
}
@Override
public String toString() {
return getRegistryId().toString() + "@" + id.toString();
@@ -268,27 +325,27 @@ public class RegistriesImpl {
public @NotNull ResourceLocation getRegistryId() {
return delegate.getRegistryName();
}
@Override
public @NotNull ResourceLocation getId() {
return registryObject.getId();
}
@Override
public boolean isPresent() {
return registryObject.isPresent();
}
@Override
public T get() {
return (T) registryObject.get();
}
@Override
public int hashCode() {
return Objects.hashCode(getRegistryId(), getId());
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
@@ -296,7 +353,7 @@ public class RegistriesImpl {
RegistrySupplier<?> other = (RegistrySupplier<?>) obj;
return other.getRegistryId().equals(getRegistryId()) && other.getId().equals(getId());
}
@Override
public String toString() {
return getRegistryId().toString() + "@" + id.toString();
@@ -310,6 +367,11 @@ public class RegistriesImpl {
return delegate.getKey(obj);
}
@Override
public int getRawId(T obj) {
return ((ForgeRegistry<T>) delegate).getID(obj);
}
@Override
public Optional<ResourceKey<T>> getKey(T t) {
return Optional.ofNullable(getId(t)).map(id -> ResourceKey.create(key(), id));
@@ -321,6 +383,11 @@ public class RegistriesImpl {
return delegate.getValue(id);
}
@Override
public T byRawId(int rawId) {
return ((ForgeRegistry<T>) delegate).getValue(rawId);
}
@Override
public boolean contains(ResourceLocation resourceLocation) {
return delegate.containsKey(resourceLocation);

View File

@@ -31,4 +31,9 @@ public-f net.minecraft.world.biome.BiomeAmbience field_235212_i_ # music
public-f net.minecraft.world.biome.BiomeAmbience field_242523_e # skyColor
public-f net.minecraft.world.biome.BiomeAmbience field_242524_f # foliageColor
public-f net.minecraft.world.biome.BiomeAmbience field_242525_g # grassColor
public-f net.minecraft.world.biome.BiomeAmbience field_242526_h # grassColorModifier
public-f net.minecraft.world.biome.BiomeAmbience field_242526_h # grassColorModifier
public net.minecraft.world.storage.FolderName <init>(Ljava/lang/String;)V
public net.minecraft.world.GameRules$BooleanValue func_223567_b(ZLjava/util/function/BiConsumer;)Lnet/minecraft/world/GameRules$RuleType; # create
public net.minecraft.world.GameRules$BooleanValue func_223568_b(Z)Lnet/minecraft/world/GameRules$RuleType; # create
public net.minecraft.world.GameRules$IntegerValue func_223564_a(ILjava/util/function/BiConsumer;)Lnet/minecraft/world/GameRules$RuleType; # create
public net.minecraft.world.GameRules$IntegerValue func_223559_b(I)Lnet/minecraft/world/GameRules$RuleType; # create

View File

@@ -1,11 +1,15 @@
{
"required": true,
"package": "me.shedaniel.architectury.mixin.forge",
"plugin": "me.shedaniel.architectury.plugin.forge.ArchitecturyMixinPlugin",
"compatibilityLevel": "JAVA_8",
"minVersion": "0.8",
"client": [
],
"mixins": ["BiomeGenerationSettingsBuilderAccessor", "MobSpawnSettingsBuilderAccessor"],
"mixins": [
"BiomeGenerationSettingsBuilderAccessor", "MixinRegistryEntry", "MixinBlockEntity", "MixinBlockEntityExtension",
"MobSpawnSettingsBuilderAccessor"
],
"injectors": {
"defaultRequire": 1
}