[VERY VERY VERY BAD IDEA]

This commit is contained in:
Brian Neumann-Fopiano committed 2026-09-20 04:24:42 -04:00
1 parent f0e7fea13b
commit 2fa0853e42
892 files changed
+13482 -53554

No files matched your search

+25 -1
View File
@@ -76,7 +76,11 @@ java {
}
}
ext.nativeSourceLoader = 'neoforge'
apply from: file('../../gradle/native-minecraft-sources.gradle')
sourceSets {
modLibraries
main {
java {
srcDir '../modded-common/src/main/java'
@@ -94,6 +98,8 @@ sourceSets {
}
}
repositories {
mavenCentral()
maven {
@@ -176,10 +182,26 @@ dependencies {
}
}
def developmentModLibraries = configurations.devBundle.incoming.artifactView {
componentFilter { identifier ->
identifier instanceof org.gradle.api.artifacts.component.ProjectComponentIdentifier
|| (identifier instanceof org.gradle.api.artifacts.component.ModuleComponentIdentifier
&& (identifier.group == 'art.arcane' || identifier.group.startsWith('com.github.VolmitSoftware')))
}
}.files
def stageDevelopmentModLibraries = tasks.register('stageDevelopmentModLibraries', Sync) {
dependsOn(developmentModLibraries)
from({ developmentModLibraries.collect { File artifact -> zipTree(artifact) } })
into(layout.buildDirectory.dir('mod-libraries'))
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
exclude('META-INF/MANIFEST.MF', 'module-info.class', 'META-INF/versions/**')
}
sourceSets.modLibraries.output.classesDirs.setFrom(stageDevelopmentModLibraries)
neoForge {
version = neoForgeVersion
accessTransformers.from('src/main/resources/META-INF/accesstransformer.cfg')
accessTransformers.from(art.arcane.volmit.packaging.NativeAccessRules.prepare(nativeSourceImplementation, "neoforge", layout.buildDirectory.dir("native-access").get().asFile))
runs {
client {
@@ -212,6 +234,7 @@ neoForge {
mods {
irisworldgen {
sourceSet(sourceSets.main)
sourceSet(sourceSets.modLibraries)
}
}
@@ -228,6 +251,7 @@ tasks.named('compileJava', JavaCompile).configure {
tasks.named('test').configure {
useJUnitPlatform()
classpath = classpath.minus(developmentModLibraries).plus(sourceSets.modLibraries.output)
}
processResources {
@@ -1,184 +1,29 @@
/*
* Iris is a World Generator for Minecraft Servers
* Copyright (c) 2026 Arcane Arts (Volmit Software)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package art.arcane.iris.neoforge;
import art.arcane.iris.modded.IrisModdedChunkGenerator;
import art.arcane.iris.modded.ModdedBlockBreakHandler;
import art.arcane.iris.modded.ModdedEngineBootstrap;
import art.arcane.iris.modded.ModdedForcedDatapack;
import art.arcane.iris.modded.command.IrisModdedCommands;
import art.arcane.iris.modded.command.ModdedWandService;
import com.mojang.serialization.MapCodec;
import net.minecraft.core.registries.Registries;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.server.packs.PackType;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.chunk.ChunkGenerator;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.bus.api.EventPriority;
import art.arcane.iris.modded.ModdedLifecycleCallbacks;
import art.arcane.iris.modded.service.ModdedTreeFellerService;
import art.arcane.volmlib.nativelib.modded.NativeLoaderOptions;
import art.arcane.volmlib.nativelib.minecraft26_2.modded.NativeChunkGeneratorDefinition;
import art.arcane.volmlib.nativelib.minecraft26_2.neoforge.NativeNeoForgeLoader;
import art.arcane.volmlib.nativelib.minecraft26_2.neoforge.NativeNeoForgeBootstrap;
import net.neoforged.bus.api.IEventBus;
import net.neoforged.fml.common.Mod;
import net.neoforged.fml.loading.FMLEnvironment;
import net.neoforged.fml.loading.FMLLoader;
import net.neoforged.neoforge.common.NeoForge;
import net.neoforged.neoforge.common.util.BlockSnapshot;
import net.neoforged.neoforge.event.AddPackFindersEvent;
import net.neoforged.neoforge.event.RegisterCommandsEvent;
import net.neoforged.neoforge.event.entity.player.PlayerInteractEvent;
import net.neoforged.neoforge.event.level.BlockDropsEvent;
import net.neoforged.neoforge.event.level.BlockEvent;
import net.neoforged.neoforge.event.level.LevelEvent;
import net.neoforged.neoforge.event.level.block.BreakBlockEvent;
import net.neoforged.neoforge.event.server.ServerAboutToStartEvent;
import net.neoforged.neoforge.event.server.ServerStartedEvent;
import net.neoforged.neoforge.event.server.ServerStartingEvent;
import net.neoforged.neoforge.event.server.ServerStoppingEvent;
import net.neoforged.neoforge.event.tick.ServerTickEvent;
import net.neoforged.neoforge.registries.DeferredRegister;
import net.neoforged.neoforge.server.permission.events.PermissionGatherEvent;
import java.util.List;
@Mod("irisworldgen")
public final class IrisNeoForgeBootstrap {
public IrisNeoForgeBootstrap(IEventBus modBus) {
ModdedEngineBootstrap.bootCommon(new NeoForgeModdedLoader(), "NeoForge " + FMLLoader.getCurrent().getVersionInfo().neoForgeVersion(), () -> {
DeferredRegister<MapCodec<? extends ChunkGenerator>> chunkGenerators = DeferredRegister.create(Registries.CHUNK_GENERATOR, "irisworldgen");
chunkGenerators.register("iris", () -> IrisModdedChunkGenerator.CODEC);
chunkGenerators.register(modBus);
});
modBus.addListener((AddPackFindersEvent event) -> {
if (event.getPackType() == PackType.SERVER_DATA) {
event.addRepositorySource(ModdedForcedDatapack.repositorySource());
}
});
NativeNeoForgeLoader loader = new NativeNeoForgeLoader(new NativeLoaderOptions(
"irisworldgen", "treefeller", ModdedTreeFellerService::runBreakProbe));
NativeChunkGeneratorDefinition generator = IrisModdedChunkGenerator.DEFINITION;
ModdedEngineBootstrap.bootCommon(loader, "NeoForge " + FMLLoader.getCurrent().getVersionInfo().neoForgeVersion(),
() -> NativeNeoForgeBootstrap.registerGenerator(modBus, generator));
NeoForgeProtocolNetworking.register(modBus);
if (FMLEnvironment.getDist() == Dist.CLIENT) {
if (loader.clientEnvironment()) {
IrisNeoForgeClient.init(modBus);
}
NeoForge.EVENT_BUS.addListener((ServerAboutToStartEvent event) -> ModdedEngineBootstrap.serverAboutToStart(event.getServer()));
NeoForge.EVENT_BUS.addListener((ServerStartingEvent event) -> ModdedEngineBootstrap.start(event.getServer()));
NeoForge.EVENT_BUS.addListener((ServerStartedEvent event) -> ModdedEngineBootstrap.serverStarted(event.getServer()));
NeoForge.EVENT_BUS.addListener((ServerStoppingEvent event) -> ModdedEngineBootstrap.stop());
NeoForge.EVENT_BUS.addListener((LevelEvent.Load event) -> {
if (event.getLevel() instanceof ServerLevel level) {
ModdedEngineBootstrap.levelLoaded(level);
}
});
NeoForge.EVENT_BUS.addListener((LevelEvent.Unload event) -> {
if (event.getLevel() instanceof ServerLevel level) {
ModdedEngineBootstrap.levelUnloaded(level);
}
});
NeoForge.EVENT_BUS.addListener((RegisterCommandsEvent event) -> IrisModdedCommands.register(event.getDispatcher()));
NeoForge.EVENT_BUS.addListener((PermissionGatherEvent.Nodes event) ->
event.addNodes(NeoForgeModdedLoader.TREE_FELLER_PERMISSION));
// LOWEST so every other mod has already had its say about cancelling the break before Iris records
// provenance for it.
NeoForge.EVENT_BUS.addListener(
EventPriority.LOWEST,
false,
(BreakBlockEvent event) -> {
if (event.getLevel() instanceof ServerLevel level
&& event.getPlayer() instanceof ServerPlayer player) {
ModdedBlockBreakHandler.prepare(level, player, event.getPos(), event.getState());
}
}
);
// Parity with the Fabric PlayerBlockBreakEvents.CANCELED hook: drop the prepared entry when the break
// never happens. It only observes cancellations from listeners registered before it at LOWEST; the
// 1-tick sweeper ModdedBlockBreakHandler.prepare schedules covers every other case.
NeoForge.EVENT_BUS.addListener(
EventPriority.LOWEST,
true,
(BreakBlockEvent event) -> {
if (event.isCanceled() && event.getLevel() instanceof ServerLevel level) {
ModdedBlockBreakHandler.cancel(level, event.getPos());
}
}
);
NeoForge.EVENT_BUS.addListener(
EventPriority.LOWEST,
false,
(BlockEvent.EntityPlaceEvent event) -> {
if (!(event instanceof BlockEvent.EntityMultiPlaceEvent)
&& event.getLevel() instanceof ServerLevel level) {
ModdedBlockBreakHandler.clearPlacedProvenance(level, event.getPos());
}
}
);
NeoForge.EVENT_BUS.addListener(
EventPriority.LOWEST,
false,
(BlockEvent.EntityMultiPlaceEvent event) -> {
for (BlockSnapshot snapshot : event.getReplacedBlockSnapshots()) {
if (snapshot.getLevel() instanceof ServerLevel level) {
ModdedBlockBreakHandler.clearPlacedProvenance(level, snapshot.getPos());
}
}
}
);
NeoForge.EVENT_BUS.addListener((BlockDropsEvent event) -> {
if (!(event.getBreaker() instanceof Player)) {
return;
}
ServerLevel level = event.getLevel();
ModdedBlockBreakHandler.Result result = ModdedBlockBreakHandler.complete(level, event.getPos(), event.getState());
List<ItemStack> vanillaDrops = event.getDrops().stream()
.map(ItemEntity::getItem)
.toList();
if (result.routeCombinedDrops(vanillaDrops)) {
event.getDrops().clear();
return;
}
if (result.replaceVanillaDrops()) {
event.getDrops().clear();
}
for (ItemStack stack : result.drops()) {
ItemEntity item = ModdedBlockBreakHandler.createDrop(level, event.getPos(), stack);
if (item != null) {
event.getDrops().add(item);
}
}
});
NeoForge.EVENT_BUS.addListener((PlayerInteractEvent.LeftClickBlock event) -> {
if (ModdedWandService.attackBlock(event.getEntity(), event.getLevel(), event.getHand(), event.getPos())) {
event.setCanceled(true);
}
});
NeoForge.EVENT_BUS.addListener((PlayerInteractEvent.RightClickBlock event) -> {
if (ModdedWandService.useBlock(event.getEntity(), event.getLevel(), event.getHand(), event.getPos())) {
event.setCanceled(true);
event.setCancellationResult(InteractionResult.SUCCESS);
}
});
NeoForge.EVENT_BUS.addListener((ServerTickEvent.Post event) -> {
ModdedEngineBootstrap.tick(event.getServer());
ModdedWandService.serverTick(event.getServer());
});
NativeNeoForgeBootstrap.install(modBus, loader, ModdedLifecycleCallbacks.create());
}
}
@@ -19,43 +19,18 @@
package art.arcane.iris.neoforge;
import art.arcane.iris.client.IrisClient;
import art.arcane.volmlib.nativelib.minecraft26_2.neoforge.NativeNeoForgeClientHooks;
import art.arcane.iris.client.IrisClientHud;
import art.arcane.iris.client.IrisClientKeybinds;
import art.arcane.iris.modded.ModdedIrisPayload;
import art.arcane.iris.modded.ModdedProtocolDefinition;
import art.arcane.volmlib.nativelib.minecraft26_2.neoforge.NativeNeoForgeProtocolNetworking;
import net.neoforged.bus.api.IEventBus;
import net.neoforged.neoforge.client.event.ClientPlayerNetworkEvent;
import net.neoforged.neoforge.client.event.ClientTickEvent;
import net.neoforged.neoforge.client.event.RegisterGuiLayersEvent;
import net.neoforged.neoforge.client.event.RegisterKeyMappingsEvent;
import net.neoforged.neoforge.client.network.ClientPacketDistributor;
import net.neoforged.neoforge.common.NeoForge;
import net.neoforged.neoforge.network.registration.PayloadRegistrar;
public final class IrisNeoForgeClient {
private IrisNeoForgeClient() {
}
public static void registerBidirectional(PayloadRegistrar registrar) {
registrar.playBidirectional(ModdedIrisPayload.TYPE, ModdedIrisPayload.STREAM_CODEC,
NeoForgeProtocolNetworking::onInbound,
(payload, context) -> context.enqueueWork(() -> IrisClient.onInbound(payload.data())));
}
public static void init(IEventBus modBus) {
IrisClient.bindSender(frame -> ClientPacketDistributor.sendToServer(new ModdedIrisPayload(frame)));
modBus.addListener((RegisterGuiLayersEvent event) ->
event.registerAboveAll(IrisClient.HUD_ELEMENT_ID, (graphics, delta) -> IrisClientHud.render(graphics)));
modBus.addListener((RegisterKeyMappingsEvent event) -> {
event.register(IrisClientKeybinds.TOGGLE_HUD);
event.register(IrisClientKeybinds.OPEN_MAP);
event.register(IrisClientKeybinds.TOGGLE_WHAT);
});
NeoForge.EVENT_BUS.addListener((ClientPlayerNetworkEvent.LoggingIn event) -> IrisClient.onWorldJoin());
NeoForge.EVENT_BUS.addListener((ClientPlayerNetworkEvent.LoggingOut event) -> IrisClient.onDisconnect());
NeoForge.EVENT_BUS.addListener((ClientTickEvent.Post event) -> {
IrisClient.tick();
IrisClientHud.tick();
IrisClientKeybinds.pollToggle();
});
IrisClient.bindSender(frame -> NativeNeoForgeProtocolNetworking.sendClient(ModdedProtocolDefinition.PROTOCOL, frame));
NativeNeoForgeClientHooks.install(modBus, IrisClientHud.binding(), IrisClient::onWorldJoin, IrisClient::onDisconnect);
}
}
@@ -1,125 +0,0 @@
/*
* Iris is a World Generator for Minecraft Servers
* Copyright (c) 2026 Arcane Arts (Volmit Software)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package art.arcane.iris.neoforge;
import art.arcane.iris.modded.ModdedLoader;
import art.arcane.iris.modded.service.ModdedTreeFellerService;
import net.minecraft.commands.Commands;
import net.minecraft.core.BlockPos;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.level.block.state.BlockState;
import net.neoforged.neoforge.common.NeoForge;
import net.neoforged.neoforge.event.level.LevelEvent;
import net.neoforged.neoforge.event.level.block.BreakBlockEvent;
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.neoforge.server.ServerLifecycleHooks;
import net.neoforged.neoforge.server.permission.PermissionAPI;
import net.neoforged.neoforge.server.permission.nodes.PermissionNode;
import net.neoforged.neoforge.server.permission.nodes.PermissionTypes;
import net.neoforged.neoforgespi.language.IModFileInfo;
import java.io.File;
import java.nio.file.Path;
public final class NeoForgeModdedLoader implements ModdedLoader {
public static final PermissionNode<Boolean> TREE_FELLER_PERMISSION = new PermissionNode<>(
"irisworldgen",
"treefeller",
PermissionTypes.BOOLEAN,
(player, playerId, contexts) ->
player != null && Commands.LEVEL_GAMEMASTERS.check(player.permissions())
);
@Override
public String platformName() {
return "neoforge";
}
@Override
public String minecraftVersion() {
return FMLLoader.getCurrent().getVersionInfo().mcVersion();
}
@Override
public String modVersion() {
return ModList.get().getModContainerById("irisworldgen")
.map((net.neoforged.fml.ModContainer container) -> container.getModInfo().getVersion().toString())
.orElse("unknown");
}
@Override
public MinecraftServer currentServer() {
return ServerLifecycleHooks.getCurrentServer();
}
@Override
public void invalidateLevelCache(MinecraftServer server) {
server.markWorldsDirty();
}
@Override
public void fireDynamicLevelLoad(MinecraftServer server, ServerLevel level) {
NeoForge.EVENT_BUS.post(new LevelEvent.Load(level));
}
@Override
public void fireDynamicLevelUnload(MinecraftServer server, ServerLevel level) {
NeoForge.EVENT_BUS.post(new LevelEvent.Unload(level));
}
@Override
public boolean clientEnvironment() {
return FMLEnvironment.getDist().isClient();
}
@Override
public Path configDir() {
return FMLPaths.CONFIGDIR.get();
}
@Override
public File modJar() {
IModFileInfo info = ModList.get().getModFileById("irisworldgen");
return info == null ? null : info.getFile().getFilePath().toFile();
}
@Override
public boolean hasTreeFellerPermission(ServerPlayer player) {
return PermissionAPI.getPermission(player, TREE_FELLER_PERMISSION);
}
@Override
public boolean canTreeFellerBreak(
ServerLevel level,
ServerPlayer player,
BlockPos position,
BlockState state
) {
return ModdedTreeFellerService.runBreakProbe(() -> {
BreakBlockEvent event = new BreakBlockEvent(level, position, state, player);
NeoForge.EVENT_BUS.post(event);
return !event.isCanceled();
});
}
}
@@ -1,82 +1,20 @@
/*
* Iris is a World Generator for Minecraft Servers
* Copyright (c) 2026 Arcane Arts (Volmit Software)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package art.arcane.iris.neoforge;
import art.arcane.iris.modded.ModdedIrisPayload;
import art.arcane.iris.modded.ModdedProtocolChannel;
import art.arcane.iris.modded.ModdedProtocolDefinition;
import art.arcane.iris.modded.ModdedProtocolHandler;
import net.minecraft.server.level.ServerPlayer;
import net.neoforged.api.distmarker.Dist;
import art.arcane.volmlib.nativelib.minecraft26_2.neoforge.NativeNeoForgeProtocolNetworking;
import art.arcane.volmlib.nativelib.minecraft26_2.modded.NativeProtocolCallbacks;
import art.arcane.iris.client.IrisClient;
import net.neoforged.bus.api.IEventBus;
import net.neoforged.fml.loading.FMLEnvironment;
import net.neoforged.neoforge.common.NeoForge;
import net.neoforged.neoforge.common.extensions.ICommonPacketListener;
import net.neoforged.neoforge.event.entity.player.PlayerEvent;
import net.neoforged.neoforge.network.PacketDistributor;
import net.neoforged.neoforge.network.event.RegisterPayloadHandlersEvent;
import net.neoforged.neoforge.network.handling.IPayloadContext;
import net.neoforged.neoforge.network.registration.PayloadRegistrar;
public final class NeoForgeProtocolNetworking {
private NeoForgeProtocolNetworking() {
}
public static void register(IEventBus modBus) {
modBus.addListener((RegisterPayloadHandlersEvent event) -> onRegisterPayloads(event));
NeoForge.EVENT_BUS.addListener((PlayerEvent.PlayerLoggedInEvent event) -> {
if (event.getEntity() instanceof ServerPlayer player) {
ModdedProtocolHandler.onPlayerJoin(player);
}
});
NeoForge.EVENT_BUS.addListener((PlayerEvent.PlayerLoggedOutEvent event) -> {
if (event.getEntity() instanceof ServerPlayer player) {
ModdedProtocolHandler.onPlayerDisconnect(player);
}
});
ModdedProtocolHandler.bindChannel(new NeoForgeProtocolChannel());
}
private static void onRegisterPayloads(RegisterPayloadHandlersEvent event) {
PayloadRegistrar registrar = event.registrar("1").optional();
if (FMLEnvironment.getDist() == Dist.CLIENT) {
IrisNeoForgeClient.registerBidirectional(registrar);
} else {
registrar.playBidirectional(ModdedIrisPayload.TYPE, ModdedIrisPayload.STREAM_CODEC,
NeoForgeProtocolNetworking::onInbound);
}
}
static void onInbound(ModdedIrisPayload payload, IPayloadContext context) {
if (context.player() instanceof ServerPlayer player) {
ModdedProtocolHandler.onInbound(player, payload.data());
}
}
private static final class NeoForgeProtocolChannel implements ModdedProtocolChannel {
@Override
public boolean canReceive(ServerPlayer player) {
return ((ICommonPacketListener) player.connection).hasChannel(ModdedIrisPayload.TYPE);
}
@Override
public void send(ServerPlayer player, ModdedIrisPayload payload) {
PacketDistributor.sendToPlayer(player, payload);
}
NativeProtocolCallbacks callbacks = new NativeProtocolCallbacks(ModdedProtocolHandler::onInbound,
ModdedProtocolHandler::onPlayerJoin, ModdedProtocolHandler::onPlayerDisconnect);
ModdedProtocolHandler.bindChannel(NativeNeoForgeProtocolNetworking.register(modBus,
ModdedProtocolDefinition.PROTOCOL, callbacks, IrisClient::onInbound));
}
}
@@ -1,3 +0,0 @@
public net.minecraft.server.MinecraftServer levels
public net.minecraft.server.MinecraftServer executor
public net.minecraft.server.MinecraftServer storageSource
@@ -4,10 +4,10 @@ license = "GPL-3.0"
issueTrackerURL = "https://github.com/VolmitSoftware/Iris/issues"
[[mixins]]
config = "irisworldgen.entity.mixins.json"
config = "volmlib.entity.mixins.json"
[[mixins]]
config = "irisworldgen.client.mixins.json"
config = "volmlib.client.mixins.json"
[[accessTransformers]]
file = "META-INF/accesstransformer.cfg"