mirror of
https://github.com/architectury/architectury-api.git
synced 2026-03-28 03:56:59 -05:00
Merge remote-tracking branch 'origin/1.20.2' into 1.20.3
# Conflicts: # gradle.properties # settings.gradle
This commit is contained in:
10
build.gradle
10
build.gradle
@@ -8,9 +8,8 @@ buildscript {
|
||||
|
||||
plugins {
|
||||
id "architectury-plugin" version "3.4-SNAPSHOT"
|
||||
id "dev.architectury.loom" version "1.1-SNAPSHOT" apply false
|
||||
id "dev.architectury.loom" version "1.4-SNAPSHOT" apply false
|
||||
id "org.cadixdev.licenser" version "0.6.1"
|
||||
id "io.github.juuxel.loom-vineflower" version "1.11.0" apply false
|
||||
id "me.shedaniel.unified-publishing" version "0.1.+" apply false
|
||||
id "maven-publish"
|
||||
}
|
||||
@@ -21,7 +20,6 @@ architectury {
|
||||
|
||||
subprojects {
|
||||
apply plugin: "dev.architectury.loom"
|
||||
apply plugin: "io.github.juuxel.loom-vineflower"
|
||||
|
||||
loom {
|
||||
silentMojangMappingsLicense()
|
||||
@@ -31,6 +29,10 @@ subprojects {
|
||||
minecraft "com.mojang:minecraft:${rootProject.architectury.minecraft}"
|
||||
mappings loom.officialMojangMappings()
|
||||
}
|
||||
|
||||
repositories {
|
||||
maven { url "https://maven.neoforged.net/releases/" }
|
||||
}
|
||||
}
|
||||
|
||||
allprojects {
|
||||
@@ -56,7 +58,7 @@ allprojects {
|
||||
|
||||
tasks.withType(JavaCompile) {
|
||||
options.encoding = "UTF-8"
|
||||
options.release = 16
|
||||
options.release = 17
|
||||
}
|
||||
|
||||
javadoc {
|
||||
|
||||
@@ -9,7 +9,9 @@ dependencies {
|
||||
}
|
||||
|
||||
architectury {
|
||||
common(rootProject.platforms.split(","))
|
||||
common(rootProject.platforms.split(",")) {
|
||||
it.platformPackage "neoforge", "forge"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021, 2022 architectury
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
package dev.architectury.impl;
|
||||
|
||||
import com.mojang.datafixers.util.Either;
|
||||
import dev.architectury.registry.registries.RegistrySupplier;
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.HolderOwner;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.tags.TagKey;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@ApiStatus.Internal
|
||||
public interface RegistrySupplierImpl<T> extends RegistrySupplier<T> {
|
||||
@Nullable
|
||||
Holder<T> getHolder();
|
||||
|
||||
@Override
|
||||
default T value() {
|
||||
return get();
|
||||
}
|
||||
|
||||
@Override
|
||||
default boolean isBound() {
|
||||
return isPresent();
|
||||
}
|
||||
|
||||
@Override
|
||||
default boolean is(ResourceLocation resourceLocation) {
|
||||
return getId().equals(resourceLocation);
|
||||
}
|
||||
|
||||
@Override
|
||||
default boolean is(ResourceKey<T> resourceKey) {
|
||||
return getKey().equals(resourceKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
default boolean is(Predicate<ResourceKey<T>> predicate) {
|
||||
return predicate.test(getKey());
|
||||
}
|
||||
|
||||
@Override
|
||||
default boolean is(TagKey<T> tagKey) {
|
||||
Holder<T> holder = getHolder();
|
||||
return holder != null && holder.is(tagKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
default Stream<TagKey<T>> tags() {
|
||||
Holder<T> holder = getHolder();
|
||||
return holder != null ? holder.tags() : Stream.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
default Either<ResourceKey<T>, T> unwrap() {
|
||||
return Either.left(getKey());
|
||||
}
|
||||
|
||||
@Override
|
||||
default Optional<ResourceKey<T>> unwrapKey() {
|
||||
return Optional.of(getKey());
|
||||
}
|
||||
|
||||
@Override
|
||||
default Kind kind() {
|
||||
return Kind.REFERENCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
default boolean canSerializeIn(HolderOwner<T> holderOwner) {
|
||||
Holder<T> holder = getHolder();
|
||||
return holder != null && holder.canSerializeIn(holderOwner);
|
||||
}
|
||||
}
|
||||
@@ -41,11 +41,25 @@ public final class Platform {
|
||||
return simpleLoaderCache == 0;
|
||||
}
|
||||
|
||||
@Deprecated(forRemoval = true)
|
||||
public static boolean isForge() {
|
||||
return isForgeLike();
|
||||
}
|
||||
|
||||
public static boolean isForgeLike() {
|
||||
return isMinecraftForge() || isNeoForge();
|
||||
}
|
||||
|
||||
public static boolean isMinecraftForge() {
|
||||
updateLoaderCache();
|
||||
return simpleLoaderCache == 1;
|
||||
}
|
||||
|
||||
public static boolean isNeoForge() {
|
||||
updateLoaderCache();
|
||||
return simpleLoaderCache == 2;
|
||||
}
|
||||
|
||||
private static void updateLoaderCache() {
|
||||
if (simpleLoaderCache != -1) {
|
||||
return;
|
||||
@@ -54,6 +68,7 @@ public final class Platform {
|
||||
switch (ArchitecturyTarget.getCurrentTarget()) {
|
||||
case "fabric" -> simpleLoaderCache = 0;
|
||||
case "forge" -> simpleLoaderCache = 1;
|
||||
case "neoforge" -> simpleLoaderCache = 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
package dev.architectury.registry.registries;
|
||||
|
||||
import com.google.common.base.Suppliers;
|
||||
import dev.architectury.impl.RegistrySupplierImpl;
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
@@ -90,16 +92,25 @@ public class DeferredRegister<T> implements Iterable<RegistrySupplier<T>> {
|
||||
return registriesSupplier.get().get(key);
|
||||
}
|
||||
|
||||
private class Entry<R> implements RegistrySupplier<R> {
|
||||
private class Entry<R> implements RegistrySupplierImpl<R> {
|
||||
private final ResourceLocation id;
|
||||
private final Supplier<R> supplier;
|
||||
private RegistrySupplier<R> value;
|
||||
@Nullable
|
||||
private Holder<R> holder = null;
|
||||
|
||||
public Entry(ResourceLocation id, Supplier<R> supplier) {
|
||||
this.id = id;
|
||||
this.supplier = supplier;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Holder<R> getHolder() {
|
||||
if (holder != null) return holder;
|
||||
return holder = getRegistrar().getHolder(getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public RegistrarManager getRegistrarManager() {
|
||||
return DeferredRegister.this.getRegistrarManager();
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
package dev.architectury.registry.registries;
|
||||
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
@@ -68,6 +69,14 @@ public interface Registrar<T> extends Iterable<T> {
|
||||
|
||||
ResourceKey<? extends Registry<T>> key();
|
||||
|
||||
@Nullable
|
||||
Holder<T> getHolder(ResourceKey<T> key);
|
||||
|
||||
@Nullable
|
||||
default Holder<T> getHolder(ResourceLocation id) {
|
||||
return getHolder(ResourceKey.create(key(), id));
|
||||
}
|
||||
|
||||
/**
|
||||
* Listens to when the registry entry is registered, and calls the given action.
|
||||
* Evaluates immediately if the entry is already registered.
|
||||
|
||||
@@ -19,12 +19,13 @@
|
||||
|
||||
package dev.architectury.registry.registries;
|
||||
|
||||
import net.minecraft.core.Holder;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@ApiStatus.NonExtendable
|
||||
public interface RegistrySupplier<T> extends DeferredSupplier<T> {
|
||||
public interface RegistrySupplier<T> extends DeferredSupplier<T>, Holder<T> {
|
||||
RegistrarManager getRegistrarManager();
|
||||
|
||||
Registrar<T> getRegistrar();
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021, 2022 architectury
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
package dev.architectury.utils;
|
||||
|
||||
public class ArchitecturyConstants {
|
||||
public static final String MOD_ID = "architectury";
|
||||
}
|
||||
@@ -23,6 +23,7 @@ import com.google.common.base.Objects;
|
||||
import com.google.common.base.Suppliers;
|
||||
import com.google.common.collect.HashMultimap;
|
||||
import com.google.common.collect.Multimap;
|
||||
import dev.architectury.impl.RegistrySupplierImpl;
|
||||
import dev.architectury.registry.registries.Registrar;
|
||||
import dev.architectury.registry.registries.RegistrarBuilder;
|
||||
import dev.architectury.registry.registries.RegistrarManager;
|
||||
@@ -32,6 +33,7 @@ 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.fabricmc.fabric.api.event.registry.RegistryEntryAddedCallback;
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.MappedRegistry;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.core.registries.BuiltInRegistries;
|
||||
@@ -153,7 +155,17 @@ public class RegistrarManagerImpl {
|
||||
public RegistrySupplier<T> delegate(ResourceLocation id) {
|
||||
Supplier<T> value = Suppliers.memoize(() -> get(id));
|
||||
RegistrarImpl<T> registrar = this;
|
||||
return new RegistrySupplier<>() {
|
||||
return new RegistrySupplierImpl<T>() {
|
||||
@Nullable
|
||||
Holder<T> holder = null;
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Holder<T> getHolder() {
|
||||
if (holder != null) return holder;
|
||||
return holder = registrar.getHolder(getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public RegistrarManager getRegistrarManager() {
|
||||
return RegistrarManager.get(modId);
|
||||
@@ -259,6 +271,12 @@ public class RegistrarManagerImpl {
|
||||
return delegate.key();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Holder<T> getHolder(ResourceKey<T> key) {
|
||||
return delegate.getHolder(key).orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<T> iterator() {
|
||||
return delegate.iterator();
|
||||
|
||||
@@ -1,109 +1,28 @@
|
||||
plugins {
|
||||
id "com.github.johnrengelman.shadow" version "7.1.2"
|
||||
id "me.shedaniel.unified-publishing"
|
||||
}
|
||||
|
||||
loom {
|
||||
accessWidenerPath = project(":common").loom.accessWidenerPath
|
||||
|
||||
forge {
|
||||
mixinConfig "architectury.mixins.json"
|
||||
mixinConfig "architectury-common.mixins.json"
|
||||
|
||||
convertAccessWideners = true
|
||||
extraAccessWideners.add loom.accessWidenerPath.get().asFile.name
|
||||
}
|
||||
}
|
||||
|
||||
architectury {
|
||||
platformSetupLoomIde()
|
||||
forge()
|
||||
}
|
||||
|
||||
configurations {
|
||||
common
|
||||
shadowCommon // Don't use shadow from the shadow plugin because we don't want IDEA to index this.
|
||||
compileClasspath.extendsFrom common
|
||||
runtimeClasspath.extendsFrom common
|
||||
developmentForge.extendsFrom common
|
||||
forgeLike(["forge", "neoforge"]) {
|
||||
it.platformPackage "neoforge", "forge"
|
||||
it.remapForgeLike "net/minecraftforge/common/extensions/IForgeItem", "net/neoforged/neoforge/common/extensions/IItemExtension"
|
||||
it.remapForgeLike "net/minecraftforge/client/event/TextureStitchEvent\$Post", "net/neoforged/neoforge/client/event/TextureAtlasStitchedEvent"
|
||||
it.remapForgeLike "net/minecraftforge/fluids/ForgeFlowingFluid", "net/neoforged/neoforge/fluids/BaseFlowingFluid"
|
||||
it.remapForgeLike "net/minecraftforge/fluids/ForgeFlowingFluid\$Properties", "net/neoforged/neoforge/fluids/BaseFlowingFluid\$Properties"
|
||||
it.remapForgeLike "net/minecraftforge/common/ForgeHooks", "net/neoforged/neoforge/common/CommonHooks"
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
forge "net.minecraftforge:forge:${rootProject.architectury.minecraft}-${rootProject.forge_version}"
|
||||
|
||||
common(project(path: ":common", configuration: "namedElements")) { transitive false }
|
||||
shadowCommon(project(path: ":common", configuration: "transformProductionForge")) { transitive false }
|
||||
}
|
||||
|
||||
processResources {
|
||||
filesMatching("META-INF/mods.toml") {
|
||||
expand "version": project.version
|
||||
}
|
||||
inputs.property "META-INF/mods.toml", project.version
|
||||
}
|
||||
|
||||
shadowJar {
|
||||
exclude "fabric.mod.json"
|
||||
exclude "architectury-common.accessWidener"
|
||||
exclude "architectury.common.json"
|
||||
|
||||
configurations = [project.configurations.shadowCommon]
|
||||
archiveClassifier = "dev-shadow"
|
||||
|
||||
// Replace classes with forge's version
|
||||
exclude "dev/architectury/core/block/ArchitecturyLiquidBlock.class"
|
||||
exclude "dev/architectury/core/fluid/ArchitecturyFlowingFluid.class"
|
||||
exclude 'dev/architectury/core/fluid/ArchitecturyFlowingFluid$Source.class'
|
||||
exclude 'dev/architectury/core/fluid/ArchitecturyFlowingFluid$Flowing.class'
|
||||
exclude 'dev/architectury/core/item/ArchitecturyBucketItem.class'
|
||||
exclude 'dev/architectury/core/item/ArchitecturyMobBucketItem.class'
|
||||
relocate "dev.architectury.core.block.forge.imitator", "dev.architectury.core.block"
|
||||
relocate "dev.architectury.core.fluid.forge.imitator", "dev.architectury.core.fluid"
|
||||
relocate "dev.architectury.core.item.forge.imitator", "dev.architectury.core.item"
|
||||
}
|
||||
|
||||
remapJar {
|
||||
input.set shadowJar.archiveFile
|
||||
dependsOn shadowJar
|
||||
archiveClassifier = null
|
||||
}
|
||||
|
||||
task renameJarForPublication(type: Zip, dependsOn: remapJar) {
|
||||
from remapJar.archiveFile.map { zipTree(it) }
|
||||
archiveExtension = "jar"
|
||||
metadataCharset "UTF-8"
|
||||
destinationDirectory = base.libsDirectory
|
||||
archiveClassifier = project.name
|
||||
}
|
||||
|
||||
assemble.dependsOn renameJarForPublication
|
||||
|
||||
jar {
|
||||
archiveClassifier = "dev"
|
||||
}
|
||||
|
||||
sourcesJar {
|
||||
afterEvaluate {
|
||||
[":common"].forEach {
|
||||
def depSources = project(it).sourcesJar
|
||||
dependsOn depSources
|
||||
from(depSources.archiveFile.map { zipTree(it) }) {
|
||||
exclude "architectury.accessWidener"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
components.java {
|
||||
withVariantsFromConfiguration(project.configurations.shadowRuntimeElements) {
|
||||
skip()
|
||||
}
|
||||
compileOnly(project(path: ":common", configuration: "namedElements")) { transitive false }
|
||||
}
|
||||
|
||||
publishing {
|
||||
publications {
|
||||
mavenForge(MavenPublication) {
|
||||
artifactId = rootProject.archivesBaseName + "-forge"
|
||||
artifactId = rootProject.archivesBaseName + "-forge-like"
|
||||
from components.java
|
||||
}
|
||||
}
|
||||
@@ -120,33 +39,3 @@ publishing {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unifiedPublishing {
|
||||
project {
|
||||
displayName = "[MinecraftForge $rootProject.supported_version] v$project.version"
|
||||
releaseType = "$rootProject.artifact_type"
|
||||
changelog = releaseChangelog()
|
||||
gameVersions = ["1.20.2"]
|
||||
gameLoaders = ["forge"]
|
||||
mainPublication renameJarForPublication
|
||||
|
||||
var CURSE_API_KEY = project.findProperty("CURSE_API_KEY") ?: System.getenv("CURSE_API_KEY")
|
||||
if (CURSE_API_KEY != null) {
|
||||
curseforge {
|
||||
token = CURSE_API_KEY
|
||||
id = rootProject.curseforge_id
|
||||
gameVersions.addAll "Java 17"
|
||||
}
|
||||
}
|
||||
|
||||
var MODRINTH_TOKEN = project.findProperty("MODRINTH_TOKEN") ?: System.getenv("MODRINTH_TOKEN")
|
||||
if (MODRINTH_TOKEN != null) {
|
||||
modrinth {
|
||||
token = MODRINTH_TOKEN
|
||||
id = rootProject.modrinth_id
|
||||
version = "$project.version+$project.name"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,8 +19,8 @@
|
||||
|
||||
package dev.architectury.event.forge;
|
||||
|
||||
import dev.architectury.forge.ArchitecturyForge;
|
||||
import dev.architectury.platform.forge.EventBuses;
|
||||
import dev.architectury.platform.hooks.EventBusesHooks;
|
||||
import dev.architectury.utils.ArchitecturyConstants;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
@@ -29,23 +29,23 @@ public class EventHandlerImpl {
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public static void registerClient() {
|
||||
MinecraftForge.EVENT_BUS.register(EventHandlerImplClient.class);
|
||||
EventBuses.onRegistered(ArchitecturyForge.MOD_ID, bus -> {
|
||||
EventBusesHooks.whenAvailable(ArchitecturyConstants.MOD_ID, bus -> {
|
||||
bus.register(EventHandlerImplClient.ModBasedEventHandler.class);
|
||||
});
|
||||
}
|
||||
|
||||
public static void registerCommon() {
|
||||
MinecraftForge.EVENT_BUS.register(EventHandlerImplCommon.class);
|
||||
EventBuses.onRegistered(ArchitecturyForge.MOD_ID, bus -> {
|
||||
EventBusesHooks.whenAvailable(ArchitecturyConstants.MOD_ID, bus -> {
|
||||
bus.register(EventHandlerImplCommon.ModBasedEventHandler.class);
|
||||
});
|
||||
}
|
||||
|
||||
@OnlyIn(Dist.DEDICATED_SERVER)
|
||||
public static void registerServer() {
|
||||
MinecraftForge.EVENT_BUS.register(EventHandlerImplServer.class);
|
||||
EventBuses.onRegistered(ArchitecturyForge.MOD_ID, bus -> {
|
||||
bus.register(EventHandlerImplServer.ModBasedEventHandler.class);
|
||||
});
|
||||
// MinecraftForge.EVENT_BUS.register(EventHandlerImplServer.class);
|
||||
// EventBusesHooks.whenAvailable(ArchitecturyConstants.MOD_ID, bus -> {
|
||||
// bus.register(EventHandlerImplServer.ModBasedEventHandler.class);
|
||||
// });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ import dev.architectury.event.EventResult;
|
||||
import dev.architectury.event.events.client.ClientChatEvent;
|
||||
import dev.architectury.event.events.client.*;
|
||||
import dev.architectury.event.events.common.InteractionEvent;
|
||||
import dev.architectury.hooks.forgelike.ForgeLikeClientHooks;
|
||||
import dev.architectury.impl.ScreenAccessImpl;
|
||||
import dev.architectury.impl.TooltipEventColorContextImpl;
|
||||
import dev.architectury.impl.TooltipEventPositionContextImpl;
|
||||
@@ -92,8 +93,8 @@ public class EventHandlerImplClient {
|
||||
@SubscribeEvent(priority = EventPriority.HIGH)
|
||||
public static void eventRenderGameOverlayEvent(CustomizeGuiOverlayEvent.DebugText event) {
|
||||
if (Minecraft.getInstance().gui.getDebugOverlay().showDebugScreen()) {
|
||||
ClientGuiEvent.DEBUG_TEXT_LEFT.invoker().gatherText(event.getLeft());
|
||||
ClientGuiEvent.DEBUG_TEXT_RIGHT.invoker().gatherText(event.getRight());
|
||||
ClientGuiEvent.DEBUG_TEXT_LEFT.invoker().gatherText(ForgeLikeClientHooks.getLeft(event));
|
||||
ClientGuiEvent.DEBUG_TEXT_RIGHT.invoker().gatherText(ForgeLikeClientHooks.getRight(event));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -217,14 +218,12 @@ public class EventHandlerImplClient {
|
||||
|
||||
@SubscribeEvent(priority = EventPriority.HIGH)
|
||||
public static void eventMouseScrollEvent(ScreenEvent.MouseScrolled.Pre event) {
|
||||
if (ClientScreenInputEvent.MOUSE_SCROLLED_PRE.invoker().mouseScrolled(Minecraft.getInstance(), event.getScreen(), event.getMouseX(), event.getMouseY(), event.getDeltaX(), event.getDeltaY()).isFalse()) {
|
||||
event.setCanceled(true);
|
||||
}
|
||||
ForgeLikeClientHooks.preMouseScroll(event);
|
||||
}
|
||||
|
||||
@SubscribeEvent(priority = EventPriority.HIGH)
|
||||
public static void eventMouseScrollEvent(ScreenEvent.MouseScrolled.Post event) {
|
||||
ClientScreenInputEvent.MOUSE_SCROLLED_POST.invoker().mouseScrolled(Minecraft.getInstance(), event.getScreen(), event.getMouseX(), event.getMouseY(), event.getDeltaX(), event.getDeltaY());
|
||||
ForgeLikeClientHooks.postMouseScroll(event);
|
||||
}
|
||||
|
||||
@SubscribeEvent(priority = EventPriority.HIGH)
|
||||
@@ -301,9 +300,7 @@ public class EventHandlerImplClient {
|
||||
|
||||
@SubscribeEvent(priority = EventPriority.HIGH)
|
||||
public static void eventInputEvent(InputEvent.MouseScrollingEvent event) {
|
||||
if (ClientRawInputEvent.MOUSE_SCROLLED.invoker().mouseScrolled(Minecraft.getInstance(), event.getDeltaX(), event.getDeltaY()).isFalse()) {
|
||||
event.setCanceled(true);
|
||||
}
|
||||
ForgeLikeClientHooks.inputMouseScroll(event);
|
||||
}
|
||||
|
||||
@SubscribeEvent(priority = EventPriority.HIGH)
|
||||
@@ -325,10 +322,10 @@ public class EventHandlerImplClient {
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public static class ModBasedEventHandler {
|
||||
@SubscribeEvent(priority = EventPriority.HIGH)
|
||||
public static void eventTextureStitchEvent(TextureStitchEvent.Post event) {
|
||||
// ClientTextureStitchEvent.POST.invoker().stitch(event.getAtlas());
|
||||
}
|
||||
// @SubscribeEvent(priority = EventPriority.HIGH)
|
||||
// public static void eventTextureStitchEvent(TextureStitchEvent.Post event) {
|
||||
// ClientTextureStitchEvent.POST.invoker().stitch(event.getAtlas());
|
||||
// }
|
||||
|
||||
@SubscribeEvent(priority = EventPriority.HIGH)
|
||||
public static void event(FMLClientSetupEvent event) {
|
||||
|
||||
@@ -57,20 +57,30 @@ final class LootTableModificationContextImpl implements LootEvent.LootTableModif
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
} catch (NoSuchFieldException ignored2) {
|
||||
for (Field field : LootTable.class.getDeclaredFields()) {
|
||||
if (field.getType().equals(List.class)) {
|
||||
// This is probably the field
|
||||
field.setAccessible(true);
|
||||
try {
|
||||
pools = (List<LootPool>) field.get(table);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new RuntimeException(e);
|
||||
try {
|
||||
Field field = LootTable.class.getDeclaredField("pools");
|
||||
field.setAccessible(true);
|
||||
try {
|
||||
pools = (List<LootPool>) field.get(table);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
} catch (NoSuchFieldException ignored3) {
|
||||
for (Field field : LootTable.class.getDeclaredFields()) {
|
||||
if (field.getType().equals(List.class)) {
|
||||
// This is probably the field
|
||||
field.setAccessible(true);
|
||||
try {
|
||||
pools = (List<LootPool>) field.get(table);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pools == null) {
|
||||
throw new RuntimeException("Unable to find pools field in LootTable!");
|
||||
|
||||
if (pools == null) {
|
||||
throw new RuntimeException("Unable to find pools field in LootTable!");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,9 +24,7 @@ import net.minecraft.client.gui.components.Renderable;
|
||||
import net.minecraft.client.gui.components.events.GuiEventListener;
|
||||
import net.minecraft.client.gui.narration.NarratableEntry;
|
||||
import net.minecraft.client.gui.screens.Screen;
|
||||
import net.minecraftforge.fml.util.ObfuscationReflectionHelper;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.List;
|
||||
|
||||
public class ScreenHooksImpl {
|
||||
@@ -39,26 +37,14 @@ public class ScreenHooksImpl {
|
||||
}
|
||||
|
||||
public static <T extends AbstractWidget & Renderable & NarratableEntry> T addRenderableWidget(Screen screen, T widget) {
|
||||
try {
|
||||
return (T) ObfuscationReflectionHelper.findMethod(Screen.class, "m_142416_", GuiEventListener.class).invoke(screen, widget);
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return screen.addRenderableWidget(widget);
|
||||
}
|
||||
|
||||
public static <T extends Renderable> T addRenderableOnly(Screen screen, T listener) {
|
||||
try {
|
||||
return (T) ObfuscationReflectionHelper.findMethod(Screen.class, "m_169394_", Renderable.class).invoke(screen, listener);
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return screen.addRenderableOnly(listener);
|
||||
}
|
||||
|
||||
public static <T extends GuiEventListener & NarratableEntry> T addWidget(Screen screen, T listener) {
|
||||
try {
|
||||
return (T) ObfuscationReflectionHelper.findMethod(Screen.class, "m_7787_", GuiEventListener.class).invoke(screen, listener);
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return screen.addWidget(listener);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021, 2022 architectury
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
package dev.architectury.hooks.forgelike;
|
||||
|
||||
import dev.architectury.injectables.annotations.ExpectPlatform;
|
||||
import net.minecraftforge.client.event.CustomizeGuiOverlayEvent;
|
||||
import net.minecraftforge.client.event.InputEvent;
|
||||
import net.minecraftforge.client.event.ScreenEvent;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ApiStatus.Internal
|
||||
public class ForgeLikeClientHooks {
|
||||
@ExpectPlatform
|
||||
public static void preMouseScroll(ScreenEvent.MouseScrolled.Pre event) {
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
@ExpectPlatform
|
||||
public static void postMouseScroll(ScreenEvent.MouseScrolled.Post event) {
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
@ExpectPlatform
|
||||
public static void inputMouseScroll(InputEvent.MouseScrollingEvent event) {
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
@ExpectPlatform
|
||||
public static List<String> getLeft(CustomizeGuiOverlayEvent.DebugText event) {
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
@ExpectPlatform
|
||||
public static List<String> getRight(CustomizeGuiOverlayEvent.DebugText event) {
|
||||
throw new AssertionError();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021, 2022 architectury
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
package dev.architectury.hooks.forgelike;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import dev.architectury.injectables.annotations.ExpectPlatform;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraftforge.common.world.BiomeModifier;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
@ApiStatus.Internal
|
||||
public class ForgeLikeHooks {
|
||||
@ExpectPlatform
|
||||
public static void registerBiomeModifier(ResourceLocation id, Supplier<Codec<? extends BiomeModifier>> codecSupplier) {
|
||||
throw new AssertionError();
|
||||
}
|
||||
}
|
||||
@@ -19,11 +19,11 @@
|
||||
|
||||
package dev.architectury.hooks.level.entity.forge;
|
||||
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraftforge.common.util.FakePlayer;
|
||||
|
||||
public class PlayerHooksImpl {
|
||||
public static boolean isFake(Player playerEntity) {
|
||||
return playerEntity instanceof FakePlayer;
|
||||
return playerEntity instanceof ServerPlayer && playerEntity.getClass() != ServerPlayer.class;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
// adopted from fabric
|
||||
@Mixin(Minecraft.class)
|
||||
public abstract class MixinMinecraft {
|
||||
@Inject(at = @At(value = "FIELD", target = "Lnet/minecraft/client/Minecraft;gameThread:Ljava/lang/Thread;", shift = At.Shift.AFTER, ordinal = 0), method = "run")
|
||||
@Inject(at = @At(value = "INVOKE", target = "Ljava/lang/Runtime;getRuntime()Ljava/lang/Runtime;", ordinal = 0), method = "run")
|
||||
private void onStart(CallbackInfo ci) {
|
||||
ClientLifecycleEvent.CLIENT_STARTED.invoker().stateChanged((Minecraft) (Object) this);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021, 2022 architectury
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
package dev.architectury.platform.hooks;
|
||||
|
||||
import dev.architectury.injectables.annotations.ExpectPlatform;
|
||||
import net.minecraftforge.eventbus.api.IEventBus;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public final class EventBusesHooks {
|
||||
private EventBusesHooks() {
|
||||
}
|
||||
|
||||
@ExpectPlatform
|
||||
public static void whenAvailable(String modId, Consumer<IEventBus> busConsumer) {
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
@ExpectPlatform
|
||||
public static Optional<IEventBus> getModEventBus(String modId) {
|
||||
throw new AssertionError();
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
package dev.architectury.plugin.forge;
|
||||
|
||||
import dev.architectury.injectables.targets.ArchitecturyTarget;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin;
|
||||
import org.spongepowered.asm.mixin.extensibility.IMixinInfo;
|
||||
@@ -29,7 +30,7 @@ import java.util.Set;
|
||||
public class ArchitecturyMixinPlugin implements IMixinConfigPlugin {
|
||||
@Override
|
||||
public void onLoad(String mixinPackage) {
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -44,21 +45,23 @@ public class ArchitecturyMixinPlugin implements IMixinConfigPlugin {
|
||||
|
||||
@Override
|
||||
public void acceptTargets(Set<String> myTargets, Set<String> otherTargets) {
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getMixins() {
|
||||
return null;
|
||||
return ArchitecturyTarget.getCurrentTarget().equals("forge")
|
||||
? List.of()
|
||||
: List.of("neoforge.MixinChunkSerializer");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) {
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) {
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,14 +19,12 @@
|
||||
|
||||
package dev.architectury.registry.client.keymappings.forge;
|
||||
|
||||
import dev.architectury.forge.ArchitecturyForge;
|
||||
import dev.architectury.platform.hooks.EventBusesHooks;
|
||||
import dev.architectury.utils.ArchitecturyConstants;
|
||||
import net.minecraft.client.KeyMapping;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.Options;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.client.event.RegisterKeyMappingsEvent;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
@@ -34,12 +32,17 @@ import org.apache.logging.log4j.Logger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Mod.EventBusSubscriber(modid = ArchitecturyForge.MOD_ID, bus = Mod.EventBusSubscriber.Bus.MOD, value = Dist.CLIENT)
|
||||
public class KeyMappingRegistryImpl {
|
||||
private static final Logger LOGGER = LogManager.getLogger(KeyMappingRegistryImpl.class);
|
||||
private static final List<KeyMapping> MAPPINGS = new ArrayList<>();
|
||||
private static boolean eventCalled = false;
|
||||
|
||||
static {
|
||||
EventBusesHooks.whenAvailable(ArchitecturyConstants.MOD_ID, bus -> {
|
||||
bus.addListener(KeyMappingRegistryImpl::event);
|
||||
});
|
||||
}
|
||||
|
||||
public static void register(KeyMapping mapping) {
|
||||
if (eventCalled) {
|
||||
Options options = Minecraft.getInstance().options;
|
||||
@@ -50,7 +53,6 @@ public class KeyMappingRegistryImpl {
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void event(RegisterKeyMappingsEvent event) {
|
||||
MAPPINGS.forEach(event::register);
|
||||
eventCalled = true;
|
||||
|
||||
@@ -19,8 +19,8 @@
|
||||
|
||||
package dev.architectury.registry.client.level.entity.forge;
|
||||
|
||||
import dev.architectury.forge.ArchitecturyForge;
|
||||
import dev.architectury.platform.forge.EventBuses;
|
||||
import dev.architectury.platform.hooks.EventBusesHooks;
|
||||
import dev.architectury.utils.ArchitecturyConstants;
|
||||
import net.minecraft.client.model.geom.ModelLayerLocation;
|
||||
import net.minecraft.client.model.geom.builders.LayerDefinition;
|
||||
import net.minecraftforge.client.event.EntityRenderersEvent;
|
||||
@@ -34,7 +34,7 @@ public class EntityModelLayerRegistryImpl {
|
||||
private static final Map<ModelLayerLocation, Supplier<LayerDefinition>> DEFINITIONS = new ConcurrentHashMap<>();
|
||||
|
||||
static {
|
||||
EventBuses.onRegistered(ArchitecturyForge.MOD_ID, bus -> {
|
||||
EventBusesHooks.whenAvailable(ArchitecturyConstants.MOD_ID, bus -> {
|
||||
bus.register(EntityModelLayerRegistryImpl.class);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -19,8 +19,8 @@
|
||||
|
||||
package dev.architectury.registry.client.level.entity.forge;
|
||||
|
||||
import dev.architectury.forge.ArchitecturyForge;
|
||||
import dev.architectury.platform.forge.EventBuses;
|
||||
import dev.architectury.platform.hooks.EventBusesHooks;
|
||||
import dev.architectury.utils.ArchitecturyConstants;
|
||||
import net.minecraft.client.renderer.entity.EntityRendererProvider;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
@@ -39,7 +39,7 @@ public class EntityRendererRegistryImpl {
|
||||
}
|
||||
|
||||
static {
|
||||
EventBuses.onRegistered(ArchitecturyForge.MOD_ID, bus -> {
|
||||
EventBusesHooks.whenAvailable(ArchitecturyConstants.MOD_ID, bus -> {
|
||||
bus.register(EntityRendererRegistryImpl.class);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -20,8 +20,9 @@
|
||||
package dev.architectury.registry.client.particle.forge;
|
||||
|
||||
import com.mojang.logging.LogUtils;
|
||||
import dev.architectury.forge.ArchitecturyForge;
|
||||
import dev.architectury.platform.hooks.EventBusesHooks;
|
||||
import dev.architectury.registry.client.particle.ParticleProviderRegistry;
|
||||
import dev.architectury.utils.ArchitecturyConstants;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.particle.ParticleEngine;
|
||||
import net.minecraft.client.particle.ParticleProvider;
|
||||
@@ -31,21 +32,22 @@ import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.core.particles.ParticleOptions;
|
||||
import net.minecraft.core.particles.ParticleType;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.client.event.RegisterParticleProvidersEvent;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@Mod.EventBusSubscriber(modid = ArchitecturyForge.MOD_ID, value = Dist.CLIENT, bus = Mod.EventBusSubscriber.Bus.MOD)
|
||||
public class ParticleProviderRegistryImpl {
|
||||
|
||||
public static final Logger LOGGER = LogUtils.getLogger();
|
||||
|
||||
static {
|
||||
EventBusesHooks.whenAvailable(ArchitecturyConstants.MOD_ID, bus -> {
|
||||
bus.addListener(ParticleProviderRegistryImpl::onParticleFactoryRegister);
|
||||
});
|
||||
}
|
||||
|
||||
private static final class ExtendedSpriteSetImpl implements ParticleProviderRegistry.ExtendedSpriteSet {
|
||||
private final ParticleEngine engine;
|
||||
private final SpriteSet delegate;
|
||||
@@ -105,7 +107,6 @@ public class ParticleProviderRegistryImpl {
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onParticleFactoryRegister(RegisterParticleProvidersEvent event) {
|
||||
if (deferred != null) {
|
||||
ParticleProviderRegistrar registrar = ParticleProviderRegistrar.ofForge(event);
|
||||
|
||||
@@ -20,8 +20,8 @@
|
||||
package dev.architectury.registry.client.rendering.forge;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import dev.architectury.forge.ArchitecturyForge;
|
||||
import dev.architectury.platform.forge.EventBuses;
|
||||
import dev.architectury.platform.hooks.EventBusesHooks;
|
||||
import dev.architectury.utils.ArchitecturyConstants;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.color.block.BlockColor;
|
||||
import net.minecraft.client.color.item.ItemColor;
|
||||
@@ -40,7 +40,7 @@ public class ColorHandlerRegistryImpl {
|
||||
private static final List<Pair<BlockColor, Supplier<? extends Block>[]>> BLOCK_COLORS = Lists.newArrayList();
|
||||
|
||||
static {
|
||||
EventBuses.onRegistered(ArchitecturyForge.MOD_ID, bus -> {
|
||||
EventBusesHooks.whenAvailable(ArchitecturyConstants.MOD_ID, bus -> {
|
||||
bus.register(ColorHandlerRegistryImpl.class);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -22,21 +22,19 @@ package dev.architectury.registry.forge;
|
||||
import com.google.common.base.Suppliers;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.common.collect.MultimapBuilder;
|
||||
import dev.architectury.forge.ArchitecturyForge;
|
||||
import dev.architectury.platform.hooks.EventBusesHooks;
|
||||
import dev.architectury.registry.CreativeTabOutput;
|
||||
import dev.architectury.registry.CreativeTabRegistry;
|
||||
import dev.architectury.registry.registries.DeferredSupplier;
|
||||
import dev.architectury.utils.ArchitecturyConstants;
|
||||
import net.minecraft.core.registries.BuiltInRegistries;
|
||||
import net.minecraft.core.registries.Registries;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.CreativeModeTab;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.common.CreativeModeTabRegistry;
|
||||
import net.minecraftforge.common.util.MutableHashedLinkedMap;
|
||||
import net.minecraftforge.event.BuildCreativeModeTabContentsEvent;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
@@ -46,7 +44,6 @@ import java.util.*;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
@Mod.EventBusSubscriber(modid = ArchitecturyForge.MOD_ID, bus = Mod.EventBusSubscriber.Bus.MOD, value = Dist.CLIENT)
|
||||
public class CreativeTabRegistryImpl {
|
||||
private static final Logger LOGGER = LogManager.getLogger(CreativeTabRegistryImpl.class);
|
||||
|
||||
@@ -54,6 +51,10 @@ public class CreativeTabRegistryImpl {
|
||||
private static final Multimap<TabKey, Supplier<ItemStack>> APPENDS = MultimapBuilder.hashKeys().arrayListValues().build();
|
||||
|
||||
static {
|
||||
EventBusesHooks.whenAvailable(ArchitecturyConstants.MOD_ID, bus -> {
|
||||
bus.addListener(CreativeTabRegistryImpl::event);
|
||||
});
|
||||
|
||||
BUILD_CONTENTS_LISTENERS.add(event -> {
|
||||
for (Map.Entry<TabKey, Collection<Supplier<ItemStack>>> keyEntry : APPENDS.asMap().entrySet()) {
|
||||
Supplier<List<ItemStack>> stacks = Suppliers.memoize(() -> keyEntry.getValue().stream()
|
||||
@@ -76,7 +77,6 @@ public class CreativeTabRegistryImpl {
|
||||
});
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void event(BuildCreativeModeTabContentsEvent event) {
|
||||
for (Consumer<BuildCreativeModeTabContentsEvent> listener : BUILD_CONTENTS_LISTENERS) {
|
||||
listener.accept(event);
|
||||
|
||||
@@ -20,7 +20,8 @@
|
||||
package dev.architectury.registry.forge;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import dev.architectury.forge.ArchitecturyForge;
|
||||
import dev.architectury.platform.hooks.EventBusesHooks;
|
||||
import dev.architectury.utils.ArchitecturyConstants;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.packs.PackType;
|
||||
@@ -28,18 +29,20 @@ import net.minecraft.server.packs.resources.PreparableReloadListener;
|
||||
import net.minecraft.server.packs.resources.ReloadableResourceManager;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.event.AddReloadListenerEvent;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
@Mod.EventBusSubscriber(modid = ArchitecturyForge.MOD_ID)
|
||||
public class ReloadListenerRegistryImpl {
|
||||
private static List<PreparableReloadListener> serverDataReloadListeners = Lists.newArrayList();
|
||||
|
||||
static {
|
||||
MinecraftForge.EVENT_BUS.addListener(ReloadListenerRegistryImpl::addReloadListeners);
|
||||
}
|
||||
|
||||
public static void register(PackType type, PreparableReloadListener listener, @Nullable ResourceLocation listenerId, Collection<ResourceLocation> dependencies) {
|
||||
if (type == PackType.SERVER_DATA) {
|
||||
serverDataReloadListeners.add(listener);
|
||||
@@ -53,7 +56,6 @@ public class ReloadListenerRegistryImpl {
|
||||
((ReloadableResourceManager) Minecraft.getInstance().getResourceManager()).registerReloadListener(listener);
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void addReloadListeners(AddReloadListenerEvent event) {
|
||||
for (PreparableReloadListener listener : serverDataReloadListeners) {
|
||||
event.addListener(listener);
|
||||
|
||||
@@ -21,10 +21,10 @@ package dev.architectury.registry.level.biome.forge;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.mojang.serialization.Codec;
|
||||
import dev.architectury.forge.ArchitecturyForge;
|
||||
import dev.architectury.hooks.forgelike.ForgeLikeHooks;
|
||||
import dev.architectury.hooks.level.biome.*;
|
||||
import dev.architectury.platform.forge.EventBuses;
|
||||
import dev.architectury.registry.level.biome.BiomeModifications.BiomeContext;
|
||||
import dev.architectury.utils.ArchitecturyConstants;
|
||||
import dev.architectury.utils.GameInstance;
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.Registry;
|
||||
@@ -42,8 +42,6 @@ import net.minecraft.world.level.levelgen.GenerationStep;
|
||||
import net.minecraft.world.level.levelgen.carver.ConfiguredWorldCarver;
|
||||
import net.minecraft.world.level.levelgen.placement.PlacedFeature;
|
||||
import net.minecraftforge.common.world.*;
|
||||
import net.minecraftforge.registries.ForgeRegistries;
|
||||
import net.minecraftforge.registries.RegisterEvent;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -64,14 +62,8 @@ public class BiomeModificationsImpl {
|
||||
private static Codec<BiomeModifierImpl> noneBiomeModCodec = null;
|
||||
|
||||
public static void init() {
|
||||
EventBuses.onRegistered(ArchitecturyForge.MOD_ID, bus -> {
|
||||
bus.<RegisterEvent>addListener(event -> {
|
||||
event.register(ForgeRegistries.Keys.BIOME_MODIFIER_SERIALIZERS, registry -> {
|
||||
registry.register(new ResourceLocation(ArchitecturyForge.MOD_ID, "none_biome_mod_codec"),
|
||||
noneBiomeModCodec = Codec.unit(BiomeModifierImpl.INSTANCE));
|
||||
});
|
||||
});
|
||||
});
|
||||
ForgeLikeHooks.registerBiomeModifier(new ResourceLocation(ArchitecturyConstants.MOD_ID, "none_biome_mod_codec"),
|
||||
() -> noneBiomeModCodec = Codec.unit(BiomeModifierImpl.INSTANCE));
|
||||
}
|
||||
|
||||
public static void addProperties(Predicate<BiomeContext> predicate, BiConsumer<BiomeContext, BiomeProperties.Mutable> modifier) {
|
||||
|
||||
@@ -19,8 +19,8 @@
|
||||
|
||||
package dev.architectury.registry.level.entity.forge;
|
||||
|
||||
import dev.architectury.forge.ArchitecturyForge;
|
||||
import dev.architectury.platform.forge.EventBuses;
|
||||
import dev.architectury.platform.hooks.EventBusesHooks;
|
||||
import dev.architectury.utils.ArchitecturyConstants;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.ai.attributes.AttributeSupplier;
|
||||
@@ -39,7 +39,7 @@ public class EntityAttributeRegistryImpl {
|
||||
}
|
||||
|
||||
static {
|
||||
EventBuses.onRegistered(ArchitecturyForge.MOD_ID, bus -> {
|
||||
EventBusesHooks.whenAvailable(ArchitecturyConstants.MOD_ID, bus -> {
|
||||
bus.register(EntityAttributeRegistryImpl.class);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -21,23 +21,25 @@ package dev.architectury.registry.level.entity.trade.forge;
|
||||
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import dev.architectury.forge.ArchitecturyForge;
|
||||
import net.minecraft.core.NonNullList;
|
||||
import net.minecraft.world.entity.npc.VillagerProfession;
|
||||
import net.minecraft.world.entity.npc.VillagerTrades;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.event.village.VillagerTradesEvent;
|
||||
import net.minecraftforge.event.village.WandererTradesEvent;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@Mod.EventBusSubscriber(modid = ArchitecturyForge.MOD_ID)
|
||||
public class TradeRegistryImpl {
|
||||
private static final Map<VillagerProfession, Int2ObjectMap<List<VillagerTrades.ItemListing>>> TRADES_TO_ADD = new HashMap<>();
|
||||
private static final List<VillagerTrades.ItemListing> WANDERER_TRADER_TRADES_GENERIC = new ArrayList<>();
|
||||
private static final List<VillagerTrades.ItemListing> WANDERER_TRADER_TRADES_RARE = new ArrayList<>();
|
||||
|
||||
static {
|
||||
MinecraftForge.EVENT_BUS.addListener(TradeRegistryImpl::onTradeRegistering);
|
||||
MinecraftForge.EVENT_BUS.addListener(TradeRegistryImpl::onWanderingTradeRegistering);
|
||||
}
|
||||
|
||||
public static void registerVillagerTrade0(VillagerProfession profession, int level, VillagerTrades.ItemListing... trades) {
|
||||
Int2ObjectMap<List<VillagerTrades.ItemListing>> tradesForProfession = TRADES_TO_ADD.computeIfAbsent(profession, $ -> new Int2ObjectOpenHashMap<>());
|
||||
List<VillagerTrades.ItemListing> tradesForLevel = tradesForProfession.computeIfAbsent(level, $ -> new ArrayList<>());
|
||||
@@ -52,7 +54,6 @@ public class TradeRegistryImpl {
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onTradeRegistering(VillagerTradesEvent event) {
|
||||
Int2ObjectMap<List<VillagerTrades.ItemListing>> trades = TRADES_TO_ADD.get(event.getType());
|
||||
|
||||
@@ -63,7 +64,6 @@ public class TradeRegistryImpl {
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onWanderingTradeRegistering(WandererTradesEvent event) {
|
||||
if (!WANDERER_TRADER_TRADES_GENERIC.isEmpty()) {
|
||||
event.getGenericTrades().addAll(WANDERER_TRADER_TRADES_GENERIC);
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
"MixinMinecraft"
|
||||
],
|
||||
"mixins": [
|
||||
"MixinChunkSerializer",
|
||||
"MixinEntitySpawnExtension",
|
||||
"MixinFallingBlockEntity",
|
||||
"MixinItemExtension",
|
||||
|
||||
@@ -17,7 +17,8 @@ fabric_loader_version=0.14.23
|
||||
fabric_api_version=0.90.3+1.20.3
|
||||
mod_menu_version=7.0.0
|
||||
|
||||
forge_version=48.0.1
|
||||
forge_version=48.0.38
|
||||
neoforge_version=20.2.59-beta
|
||||
|
||||
curseforge_id=419699
|
||||
modrinth_id=lhGA9TYQ
|
||||
|
||||
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,5 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.1-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
||||
155
minecraftforge/build.gradle
Normal file
155
minecraftforge/build.gradle
Normal file
@@ -0,0 +1,155 @@
|
||||
plugins {
|
||||
id "com.github.johnrengelman.shadow" version "7.1.2"
|
||||
id "me.shedaniel.unified-publishing"
|
||||
}
|
||||
|
||||
loom {
|
||||
accessWidenerPath = project(":common").loom.accessWidenerPath
|
||||
|
||||
forge {
|
||||
mixinConfig "architectury.mixins.json"
|
||||
mixinConfig "architectury-common.mixins.json"
|
||||
mixinConfig "architectury-forge.mixins.json"
|
||||
|
||||
convertAccessWideners = true
|
||||
extraAccessWideners.add loom.accessWidenerPath.get().asFile.name
|
||||
}
|
||||
}
|
||||
|
||||
architectury {
|
||||
platformSetupLoomIde()
|
||||
forge()
|
||||
}
|
||||
|
||||
configurations {
|
||||
common
|
||||
shadowCommon // Don't use shadow from the shadow plugin because we don't want IDEA to index this.
|
||||
compileClasspath.extendsFrom common
|
||||
runtimeClasspath.extendsFrom common
|
||||
developmentForge.extendsFrom common
|
||||
}
|
||||
|
||||
dependencies {
|
||||
forge "net.minecraftforge:forge:${rootProject.architectury.minecraft}-${rootProject.forge_version}"
|
||||
|
||||
common(project(path: ":common", configuration: "namedElements")) { transitive false }
|
||||
common(project(path: ":forge", configuration: "namedElements")) { transitive false }
|
||||
shadowCommon(project(path: ":common", configuration: "transformProductionForge")) { transitive false }
|
||||
shadowCommon(project(path: ":forge", configuration: "transformProductionForge")) { transitive false }
|
||||
}
|
||||
|
||||
processResources {
|
||||
filesMatching("META-INF/mods.toml") {
|
||||
expand "version": project.version
|
||||
}
|
||||
inputs.property "META-INF/mods.toml", project.version
|
||||
}
|
||||
|
||||
shadowJar {
|
||||
exclude "fabric.mod.json"
|
||||
exclude "architectury-common.accessWidener"
|
||||
exclude "architectury.common.json"
|
||||
|
||||
configurations = [project.configurations.shadowCommon]
|
||||
archiveClassifier = "dev-shadow"
|
||||
|
||||
// Replace classes with forge's version
|
||||
exclude "dev/architectury/core/block/ArchitecturyLiquidBlock.class"
|
||||
exclude "dev/architectury/core/fluid/ArchitecturyFlowingFluid.class"
|
||||
exclude 'dev/architectury/core/fluid/ArchitecturyFlowingFluid$Source.class'
|
||||
exclude 'dev/architectury/core/fluid/ArchitecturyFlowingFluid$Flowing.class'
|
||||
exclude 'dev/architectury/core/item/ArchitecturyBucketItem.class'
|
||||
exclude 'dev/architectury/core/item/ArchitecturyMobBucketItem.class'
|
||||
relocate "dev.architectury.core.block.forge.imitator", "dev.architectury.core.block"
|
||||
relocate "dev.architectury.core.fluid.forge.imitator", "dev.architectury.core.fluid"
|
||||
relocate "dev.architectury.core.item.forge.imitator", "dev.architectury.core.item"
|
||||
}
|
||||
|
||||
remapJar {
|
||||
input.set shadowJar.archiveFile
|
||||
dependsOn shadowJar
|
||||
archiveClassifier = null
|
||||
}
|
||||
|
||||
task renameJarForPublication(type: Zip, dependsOn: remapJar) {
|
||||
from remapJar.archiveFile.map { zipTree(it) }
|
||||
archiveExtension = "jar"
|
||||
metadataCharset "UTF-8"
|
||||
destinationDirectory = base.libsDirectory
|
||||
archiveClassifier = project.name
|
||||
}
|
||||
|
||||
assemble.dependsOn renameJarForPublication
|
||||
|
||||
jar {
|
||||
archiveClassifier = "dev"
|
||||
}
|
||||
|
||||
sourcesJar {
|
||||
afterEvaluate {
|
||||
[":common"].forEach {
|
||||
def depSources = project(it).sourcesJar
|
||||
dependsOn depSources
|
||||
from(depSources.archiveFile.map { zipTree(it) }) {
|
||||
exclude "architectury.accessWidener"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
components.java {
|
||||
withVariantsFromConfiguration(project.configurations.shadowRuntimeElements) {
|
||||
skip()
|
||||
}
|
||||
}
|
||||
|
||||
publishing {
|
||||
publications {
|
||||
mavenMinecraftForge(MavenPublication) {
|
||||
artifactId = rootProject.archivesBaseName + "-forge"
|
||||
from components.java
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
if (System.getenv("MAVEN_PASS") != null) {
|
||||
maven {
|
||||
url = "https://deploy.shedaniel.me/"
|
||||
credentials {
|
||||
username = "shedaniel"
|
||||
password = System.getenv("MAVEN_PASS")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unifiedPublishing {
|
||||
project {
|
||||
displayName = "[MinecraftForge $rootProject.supported_version] v$project.version"
|
||||
releaseType = "$rootProject.artifact_type"
|
||||
changelog = releaseChangelog()
|
||||
gameVersions = ["1.20.2"]
|
||||
gameLoaders = ["forge"]
|
||||
mainPublication renameJarForPublication
|
||||
|
||||
var CURSE_API_KEY = project.findProperty("CURSE_API_KEY") ?: System.getenv("CURSE_API_KEY")
|
||||
if (CURSE_API_KEY != null) {
|
||||
curseforge {
|
||||
token = CURSE_API_KEY
|
||||
id = rootProject.curseforge_id
|
||||
gameVersions.addAll "Java 17"
|
||||
}
|
||||
}
|
||||
|
||||
var MODRINTH_TOKEN = project.findProperty("MODRINTH_TOKEN") ?: System.getenv("MODRINTH_TOKEN")
|
||||
if (MODRINTH_TOKEN != null) {
|
||||
modrinth {
|
||||
token = MODRINTH_TOKEN
|
||||
id = rootProject.modrinth_id
|
||||
version = "$project.version+$project.name"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
1
minecraftforge/gradle.properties
Normal file
1
minecraftforge/gradle.properties
Normal file
@@ -0,0 +1 @@
|
||||
loom.platform=forge
|
||||
@@ -19,18 +19,17 @@
|
||||
|
||||
package dev.architectury.forge;
|
||||
|
||||
import dev.architectury.platform.forge.EventBuses;
|
||||
import dev.architectury.event.EventHandler;
|
||||
import dev.architectury.platform.forge.EventBuses;
|
||||
import dev.architectury.registry.level.biome.forge.BiomeModificationsImpl;
|
||||
import dev.architectury.utils.ArchitecturyConstants;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
|
||||
|
||||
@Mod(ArchitecturyForge.MOD_ID)
|
||||
@Mod(ArchitecturyConstants.MOD_ID)
|
||||
public class ArchitecturyForge {
|
||||
public static final String MOD_ID = "architectury";
|
||||
|
||||
public ArchitecturyForge() {
|
||||
EventBuses.registerModEventBus(ArchitecturyForge.MOD_ID, FMLJavaModLoadingContext.get().getModEventBus());
|
||||
EventBuses.registerModEventBus(ArchitecturyConstants.MOD_ID, FMLJavaModLoadingContext.get().getModEventBus());
|
||||
EventHandler.init();
|
||||
BiomeModificationsImpl.init();
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021, 2022 architectury
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
package dev.architectury.hooks.forgelike.forge;
|
||||
|
||||
import dev.architectury.event.events.client.ClientRawInputEvent;
|
||||
import dev.architectury.event.events.client.ClientScreenInputEvent;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraftforge.client.event.CustomizeGuiOverlayEvent;
|
||||
import net.minecraftforge.client.event.InputEvent;
|
||||
import net.minecraftforge.client.event.ScreenEvent;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ForgeLikeClientHooksImpl {
|
||||
public static void preMouseScroll(ScreenEvent.MouseScrolled.Pre event) {
|
||||
if (ClientScreenInputEvent.MOUSE_SCROLLED_PRE.invoker().mouseScrolled(Minecraft.getInstance(), event.getScreen(), event.getMouseX(), event.getMouseY(), event.getDeltaX(), event.getDeltaY()).isFalse()) {
|
||||
event.setCanceled(true);
|
||||
}
|
||||
}
|
||||
|
||||
public static void postMouseScroll(ScreenEvent.MouseScrolled.Post event) {
|
||||
ClientScreenInputEvent.MOUSE_SCROLLED_POST.invoker().mouseScrolled(Minecraft.getInstance(), event.getScreen(), event.getMouseX(), event.getMouseY(), event.getDeltaX(), event.getDeltaY());
|
||||
}
|
||||
|
||||
public static void inputMouseScroll(InputEvent.MouseScrollingEvent event) {
|
||||
if (ClientRawInputEvent.MOUSE_SCROLLED.invoker().mouseScrolled(Minecraft.getInstance(), event.getDeltaX(), event.getDeltaY()).isFalse()) {
|
||||
event.setCanceled(true);
|
||||
}
|
||||
}
|
||||
|
||||
public static List<String> getLeft(CustomizeGuiOverlayEvent.DebugText event) {
|
||||
return event.getLeft();
|
||||
}
|
||||
|
||||
public static List<String> getRight(CustomizeGuiOverlayEvent.DebugText event) {
|
||||
return event.getRight();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021, 2022 architectury
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
package dev.architectury.hooks.forgelike.forge;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import dev.architectury.platform.hooks.EventBusesHooks;
|
||||
import dev.architectury.utils.ArchitecturyConstants;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraftforge.common.world.BiomeModifier;
|
||||
import net.minecraftforge.registries.ForgeRegistries;
|
||||
import net.minecraftforge.registries.RegisterEvent;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class ForgeLikeHooksImpl {
|
||||
public static void registerBiomeModifier(ResourceLocation id, Supplier<Codec<? extends BiomeModifier>> codecSupplier) {
|
||||
EventBusesHooks.whenAvailable(ArchitecturyConstants.MOD_ID, bus -> {
|
||||
bus.<RegisterEvent>addListener(event -> {
|
||||
event.register(ForgeRegistries.Keys.BIOME_MODIFIER_SERIALIZERS, registry -> {
|
||||
registry.register(id, codecSupplier.get());
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -17,7 +17,7 @@
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
package dev.architectury.mixin.forge;
|
||||
package dev.architectury.mixin.forge.minecraftforge;
|
||||
|
||||
import dev.architectury.event.forge.EventHandlerImplCommon;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
@@ -22,7 +22,6 @@ package dev.architectury.networking.forge;
|
||||
|
||||
import com.google.common.collect.*;
|
||||
import com.mojang.logging.LogUtils;
|
||||
import dev.architectury.forge.ArchitecturyForge;
|
||||
import dev.architectury.networking.NetworkManager;
|
||||
import dev.architectury.networking.NetworkManager.NetworkReceiver;
|
||||
import dev.architectury.networking.transformers.PacketSink;
|
||||
@@ -52,7 +51,7 @@ import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.*;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@Mod.EventBusSubscriber(modid = ArchitecturyForge.MOD_ID)
|
||||
@Mod.EventBusSubscriber(modid = "architectury")
|
||||
public class NetworkManagerImpl {
|
||||
public static void registerReceiver(NetworkManager.Side side, ResourceLocation id, List<PacketTransformer> packetTransformers, NetworkReceiver receiver) {
|
||||
Objects.requireNonNull(id, "Cannot register receiver with a null ID!");
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021, 2022 architectury
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
package dev.architectury.platform.hooks.forge;
|
||||
|
||||
import dev.architectury.platform.forge.EventBuses;
|
||||
import net.minecraftforge.eventbus.api.IEventBus;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class EventBusesHooksImpl {
|
||||
public static void whenAvailable(String modId, Consumer<IEventBus> busConsumer) {
|
||||
EventBuses.onRegistered(modId, busConsumer);
|
||||
}
|
||||
|
||||
public static Optional<IEventBus> getModEventBus(String modId) {
|
||||
return EventBuses.getModEventBus(modId);
|
||||
}
|
||||
}
|
||||
@@ -23,13 +23,15 @@ import com.google.common.base.Objects;
|
||||
import com.google.common.base.Suppliers;
|
||||
import com.google.common.collect.HashMultimap;
|
||||
import com.google.common.collect.Multimap;
|
||||
import dev.architectury.platform.forge.EventBuses;
|
||||
import dev.architectury.impl.RegistrySupplierImpl;
|
||||
import dev.architectury.platform.hooks.EventBusesHooks;
|
||||
import dev.architectury.registry.registries.Registrar;
|
||||
import dev.architectury.registry.registries.RegistrarBuilder;
|
||||
import dev.architectury.registry.registries.RegistrarManager;
|
||||
import dev.architectury.registry.registries.RegistrySupplier;
|
||||
import dev.architectury.registry.registries.options.RegistrarOption;
|
||||
import dev.architectury.registry.registries.options.StandardRegistrarOption;
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.core.registries.BuiltInRegistries;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
@@ -123,7 +125,7 @@ public class RegistrarManagerImpl {
|
||||
public RegistryProviderImpl(String modId) {
|
||||
this.modId = modId;
|
||||
this.eventBus = Suppliers.memoize(() -> {
|
||||
IEventBus eventBus = EventBuses.getModEventBus(modId).orElseThrow(() -> new IllegalStateException("Can't get event bus for mod '" + modId + "' because it was not registered!"));
|
||||
IEventBus eventBus = EventBusesHooks.getModEventBus(modId).orElseThrow(() -> new IllegalStateException("Can't get event bus for mod '" + modId + "' because it was not registered!"));
|
||||
eventBus.register(new EventListener());
|
||||
return eventBus;
|
||||
});
|
||||
@@ -322,7 +324,17 @@ public class RegistrarManagerImpl {
|
||||
public RegistrySupplier<T> delegate(ResourceLocation id) {
|
||||
Supplier<T> value = Suppliers.memoize(() -> get(id));
|
||||
Registrar<T> registrar = this;
|
||||
return new RegistrySupplier<>() {
|
||||
return new RegistrySupplierImpl<T>() {
|
||||
@Nullable
|
||||
Holder<T> holder = null;
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Holder<T> getHolder() {
|
||||
if (holder != null) return holder;
|
||||
return holder = registrar.getHolder(getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public RegistrarManager getRegistrarManager() {
|
||||
return RegistrarManager.get(modId);
|
||||
@@ -432,6 +444,12 @@ public class RegistrarManagerImpl {
|
||||
return delegate.key();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Holder<T> getHolder(ResourceKey<T> key) {
|
||||
return delegate.getHolder(key).orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<T> iterator() {
|
||||
return delegate.iterator();
|
||||
@@ -462,7 +480,17 @@ public class RegistrarManagerImpl {
|
||||
public RegistrySupplier<T> delegate(ResourceLocation id) {
|
||||
Supplier<T> value = Suppliers.memoize(() -> get(id));
|
||||
Registrar<T> registrar = this;
|
||||
return new RegistrySupplier<>() {
|
||||
return new RegistrySupplierImpl<T>() {
|
||||
@Nullable
|
||||
Holder<T> holder = null;
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Holder<T> getHolder() {
|
||||
if (holder != null) return holder;
|
||||
return holder = registrar.getHolder(getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public RegistrarManager getRegistrarManager() {
|
||||
return RegistrarManager.get(modId);
|
||||
@@ -519,7 +547,17 @@ public class RegistrarManagerImpl {
|
||||
Data<T> data = (Data<T>) registry.computeIfAbsent(key(), type -> new Data<>());
|
||||
data.registerForForge(delegate, id, objectArr, supplier);
|
||||
Registrar<T> registrar = this;
|
||||
return new RegistrySupplier<>() {
|
||||
return new RegistrySupplierImpl<E>() {
|
||||
@Nullable
|
||||
Holder<E> holder = null;
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Holder<E> getHolder() {
|
||||
if (holder != null) return holder;
|
||||
return holder = getRegistrar().getHolder(getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public RegistrarManager getRegistrarManager() {
|
||||
return RegistrarManager.get(modId);
|
||||
@@ -625,6 +663,12 @@ public class RegistrarManagerImpl {
|
||||
return ResourceKey.createRegistryKey(delegate.getRegistryName());
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Holder<T> getHolder(ResourceKey<T> key) {
|
||||
return delegate.getHolder(key).orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<T> iterator() {
|
||||
return delegate.iterator();
|
||||
@@ -668,7 +712,17 @@ public class RegistrarManagerImpl {
|
||||
@Override
|
||||
public RegistrySupplier<T> delegate(ResourceLocation id) {
|
||||
if (isReady()) return delegate.get().delegate(id);
|
||||
return new RegistrySupplier<>() {
|
||||
return new RegistrySupplierImpl<T>() {
|
||||
@Nullable
|
||||
Holder<T> holder = null;
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Holder<T> getHolder() {
|
||||
if (holder != null || !isReady()) return holder;
|
||||
return holder = delegate.get().getHolder(getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public RegistrarManager getRegistrarManager() {
|
||||
return RegistrarManager.get(modId);
|
||||
@@ -761,6 +815,12 @@ public class RegistrarManagerImpl {
|
||||
return isReady() ? delegate.get().key() : ResourceKey.createRegistryKey(registryId);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Holder<T> getHolder(ResourceKey<T> key) {
|
||||
return isReady() ? delegate.get().getHolder(key) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void listen(ResourceLocation id, Consumer<T> callback) {
|
||||
if (isReady()) {
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"required": true,
|
||||
"package": "dev.architectury.mixin.forge",
|
||||
"compatibilityLevel": "JAVA_16",
|
||||
"minVersion": "0.8",
|
||||
"client": [
|
||||
],
|
||||
"mixins": [
|
||||
"minecraftforge.MixinChunkSerializer"
|
||||
],
|
||||
"injectors": {
|
||||
"defaultRequire": 1
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 150 KiB After Width: | Height: | Size: 150 KiB |
156
neoforge/build.gradle
Normal file
156
neoforge/build.gradle
Normal file
@@ -0,0 +1,156 @@
|
||||
plugins {
|
||||
id "com.github.johnrengelman.shadow" version "7.1.2"
|
||||
id "me.shedaniel.unified-publishing"
|
||||
}
|
||||
|
||||
loom {
|
||||
accessWidenerPath = project(":common").loom.accessWidenerPath
|
||||
}
|
||||
|
||||
architectury {
|
||||
platformSetupLoomIde()
|
||||
neoForge {
|
||||
platformPackage = "forge"
|
||||
remapForgeLike "net/minecraftforge/common/extensions/IForgeItem", "net/neoforged/neoforge/common/extensions/IItemExtension"
|
||||
remapForgeLike "net/minecraftforge/client/event/TextureStitchEvent\$Post", "net/neoforged/neoforge/client/event/TextureAtlasStitchedEvent"
|
||||
remapForgeLike "net/minecraftforge/fluids/ForgeFlowingFluid", "net/neoforged/neoforge/fluids/BaseFlowingFluid"
|
||||
remapForgeLike "net/minecraftforge/fluids/ForgeFlowingFluid\$Properties", "net/neoforged/neoforge/fluids/BaseFlowingFluid\$Properties"
|
||||
remapForgeLike "net/minecraftforge/common/ForgeHooks", "net/neoforged/neoforge/common/CommonHooks"
|
||||
}
|
||||
}
|
||||
|
||||
configurations {
|
||||
common
|
||||
forgeLike
|
||||
shadowCommon // Don't use shadow from the shadow plugin because we don't want IDEA to index this.
|
||||
compileClasspath.extendsFrom common, forgeLike
|
||||
runtimeClasspath.extendsFrom common, forgeLike
|
||||
developmentNeoForge.extendsFrom common
|
||||
developmentForgeLike.extendsFrom forgeLike
|
||||
}
|
||||
|
||||
dependencies {
|
||||
neoForge "net.neoforged:neoforge:${rootProject.neoforge_version}"
|
||||
|
||||
common(project(path: ":common", configuration: "namedElements")) { transitive false }
|
||||
forgeLike(project(path: ":forge", configuration: "namedElements")) { transitive false }
|
||||
shadowCommon(project(path: ":common", configuration: "transformProductionNeoForge")) { transitive false }
|
||||
shadowCommon(project(path: ":forge", configuration: "transformProductionNeoForge")) { transitive false }
|
||||
}
|
||||
|
||||
processResources {
|
||||
filesMatching("META-INF/mods.toml") {
|
||||
expand "version": project.version
|
||||
}
|
||||
inputs.property "META-INF/mods.toml", project.version
|
||||
}
|
||||
|
||||
shadowJar {
|
||||
exclude "fabric.mod.json"
|
||||
exclude "architectury-common.accessWidener"
|
||||
exclude "architectury.common.json"
|
||||
|
||||
configurations = [project.configurations.shadowCommon]
|
||||
archiveClassifier = "dev-shadow"
|
||||
|
||||
// Replace classes with forge's version
|
||||
exclude "dev/architectury/core/block/ArchitecturyLiquidBlock.class"
|
||||
exclude "dev/architectury/core/fluid/ArchitecturyFlowingFluid.class"
|
||||
exclude 'dev/architectury/core/fluid/ArchitecturyFlowingFluid$Source.class'
|
||||
exclude 'dev/architectury/core/fluid/ArchitecturyFlowingFluid$Flowing.class'
|
||||
exclude 'dev/architectury/core/item/ArchitecturyBucketItem.class'
|
||||
exclude 'dev/architectury/core/item/ArchitecturyMobBucketItem.class'
|
||||
relocate "dev.architectury.core.block.forge.imitator", "dev.architectury.core.block"
|
||||
relocate "dev.architectury.core.fluid.forge.imitator", "dev.architectury.core.fluid"
|
||||
relocate "dev.architectury.core.item.forge.imitator", "dev.architectury.core.item"
|
||||
}
|
||||
|
||||
remapJar {
|
||||
input.set shadowJar.archiveFile
|
||||
dependsOn shadowJar
|
||||
archiveClassifier = null
|
||||
atAccessWideners.add "architectury.accessWidener"
|
||||
}
|
||||
|
||||
task renameJarForPublication(type: Zip, dependsOn: remapJar) {
|
||||
from remapJar.archiveFile.map { zipTree(it) }
|
||||
archiveExtension = "jar"
|
||||
metadataCharset "UTF-8"
|
||||
destinationDirectory = base.libsDirectory
|
||||
archiveClassifier = project.name
|
||||
}
|
||||
|
||||
assemble.dependsOn renameJarForPublication
|
||||
|
||||
jar {
|
||||
archiveClassifier = "dev"
|
||||
}
|
||||
|
||||
sourcesJar {
|
||||
afterEvaluate {
|
||||
[":common"].forEach {
|
||||
def depSources = project(it).sourcesJar
|
||||
dependsOn depSources
|
||||
from(depSources.archiveFile.map { zipTree(it) }) {
|
||||
exclude "architectury.accessWidener"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
components.java {
|
||||
withVariantsFromConfiguration(project.configurations.shadowRuntimeElements) {
|
||||
skip()
|
||||
}
|
||||
}
|
||||
|
||||
publishing {
|
||||
publications {
|
||||
mavenNeoForge(MavenPublication) {
|
||||
artifactId = rootProject.archivesBaseName + "-neoforge"
|
||||
from components.java
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
if (System.getenv("MAVEN_PASS") != null) {
|
||||
maven {
|
||||
url = "https://deploy.shedaniel.me/"
|
||||
credentials {
|
||||
username = "shedaniel"
|
||||
password = System.getenv("MAVEN_PASS")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unifiedPublishing {
|
||||
project {
|
||||
displayName = "[NeoForge $rootProject.supported_version] v$project.version"
|
||||
releaseType = "$rootProject.artifact_type"
|
||||
changelog = releaseChangelog()
|
||||
gameVersions = ["1.20.2"]
|
||||
gameLoaders = ["neoforge"]
|
||||
mainPublication renameJarForPublication
|
||||
|
||||
var CURSE_API_KEY = project.findProperty("CURSE_API_KEY") ?: System.getenv("CURSE_API_KEY")
|
||||
if (CURSE_API_KEY != null) {
|
||||
curseforge {
|
||||
token = CURSE_API_KEY
|
||||
id = rootProject.curseforge_id
|
||||
gameVersions.addAll "Java 17"
|
||||
}
|
||||
}
|
||||
|
||||
var MODRINTH_TOKEN = project.findProperty("MODRINTH_TOKEN") ?: System.getenv("MODRINTH_TOKEN")
|
||||
if (MODRINTH_TOKEN != null) {
|
||||
modrinth {
|
||||
token = MODRINTH_TOKEN
|
||||
id = rootProject.modrinth_id
|
||||
version = "$project.version+$project.name"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
1
neoforge/gradle.properties
Normal file
1
neoforge/gradle.properties
Normal file
@@ -0,0 +1 @@
|
||||
loom.platform=neoforge
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021, 2022 architectury
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
package dev.architectury.hooks.forgelike.forge;
|
||||
|
||||
import dev.architectury.event.events.client.ClientRawInputEvent;
|
||||
import dev.architectury.event.events.client.ClientScreenInputEvent;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.neoforged.neoforge.client.event.CustomizeGuiOverlayEvent;
|
||||
import net.neoforged.neoforge.client.event.InputEvent;
|
||||
import net.neoforged.neoforge.client.event.ScreenEvent;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ForgeLikeClientHooksImpl {
|
||||
public static void preMouseScroll(ScreenEvent.MouseScrolled.Pre event) {
|
||||
if (ClientScreenInputEvent.MOUSE_SCROLLED_PRE.invoker().mouseScrolled(Minecraft.getInstance(), event.getScreen(), event.getMouseX(), event.getMouseY(), event.getScrollDeltaX(), event.getScrollDeltaY()).isFalse()) {
|
||||
event.setCanceled(true);
|
||||
}
|
||||
}
|
||||
|
||||
public static void postMouseScroll(ScreenEvent.MouseScrolled.Post event) {
|
||||
ClientScreenInputEvent.MOUSE_SCROLLED_POST.invoker().mouseScrolled(Minecraft.getInstance(), event.getScreen(), event.getMouseX(), event.getMouseY(), event.getScrollDeltaX(), event.getScrollDeltaY());
|
||||
}
|
||||
|
||||
public static void inputMouseScroll(InputEvent.MouseScrollingEvent event) {
|
||||
if (ClientRawInputEvent.MOUSE_SCROLLED.invoker().mouseScrolled(Minecraft.getInstance(), event.getScrollDeltaX(), event.getScrollDeltaY()).isFalse()) {
|
||||
event.setCanceled(true);
|
||||
}
|
||||
}
|
||||
|
||||
public static List<String> getLeft(CustomizeGuiOverlayEvent.DebugText event) {
|
||||
return event.getLeft();
|
||||
}
|
||||
|
||||
public static List<String> getRight(CustomizeGuiOverlayEvent.DebugText event) {
|
||||
return event.getRight();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021, 2022 architectury
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
package dev.architectury.hooks.forgelike.forge;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import dev.architectury.platform.hooks.forge.EventBusesHooksImpl;
|
||||
import dev.architectury.utils.ArchitecturyConstants;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.neoforged.neoforge.common.world.BiomeModifier;
|
||||
import net.neoforged.neoforge.registries.NeoForgeRegistries;
|
||||
import net.neoforged.neoforge.registries.RegisterEvent;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class ForgeLikeHooksImpl {
|
||||
public static void registerBiomeModifier(ResourceLocation id, Supplier<Codec<? extends BiomeModifier>> codecSupplier) {
|
||||
EventBusesHooksImpl.whenAvailable(ArchitecturyConstants.MOD_ID, bus -> {
|
||||
bus.<RegisterEvent>addListener(event -> {
|
||||
event.register(NeoForgeRegistries.Keys.BIOME_MODIFIER_SERIALIZERS, registry -> {
|
||||
registry.register(id, codecSupplier.get());
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021, 2022 architectury
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
package dev.architectury.mixin.forge.neoforge;
|
||||
|
||||
import dev.architectury.event.forge.EventHandlerImplCommon;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
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.chunk.ProtoChunk;
|
||||
import net.minecraft.world.level.chunk.storage.ChunkSerializer;
|
||||
import net.neoforged.bus.api.Event;
|
||||
import net.neoforged.neoforge.event.level.ChunkDataEvent;
|
||||
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.ModifyArg;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
@Mixin(ChunkSerializer.class)
|
||||
public class MixinChunkSerializer {
|
||||
@Unique
|
||||
private static ThreadLocal<WeakReference<ServerLevel>> level = new ThreadLocal<>();
|
||||
|
||||
@Inject(method = "read", at = @At("HEAD"))
|
||||
private static void read(ServerLevel worldIn, PoiManager arg2, ChunkPos arg3, CompoundTag arg4, CallbackInfoReturnable<ProtoChunk> cir) {
|
||||
level.set(new WeakReference<>(worldIn));
|
||||
}
|
||||
|
||||
@ModifyArg(method = "read", at = @At(value = "INVOKE",
|
||||
ordinal = 1,
|
||||
target = "Lnet/neoforged/bus/api/IEventBus;post(Lnet/neoforged/bus/api/Event;)Lnet/neoforged/bus/api/Event;"),
|
||||
index = 0)
|
||||
private static Event modifyProtoChunkLevel(Event event) {
|
||||
// We should get this PRed to Forge
|
||||
WeakReference<ServerLevel> levelRef = level.get();
|
||||
if (levelRef != null && event instanceof ChunkDataEvent.Load) {
|
||||
ChunkDataEvent.Load load = (ChunkDataEvent.Load) event;
|
||||
((EventHandlerImplCommon.LevelEventAttachment) load).architectury$attachLevel(levelRef.get());
|
||||
}
|
||||
level.remove();
|
||||
return event;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021, 2022 architectury
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
package dev.architectury.neoforge;
|
||||
|
||||
import dev.architectury.event.EventHandler;
|
||||
import dev.architectury.registry.level.biome.forge.BiomeModificationsImpl;
|
||||
import dev.architectury.utils.ArchitecturyConstants;
|
||||
import net.neoforged.fml.common.Mod;
|
||||
|
||||
@Mod(ArchitecturyConstants.MOD_ID)
|
||||
public class ArchitecturyNeoForge {
|
||||
public ArchitecturyNeoForge() {
|
||||
EventHandler.init();
|
||||
BiomeModificationsImpl.init();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021, 2022 architectury
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
package dev.architectury.networking.forge;
|
||||
|
||||
import dev.architectury.networking.NetworkManager;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.neoforged.api.distmarker.Dist;
|
||||
import net.neoforged.api.distmarker.OnlyIn;
|
||||
import net.neoforged.bus.api.SubscribeEvent;
|
||||
import net.neoforged.neoforge.client.event.ClientPlayerNetworkEvent;
|
||||
import net.neoforged.neoforge.common.NeoForge;
|
||||
import net.neoforged.neoforge.network.PlayNetworkDirection;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public class ClientNetworkingManager {
|
||||
public static void initClient() {
|
||||
NetworkManagerImpl.CHANNEL.addListener(NetworkManagerImpl.createPacketHandler(PlayNetworkDirection.PLAY_TO_CLIENT, NetworkManagerImpl.S2C_TRANSFORMERS));
|
||||
NeoForge.EVENT_BUS.register(ClientNetworkingManager.class);
|
||||
|
||||
NetworkManagerImpl.registerS2CReceiver(NetworkManagerImpl.SYNC_IDS, Collections.emptyList(), (buffer, context) -> {
|
||||
Set<ResourceLocation> receivables = NetworkManagerImpl.serverReceivables;
|
||||
int size = buffer.readInt();
|
||||
receivables.clear();
|
||||
for (int i = 0; i < size; i++) {
|
||||
receivables.add(buffer.readResourceLocation());
|
||||
}
|
||||
context.queue(() -> {
|
||||
NetworkManager.sendToServer(NetworkManagerImpl.SYNC_IDS, NetworkManagerImpl.sendSyncPacket(NetworkManagerImpl.C2S));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public static Player getClientPlayer() {
|
||||
return Minecraft.getInstance().player;
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void loggedOut(ClientPlayerNetworkEvent.LoggingOut event) {
|
||||
NetworkManagerImpl.serverReceivables.clear();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,203 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021, 2022 architectury
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
package dev.architectury.networking.forge;
|
||||
|
||||
|
||||
import com.google.common.collect.*;
|
||||
import com.mojang.logging.LogUtils;
|
||||
import dev.architectury.networking.NetworkManager;
|
||||
import dev.architectury.networking.NetworkManager.NetworkReceiver;
|
||||
import dev.architectury.networking.transformers.PacketSink;
|
||||
import dev.architectury.networking.transformers.PacketTransformer;
|
||||
import dev.architectury.utils.ArchitecturyConstants;
|
||||
import dev.architectury.utils.Env;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.network.protocol.Packet;
|
||||
import net.minecraft.network.protocol.game.ClientGamePacketListener;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.neoforged.api.distmarker.Dist;
|
||||
import net.neoforged.api.distmarker.OnlyIn;
|
||||
import net.neoforged.bus.api.SubscribeEvent;
|
||||
import net.neoforged.fml.DistExecutor;
|
||||
import net.neoforged.fml.LogicalSide;
|
||||
import net.neoforged.fml.common.Mod;
|
||||
import net.neoforged.neoforge.event.entity.player.PlayerEvent;
|
||||
import net.neoforged.neoforge.network.*;
|
||||
import net.neoforged.neoforge.network.event.EventNetworkChannel;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@Mod.EventBusSubscriber(modid = ArchitecturyConstants.MOD_ID)
|
||||
public class NetworkManagerImpl {
|
||||
public static void registerReceiver(NetworkManager.Side side, ResourceLocation id, List<PacketTransformer> packetTransformers, NetworkReceiver receiver) {
|
||||
Objects.requireNonNull(id, "Cannot register receiver with a null ID!");
|
||||
packetTransformers = Objects.requireNonNullElse(packetTransformers, List.of());
|
||||
Objects.requireNonNull(receiver, "Cannot register a null receiver!");
|
||||
if (side == NetworkManager.Side.C2S) {
|
||||
registerC2SReceiver(id, packetTransformers, receiver);
|
||||
} else if (side == NetworkManager.Side.S2C) {
|
||||
registerS2CReceiver(id, packetTransformers, receiver);
|
||||
}
|
||||
}
|
||||
|
||||
public static Packet<?> toPacket(NetworkManager.Side side, ResourceLocation id, FriendlyByteBuf buffer) {
|
||||
FriendlyByteBuf packetBuffer = new FriendlyByteBuf(Unpooled.buffer());
|
||||
packetBuffer.writeResourceLocation(id);
|
||||
packetBuffer.writeBytes(buffer);
|
||||
return (side == NetworkManager.Side.C2S ? PlayNetworkDirection.PLAY_TO_SERVER : PlayNetworkDirection.PLAY_TO_CLIENT).buildPacket(new INetworkDirection.PacketData(packetBuffer, 0), CHANNEL_ID);
|
||||
}
|
||||
|
||||
public static void collectPackets(PacketSink sink, NetworkManager.Side side, ResourceLocation id, FriendlyByteBuf buf) {
|
||||
PacketTransformer transformer = side == NetworkManager.Side.C2S ? C2S_TRANSFORMERS.get(id) : S2C_TRANSFORMERS.get(id);
|
||||
if (transformer != null) {
|
||||
transformer.outbound(side, id, buf, (side1, id1, buf1) -> {
|
||||
sink.accept(toPacket(side1, id1, buf1));
|
||||
});
|
||||
} else {
|
||||
sink.accept(toPacket(side, id, buf));
|
||||
}
|
||||
}
|
||||
|
||||
private static final Logger LOGGER = LogUtils.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.ChannelBuilder.named(CHANNEL_ID).networkProtocolVersion(() -> "").clientAcceptedVersions(version -> true).serverAcceptedVersions(version -> true).eventNetworkChannel();
|
||||
static final Map<ResourceLocation, NetworkReceiver> S2C = Maps.newHashMap();
|
||||
static final Map<ResourceLocation, NetworkReceiver> C2S = Maps.newHashMap();
|
||||
static final Map<ResourceLocation, PacketTransformer> S2C_TRANSFORMERS = Maps.newHashMap();
|
||||
static final Map<ResourceLocation, PacketTransformer> C2S_TRANSFORMERS = Maps.newHashMap();
|
||||
static final Set<ResourceLocation> serverReceivables = Sets.newHashSet();
|
||||
private static final Multimap<Player, ResourceLocation> clientReceivables = Multimaps.newMultimap(Maps.newHashMap(), Sets::newHashSet);
|
||||
|
||||
static {
|
||||
CHANNEL.addListener(createPacketHandler(PlayNetworkDirection.PLAY_TO_SERVER, C2S_TRANSFORMERS));
|
||||
|
||||
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> ClientNetworkingManager::initClient);
|
||||
|
||||
registerC2SReceiver(SYNC_IDS, Collections.emptyList(), (buffer, context) -> {
|
||||
Set<ResourceLocation> receivables = (Set<ResourceLocation>) clientReceivables.get(context.getPlayer());
|
||||
int size = buffer.readInt();
|
||||
receivables.clear();
|
||||
for (int i = 0; i < size; i++) {
|
||||
receivables.add(buffer.readResourceLocation());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static <T extends NetworkEvent> Consumer<T> createPacketHandler(INetworkDirection<?> direction, Map<ResourceLocation, PacketTransformer> map) {
|
||||
return event -> {
|
||||
NetworkEvent.Context context = event.getSource();
|
||||
if (context.getDirection() != direction) return;
|
||||
if (context.getPacketHandled()) return;
|
||||
FriendlyByteBuf buffer = event.getPayload();
|
||||
if (buffer == null) return;
|
||||
ResourceLocation type = buffer.readResourceLocation();
|
||||
PacketTransformer transformer = map.get(type);
|
||||
|
||||
if (transformer != null) {
|
||||
NetworkManager.Side side = context.getDirection().getReceptionSide() == LogicalSide.CLIENT ? NetworkManager.Side.S2C : NetworkManager.Side.C2S;
|
||||
NetworkManager.PacketContext packetContext = new NetworkManager.PacketContext() {
|
||||
@Override
|
||||
public Player getPlayer() {
|
||||
return getEnvironment() == Env.CLIENT ? getClientPlayer() : context.getSender();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void queue(Runnable runnable) {
|
||||
context.enqueueWork(runnable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Env getEnvironment() {
|
||||
return context.getDirection().getReceptionSide() == LogicalSide.CLIENT ? Env.CLIENT : Env.SERVER;
|
||||
}
|
||||
|
||||
private Player getClientPlayer() {
|
||||
return DistExecutor.unsafeCallWhenOn(Dist.CLIENT, () -> ClientNetworkingManager::getClientPlayer);
|
||||
}
|
||||
};
|
||||
transformer.inbound(side, type, buffer, packetContext, (side1, id1, buf1) -> {
|
||||
NetworkReceiver networkReceiver = side == NetworkManager.Side.C2S ? C2S.get(id1) : S2C.get(id1);
|
||||
if (networkReceiver == null) {
|
||||
throw new IllegalArgumentException("Network Receiver not found! " + id1);
|
||||
}
|
||||
networkReceiver.receive(buf1, packetContext);
|
||||
});
|
||||
} else {
|
||||
LOGGER.error("Unknown message ID: " + type);
|
||||
}
|
||||
|
||||
context.setPacketHandled(true);
|
||||
};
|
||||
}
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public static void registerS2CReceiver(ResourceLocation id, List<PacketTransformer> packetTransformers, NetworkReceiver receiver) {
|
||||
LOGGER.info("Registering S2C receiver with id {}", id);
|
||||
S2C.put(id, receiver);
|
||||
PacketTransformer transformer = PacketTransformer.concat(packetTransformers);
|
||||
S2C_TRANSFORMERS.put(id, transformer);
|
||||
}
|
||||
|
||||
public static void registerC2SReceiver(ResourceLocation id, List<PacketTransformer> packetTransformers, NetworkReceiver receiver) {
|
||||
LOGGER.info("Registering C2S receiver with id {}", id);
|
||||
C2S.put(id, receiver);
|
||||
PacketTransformer transformer = PacketTransformer.concat(packetTransformers);
|
||||
C2S_TRANSFORMERS.put(id, transformer);
|
||||
}
|
||||
|
||||
public static boolean canServerReceive(ResourceLocation id) {
|
||||
return serverReceivables.contains(id);
|
||||
}
|
||||
|
||||
public static boolean canPlayerReceive(ServerPlayer player, ResourceLocation id) {
|
||||
return clientReceivables.get(player).contains(id);
|
||||
}
|
||||
|
||||
public static Packet<ClientGamePacketListener> createAddEntityPacket(Entity entity) {
|
||||
return NetworkHooks.getEntitySpawningPacket(entity);
|
||||
}
|
||||
|
||||
static FriendlyByteBuf sendSyncPacket(Map<ResourceLocation, NetworkReceiver> map) {
|
||||
List<ResourceLocation> availableIds = Lists.newArrayList(map.keySet());
|
||||
FriendlyByteBuf packetBuffer = new FriendlyByteBuf(Unpooled.buffer());
|
||||
packetBuffer.writeInt(availableIds.size());
|
||||
for (ResourceLocation availableId : availableIds) {
|
||||
packetBuffer.writeResourceLocation(availableId);
|
||||
}
|
||||
return packetBuffer;
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void loggedIn(PlayerEvent.PlayerLoggedInEvent event) {
|
||||
NetworkManager.sendToPlayer((ServerPlayer) event.getEntity(), SYNC_IDS, sendSyncPacket(C2S));
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void loggedOut(PlayerEvent.PlayerLoggedOutEvent event) {
|
||||
clientReceivables.removeAll(event.getEntity());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,185 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021, 2022 architectury
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
package dev.architectury.platform.forge;
|
||||
|
||||
import dev.architectury.platform.Mod;
|
||||
import dev.architectury.utils.Env;
|
||||
import net.neoforged.api.distmarker.Dist;
|
||||
import net.neoforged.fml.ModContainer;
|
||||
import net.neoforged.fml.ModList;
|
||||
import net.neoforged.fml.loading.FMLEnvironment;
|
||||
import net.neoforged.fml.loading.FMLLoader;
|
||||
import net.neoforged.fml.loading.FMLPaths;
|
||||
import net.neoforged.fml.loading.moddiscovery.ModFileInfo;
|
||||
import net.neoforged.neoforge.client.ConfigScreenHandler;
|
||||
import net.neoforged.neoforgespi.language.IModFileInfo;
|
||||
import net.neoforged.neoforgespi.language.IModInfo;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.net.URL;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class PlatformImpl {
|
||||
private static final Map<String, Mod> mods = new ConcurrentHashMap<>();
|
||||
|
||||
public static Path getGameFolder() {
|
||||
return FMLPaths.GAMEDIR.get();
|
||||
}
|
||||
|
||||
public static Path getConfigFolder() {
|
||||
return FMLPaths.CONFIGDIR.get();
|
||||
}
|
||||
|
||||
public static Path getModsFolder() {
|
||||
return FMLPaths.MODSDIR.get();
|
||||
}
|
||||
|
||||
public static Env getEnvironment() {
|
||||
return Env.fromPlatform(getEnv());
|
||||
}
|
||||
|
||||
public static Dist getEnv() {
|
||||
return FMLEnvironment.dist;
|
||||
}
|
||||
|
||||
public static boolean isModLoaded(String id) {
|
||||
return ModList.get().isLoaded(id);
|
||||
}
|
||||
|
||||
public static Mod getMod(String id) {
|
||||
return mods.computeIfAbsent(id, ModImpl::new);
|
||||
}
|
||||
|
||||
public static Collection<Mod> getMods() {
|
||||
for (IModInfo mod : ModList.get().getMods()) {
|
||||
getMod(mod.getModId());
|
||||
}
|
||||
return mods.values();
|
||||
}
|
||||
|
||||
public static Collection<String> getModIds() {
|
||||
return ModList.get().getMods().stream().map(IModInfo::getModId).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public static boolean isDevelopmentEnvironment() {
|
||||
return !FMLLoader.isProduction();
|
||||
}
|
||||
|
||||
private static class ModImpl implements Mod {
|
||||
private final ModContainer container;
|
||||
private final IModInfo info;
|
||||
|
||||
public ModImpl(String id) {
|
||||
this.container = ModList.get().getModContainerById(id).orElseThrow();
|
||||
this.info = ModList.get().getMods().stream()
|
||||
.filter(modInfo -> Objects.equals(modInfo.getModId(), id))
|
||||
.findAny()
|
||||
.orElseThrow();
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getModId() {
|
||||
return info.getModId();
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getVersion() {
|
||||
return info.getVersion().toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getName() {
|
||||
return info.getDisplayName();
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getDescription() {
|
||||
return info.getDescription();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<String> getLogoFile(int i) {
|
||||
return this.info.getLogoFile();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Path> getFilePaths() {
|
||||
return List.of(getFilePath());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path getFilePath() {
|
||||
return this.info.getOwningFile().getFile().getSecureJar().getRootPath();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Path> findResource(String... path) {
|
||||
return Optional.of(this.info.getOwningFile().getFile().findResource(path)).filter(Files::exists);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<String> getAuthors() {
|
||||
Optional<String> optional = this.info.getConfig().getConfigElement("authors")
|
||||
.map(String::valueOf);
|
||||
return optional.isPresent() ? Collections.singleton(optional.get()) : Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Collection<String> getLicense() {
|
||||
return Collections.singleton(this.info.getOwningFile().getLicense());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<String> getHomepage() {
|
||||
return this.info.getConfig().getConfigElement("displayURL")
|
||||
.map(String::valueOf);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<String> getSources() {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<String> getIssueTracker() {
|
||||
IModFileInfo owningFile = this.info.getOwningFile();
|
||||
if (owningFile instanceof ModFileInfo info) {
|
||||
return Optional.ofNullable(info.getIssueURL())
|
||||
.map(URL::toString);
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerConfigurationScreen(ConfigurationScreenProvider configurationScreenProvider) {
|
||||
container.registerExtensionPoint(ConfigScreenHandler.ConfigScreenFactory.class, () ->
|
||||
new ConfigScreenHandler.ConfigScreenFactory((minecraft, screen) -> configurationScreenProvider.provide(screen)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021, 2022 architectury
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
package dev.architectury.platform.hooks.forge;
|
||||
|
||||
import net.neoforged.bus.api.IEventBus;
|
||||
import net.neoforged.fml.ModContainer;
|
||||
import net.neoforged.fml.ModList;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class EventBusesHooksImpl {
|
||||
public static void whenAvailable(String modId, Consumer<IEventBus> busConsumer) {
|
||||
IEventBus bus = getModEventBus(modId).orElseThrow(() -> new IllegalStateException("Mod '" + modId + "' is not available!"));
|
||||
busConsumer.accept(bus);
|
||||
}
|
||||
|
||||
public static Optional<IEventBus> getModEventBus(String modId) {
|
||||
return ModList.get().getModContainerById(modId)
|
||||
.map(ModContainer::getEventBus);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,426 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021, 2022 architectury
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
package dev.architectury.registry.registries.forge;
|
||||
|
||||
import com.google.common.base.Objects;
|
||||
import com.google.common.base.Suppliers;
|
||||
import com.google.common.collect.HashMultimap;
|
||||
import com.google.common.collect.Multimap;
|
||||
import dev.architectury.impl.RegistrySupplierImpl;
|
||||
import dev.architectury.platform.hooks.forge.EventBusesHooksImpl;
|
||||
import dev.architectury.registry.registries.Registrar;
|
||||
import dev.architectury.registry.registries.RegistrarBuilder;
|
||||
import dev.architectury.registry.registries.RegistrarManager;
|
||||
import dev.architectury.registry.registries.RegistrySupplier;
|
||||
import dev.architectury.registry.registries.options.RegistrarOption;
|
||||
import dev.architectury.registry.registries.options.StandardRegistrarOption;
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.core.registries.BuiltInRegistries;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.neoforged.bus.api.EventPriority;
|
||||
import net.neoforged.bus.api.IEventBus;
|
||||
import net.neoforged.bus.api.SubscribeEvent;
|
||||
import net.neoforged.neoforge.registries.NewRegistryEvent;
|
||||
import net.neoforged.neoforge.registries.RegisterEvent;
|
||||
import net.neoforged.neoforge.registries.RegistryBuilder;
|
||||
import org.apache.commons.lang3.mutable.Mutable;
|
||||
import org.apache.commons.lang3.mutable.MutableObject;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.BooleanSupplier;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class RegistrarManagerImpl {
|
||||
private static final Logger LOGGER = LogManager.getLogger(RegistrarManagerImpl.class);
|
||||
private static final Multimap<RegistryEntryId<?>, Consumer<?>> LISTENERS = HashMultimap.create();
|
||||
|
||||
private static void listen(ResourceKey<?> resourceKey, ResourceLocation id, Consumer<?> listener) {
|
||||
LISTENERS.put(new RegistryEntryId<>(resourceKey, id), listener);
|
||||
}
|
||||
|
||||
public static RegistrarManager.RegistryProvider _get(String modId) {
|
||||
return new RegistryProviderImpl(modId);
|
||||
}
|
||||
|
||||
public static class Data<T> {
|
||||
private boolean registered = false;
|
||||
private final Map<ResourceLocation, Supplier<? extends T>> objects = new LinkedHashMap<>();
|
||||
|
||||
public void register(Registry<T> registry, ResourceLocation location, Mutable<T> object, Supplier<? extends T> reference) {
|
||||
if (!registered) {
|
||||
objects.put(location, () -> {
|
||||
T value = reference.get();
|
||||
object.setValue(value);
|
||||
return value;
|
||||
});
|
||||
} else {
|
||||
ResourceKey<? extends Registry<T>> resourceKey = registry.key();
|
||||
T value = reference.get();
|
||||
Registry.register(registry, location, value);
|
||||
object.setValue(value);
|
||||
|
||||
RegistryEntryId<?> registryEntryId = new RegistryEntryId<>(resourceKey, location);
|
||||
for (Consumer<?> consumer : LISTENERS.get(registryEntryId)) {
|
||||
((Consumer<Object>) consumer).accept(value);
|
||||
}
|
||||
LISTENERS.removeAll(registryEntryId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public record RegistryEntryId<T>(ResourceKey<T> registryKey, ResourceLocation id) {
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Registry Entry [%s / %s]".formatted(registryKey.location(), id);
|
||||
}
|
||||
}
|
||||
|
||||
public static class RegistryProviderImpl implements RegistrarManager.RegistryProvider {
|
||||
private static final Map<ResourceKey<Registry<?>>, Registrar<?>> CUSTOM_REGS = new HashMap<>();
|
||||
private final String modId;
|
||||
private final Supplier<IEventBus> eventBus;
|
||||
private final Map<ResourceKey<? extends Registry<?>>, Data<?>> registry = new HashMap<>();
|
||||
private final Multimap<ResourceKey<Registry<?>>, Consumer<Registrar<?>>> listeners = HashMultimap.create();
|
||||
|
||||
@Nullable
|
||||
private List<Registry<?>> newRegistries = new ArrayList<>();
|
||||
|
||||
public RegistryProviderImpl(String modId) {
|
||||
this.modId = modId;
|
||||
this.eventBus = Suppliers.memoize(() -> {
|
||||
IEventBus eventBus = EventBusesHooksImpl.getModEventBus(modId).orElseThrow(() -> new IllegalStateException("Can't get event bus for mod '" + modId + "' because it was not registered!"));
|
||||
eventBus.register(new EventListener());
|
||||
return eventBus;
|
||||
});
|
||||
}
|
||||
|
||||
private void updateEventBus() {
|
||||
synchronized (eventBus) {
|
||||
// Make sure that the eventbus is setup
|
||||
this.eventBus.get();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> Registrar<T> get(ResourceKey<Registry<T>> registryKey) {
|
||||
updateEventBus();
|
||||
Registry<T> registry = (Registry<T>) BuiltInRegistries.REGISTRY.get(registryKey.location());
|
||||
if (registry != null) {
|
||||
return get(registry);
|
||||
}
|
||||
Registrar<?> customReg = RegistryProviderImpl.CUSTOM_REGS.get(registryKey);
|
||||
if (customReg != null) return (Registrar<T>) customReg;
|
||||
throw new IllegalArgumentException("Registry " + registryKey + " does not exist!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> Registrar<T> get(Registry<T> registry) {
|
||||
updateEventBus();
|
||||
return new RegistrarImpl<>(modId, this.registry, registry);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void forRegistry(ResourceKey<Registry<T>> key, Consumer<Registrar<T>> consumer) {
|
||||
this.listeners.put((ResourceKey<Registry<?>>) (ResourceKey<? extends Registry<?>>) key,
|
||||
(Consumer<Registrar<?>>) (Consumer<? extends Registrar<?>>) consumer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> RegistrarBuilder<T> builder(Class<T> type, ResourceLocation registryId) {
|
||||
return new RegistryBuilderWrapper<>(this, new RegistryBuilder<>(ResourceKey.createRegistryKey(registryId)));
|
||||
}
|
||||
|
||||
public class EventListener {
|
||||
@SubscribeEvent
|
||||
public void handleEvent(RegisterEvent event) {
|
||||
for (Map.Entry<ResourceKey<? extends Registry<?>>, Data<?>> typeDataEntry : RegistryProviderImpl.this.registry.entrySet()) {
|
||||
if (typeDataEntry.getKey().equals(event.getRegistryKey())) {
|
||||
//noinspection rawtypes
|
||||
registerFor(event, (ResourceKey) typeDataEntry.getKey(), typeDataEntry.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public <T> void registerFor(RegisterEvent event, ResourceKey<? extends Registry<T>> resourceKey, Data<T> data) {
|
||||
event.register(resourceKey, registry -> {
|
||||
data.registered = true;
|
||||
|
||||
for (Map.Entry<ResourceLocation, Supplier<? extends T>> entry : data.objects.entrySet()) {
|
||||
ResourceLocation location = entry.getKey();
|
||||
T value = entry.getValue().get();
|
||||
registry.register(location, value);
|
||||
|
||||
RegistryEntryId<?> registryEntryId = new RegistryEntryId<>(resourceKey, location);
|
||||
for (Consumer<?> consumer : LISTENERS.get(registryEntryId)) {
|
||||
((Consumer<Object>) consumer).accept(value);
|
||||
}
|
||||
LISTENERS.removeAll(registryEntryId);
|
||||
}
|
||||
|
||||
data.objects.clear();
|
||||
Registrar<?> archRegistry = get(event.getRegistry());
|
||||
|
||||
for (Map.Entry<ResourceKey<Registry<?>>, Consumer<Registrar<?>>> entry : listeners.entries()) {
|
||||
if (entry.getKey().location().equals(resourceKey.location())) {
|
||||
entry.getValue().accept(archRegistry);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@SubscribeEvent(priority = EventPriority.LOWEST)
|
||||
public void handleEventPost(RegisterEvent event) {
|
||||
Registrar<?> archRegistry = get(event.getRegistry());
|
||||
|
||||
List<RegistryEntryId<?>> toRemove = new ArrayList<>();
|
||||
|
||||
for (Map.Entry<RegistryEntryId<?>, Collection<Consumer<?>>> entry : LISTENERS.asMap().entrySet()) {
|
||||
if (entry.getKey().registryKey.equals(event.getRegistryKey())) {
|
||||
if (archRegistry.contains(entry.getKey().id)) {
|
||||
Object value = archRegistry.get(entry.getKey().id);
|
||||
for (Consumer<?> consumer : entry.getValue()) {
|
||||
((Consumer<Object>) consumer).accept(value);
|
||||
}
|
||||
toRemove.add(entry.getKey());
|
||||
} else {
|
||||
LOGGER.warn("Registry entry listened {} was not realized!", entry.getKey());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (RegistryEntryId<?> id : toRemove) {
|
||||
LISTENERS.removeAll(id);
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void handleEvent(NewRegistryEvent event) {
|
||||
if (newRegistries != null) {
|
||||
for (Registry<?> registry : newRegistries) {
|
||||
event.register(registry);
|
||||
}
|
||||
newRegistries = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class RegistryBuilderWrapper<T> implements RegistrarBuilder<T> {
|
||||
private final RegistryProviderImpl provider;
|
||||
private final RegistryBuilder<T> builder;
|
||||
private boolean syncToClients = false;
|
||||
|
||||
public RegistryBuilderWrapper(RegistryProviderImpl provider, RegistryBuilder<T> builder) {
|
||||
this.provider = provider;
|
||||
this.builder = builder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Registrar<T> build() {
|
||||
builder.sync(syncToClients);
|
||||
if (provider.newRegistries == null) {
|
||||
throw new IllegalStateException("Cannot create registries when registries are already aggregated!");
|
||||
}
|
||||
var registry = builder.create();
|
||||
var registrar = provider.get(registry);
|
||||
provider.newRegistries.add(registry);
|
||||
//noinspection rawtypes
|
||||
RegistryProviderImpl.CUSTOM_REGS.put((ResourceKey) registrar.key(), registrar);
|
||||
return registrar;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RegistrarBuilder<T> option(RegistrarOption option) {
|
||||
if (option == StandardRegistrarOption.SYNC_TO_CLIENTS) {
|
||||
this.syncToClients = true;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
public static class RegistrarImpl<T> implements Registrar<T> {
|
||||
private final String modId;
|
||||
private final Registry<T> delegate;
|
||||
private final Map<ResourceKey<? extends Registry<?>>, Data<?>> registry;
|
||||
|
||||
public RegistrarImpl(String modId, Map<ResourceKey<? extends Registry<?>>, Data<?>> registry, Registry<T> delegate) {
|
||||
this.modId = modId;
|
||||
this.registry = registry;
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RegistrySupplier<T> delegate(ResourceLocation id) {
|
||||
Supplier<T> value = Suppliers.memoize(() -> get(id));
|
||||
return asSupplier(id, this, () -> contains(id), value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <E extends T> RegistrySupplier<E> register(ResourceLocation id, Supplier<E> supplier) {
|
||||
Data<T> data = (Data<T>) registry.computeIfAbsent(key(), type -> new Data<>());
|
||||
Mutable<T> object = new MutableObject<>();
|
||||
data.register(delegate, id, object, supplier);
|
||||
return asSupplier(id, (Registrar<E>) this, () -> object.getValue() != null, object::getValue);
|
||||
}
|
||||
|
||||
private <E extends T> RegistrySupplier<E> asSupplier(ResourceLocation id, Registrar<E> registrar, BooleanSupplier isPresent, Supplier<T> object) {
|
||||
return new RegistrySupplierImpl<E>() {
|
||||
@Nullable
|
||||
Holder<E> holder = null;
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Holder<E> getHolder() {
|
||||
if (holder != null) return holder;
|
||||
return holder = registrar.getHolder(getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public RegistrarManager getRegistrarManager() {
|
||||
return RegistrarManager.get(modId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Registrar<E> getRegistrar() {
|
||||
return registrar;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation getRegistryId() {
|
||||
return delegate.key().location();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPresent() {
|
||||
return isPresent.getAsBoolean();
|
||||
}
|
||||
|
||||
@Override
|
||||
public E get() {
|
||||
E value = (E) object.get();
|
||||
if (value == null) {
|
||||
throw new NullPointerException("Value missing: " + this.getId() + "@" + getRegistryId());
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@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() + "@" + id.toString();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public 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 t) {
|
||||
return delegate.getResourceKey(t);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public T get(ResourceLocation id) {
|
||||
return delegate.get(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T byRawId(int rawId) {
|
||||
return delegate.byId(rawId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(ResourceLocation resourceLocation) {
|
||||
return delegate.keySet().contains(resourceLocation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsValue(T t) {
|
||||
return delegate.getResourceKey(t).isPresent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<ResourceLocation> getIds() {
|
||||
return delegate.keySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Map.Entry<ResourceKey<T>, T>> entrySet() {
|
||||
return delegate.entrySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceKey<? extends Registry<T>> key() {
|
||||
return delegate.key();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Holder<T> getHolder(ResourceKey<T> key) {
|
||||
return delegate.getHolder(key).orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<T> iterator() {
|
||||
return delegate.iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void listen(ResourceLocation id, Consumer<T> callback) {
|
||||
if (contains(id)) {
|
||||
callback.accept(get(id));
|
||||
} else {
|
||||
RegistrarManagerImpl.listen(key(), id, callback);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
35
neoforge/src/main/resources/META-INF/mods.toml
Normal file
35
neoforge/src/main/resources/META-INF/mods.toml
Normal file
@@ -0,0 +1,35 @@
|
||||
modLoader = "javafml"
|
||||
loaderVersion = "[1,)"
|
||||
issueTrackerURL = "https://github.com/shedaniel/architectury/issues"
|
||||
license = "GNU LGPLv3"
|
||||
|
||||
[[mods]]
|
||||
modId = "architectury"
|
||||
version = "${version}"
|
||||
displayName = "Architectury"
|
||||
authors = "shedaniel"
|
||||
description = '''
|
||||
A intermediary api aimed to ease developing multiplatform mods.
|
||||
'''
|
||||
logoFile = "icon.png"
|
||||
license = "LGPL-3"
|
||||
|
||||
[[dependencies.architectury]]
|
||||
modId = "minecraft"
|
||||
mandatory = true
|
||||
versionRange = "[1.20.2,)"
|
||||
ordering = "NONE"
|
||||
side = "BOTH"
|
||||
|
||||
[[dependencies.architectury]]
|
||||
modId = "neoforge"
|
||||
mandatory = true
|
||||
versionRange = "[20.2.58,)"
|
||||
ordering = "NONE"
|
||||
side = "BOTH"
|
||||
|
||||
[[mixins]]
|
||||
config = "architectury.mixins.json"
|
||||
|
||||
[[mixins]]
|
||||
config = "architectury-common.mixins.json"
|
||||
BIN
neoforge/src/main/resources/icon.png
Normal file
BIN
neoforge/src/main/resources/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 150 KiB |
6
neoforge/src/main/resources/pack.mcmeta
Normal file
6
neoforge/src/main/resources/pack.mcmeta
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"pack": {
|
||||
"description": "Architectury",
|
||||
"pack_format": 6
|
||||
}
|
||||
}
|
||||
@@ -14,8 +14,11 @@ if (JavaVersion.current().ordinal() + 1 < 17) {
|
||||
include("common")
|
||||
include("fabric")
|
||||
//include("forge")
|
||||
//include("minecraftforge")
|
||||
//include("neoforge")
|
||||
include("testmod-common")
|
||||
include("testmod-fabric")
|
||||
//include("testmod-forge")
|
||||
//include("testmod-neoforge")
|
||||
|
||||
rootProject.name = "architectury"
|
||||
|
||||
@@ -8,7 +8,7 @@ loom {
|
||||
|
||||
mods {
|
||||
forge {
|
||||
sourceSet project(":forge").sourceSets.main
|
||||
sourceSet project(":minecraftforge").sourceSets.main
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +32,8 @@ configurations {
|
||||
dependencies {
|
||||
forge "net.minecraftforge:forge:${gradle.rootProject.architectury.minecraft}-${rootProject.forge_version}"
|
||||
|
||||
implementation project(path: ":forge", configuration: "namedElements")
|
||||
implementation project(path: ":minecraftforge", configuration: "namedElements")
|
||||
common(project(path: ":common", configuration: "namedElements")) { transitive false }
|
||||
common(project(path: ":testmod-common", configuration: "namedElements")) { transitive false }
|
||||
common(project(path: ":forge", configuration: "namedElements")) { transitive false }
|
||||
}
|
||||
|
||||
44
testmod-neoforge/build.gradle
Normal file
44
testmod-neoforge/build.gradle
Normal file
@@ -0,0 +1,44 @@
|
||||
plugins {
|
||||
id "com.github.johnrengelman.shadow" version "7.0.0"
|
||||
id "com.matthewprenger.cursegradle"
|
||||
}
|
||||
|
||||
loom {
|
||||
accessWidenerPath = project(":common").loom.accessWidenerPath
|
||||
|
||||
mods {
|
||||
forge {
|
||||
sourceSet project(":neoforge").sourceSets.main
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
architectury {
|
||||
platformSetupLoomIde()
|
||||
neoForge {
|
||||
platformPackage = "forge"
|
||||
remapForgeLike "net/minecraftforge/common/extensions/IForgeItem", "net/neoforged/neoforge/common/extensions/IItemExtension"
|
||||
remapForgeLike "net/minecraftforge/client/event/TextureStitchEvent\$Post", "net/neoforged/neoforge/client/event/TextureAtlasStitchedEvent"
|
||||
remapForgeLike "net/minecraftforge/fluids/ForgeFlowingFluid", "net/neoforged/neoforge/fluids/BaseFlowingFluid"
|
||||
remapForgeLike "net/minecraftforge/fluids/ForgeFlowingFluid\$Properties", "net/neoforged/neoforge/fluids/BaseFlowingFluid\$Properties"
|
||||
remapForgeLike "net/minecraftforge/common/ForgeHooks", "net/neoforged/neoforge/common/CommonHooks"
|
||||
}
|
||||
}
|
||||
|
||||
configurations {
|
||||
common
|
||||
forgeLike
|
||||
compileClasspath.extendsFrom common, forgeLike
|
||||
runtimeClasspath.extendsFrom common, forgeLike
|
||||
developmentNeoForge.extendsFrom common
|
||||
developmentForgeLike.extendsFrom forgeLike
|
||||
}
|
||||
|
||||
dependencies {
|
||||
neoForge "net.neoforged:neoforge:${rootProject.neoforge_version}"
|
||||
|
||||
implementation(project(path: ":neoforge", configuration: "namedElements")) { transitive false }
|
||||
common(project(path: ":common", configuration: "namedElements")) { transitive false }
|
||||
common(project(path: ":testmod-common", configuration: "namedElements")) { transitive false }
|
||||
forgeLike(project(path: ":forge", configuration: "namedElements")) { transitive false }
|
||||
}
|
||||
1
testmod-neoforge/gradle.properties
Normal file
1
testmod-neoforge/gradle.properties
Normal file
@@ -0,0 +1 @@
|
||||
loom.platform=neoforge
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021, 2022 architectury
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
package dev.architectury.test.forge;
|
||||
|
||||
import dev.architectury.test.TestMod;
|
||||
import net.neoforged.fml.common.Mod;
|
||||
|
||||
@Mod(TestMod.MOD_ID)
|
||||
public class TestModForge {
|
||||
public TestModForge() {
|
||||
TestMod.initialize();
|
||||
}
|
||||
}
|
||||
14
testmod-neoforge/src/main/resources/META-INF/mods.toml
Normal file
14
testmod-neoforge/src/main/resources/META-INF/mods.toml
Normal file
@@ -0,0 +1,14 @@
|
||||
modLoader = "javafml"
|
||||
loaderVersion = "[1,)"
|
||||
issueTrackerURL = "https://github.com/shedaniel/architectury/issues"
|
||||
license = "LGPL-3"
|
||||
|
||||
[[mods]]
|
||||
modId = "architectury_test"
|
||||
version = "${file.jarVersion}"
|
||||
displayName = "Architectury Test"
|
||||
authors = "shedaniel"
|
||||
description = '''
|
||||
A intermediary api aimed to ease developing multiplatform mods.
|
||||
'''
|
||||
license = "LGPL-3"
|
||||
6
testmod-neoforge/src/main/resources/pack.mcmeta
Normal file
6
testmod-neoforge/src/main/resources/pack.mcmeta
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"pack": {
|
||||
"description": "Architectury Test",
|
||||
"pack_format": 6
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user