[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

@@ -1,31 +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.forge;
import art.arcane.iris.client.IrisClient;
import net.minecraftforge.event.network.CustomPayloadEvent;
public final class ForgeClientProtocol {
private ForgeClientProtocol() {
}
public static void handleInbound(CustomPayloadEvent.Context context, byte[] data) {
context.enqueueWork(() -> IrisClient.onInbound(data));
}
}
@@ -1,131 +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.forge;
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.minecraftforge.common.util.Result;
import net.minecraftforge.event.level.BlockEvent;
import net.minecraftforge.event.level.LevelEvent;
import net.minecraftforge.fml.ModList;
import net.minecraftforge.fml.loading.FMLEnvironment;
import net.minecraftforge.fml.loading.FMLLoader;
import net.minecraftforge.fml.loading.FMLPaths;
import net.minecraftforge.forgespi.language.IModFileInfo;
import net.minecraftforge.server.ServerLifecycleHooks;
import net.minecraftforge.server.permission.PermissionAPI;
import net.minecraftforge.server.permission.nodes.PermissionNode;
import net.minecraftforge.server.permission.nodes.PermissionTypes;
import java.io.File;
import java.nio.file.Path;
public final class ForgeModdedLoader 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 "forge";
}
@Override
public String minecraftVersion() {
return FMLLoader.versionInfo().mcVersion();
}
@Override
public String modVersion() {
return ModList.getModContainerById("irisworldgen")
.map((net.minecraftforge.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) {
LevelEvent.Load.BUS.post(new LevelEvent.Load(level));
}
@Override
public void fireDynamicLevelUnload(MinecraftServer server, ServerLevel level) {
LevelEvent.Unload.BUS.post(new LevelEvent.Unload(level));
}
@Override
public boolean clientEnvironment() {
return FMLEnvironment.dist.isClient();
}
@Override
public Path configDir() {
return FMLPaths.CONFIGDIR.get();
}
@Override
public File modJar() {
IModFileInfo info = ModList.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(() -> {
BlockEvent.BreakEvent event = new BlockEvent.BreakEvent(
level,
position,
state,
player,
Result.DEFAULT
);
BlockEvent.BreakEvent.BUS.post(event);
return !event.getResult().isDenied();
});
}
}
@@ -1,89 +1,26 @@
/*
* 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.forge;
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 art.arcane.iris.spi.protocol.IrisProtocol;
import net.minecraft.network.protocol.common.custom.CustomPacketPayload;
import net.minecraft.resources.Identifier;
import net.minecraft.server.level.ServerPlayer;
import net.minecraftforge.event.network.CustomPayloadEvent;
import net.minecraftforge.network.Channel;
import net.minecraftforge.network.ChannelBuilder;
import net.minecraftforge.network.NetworkProtocol;
import net.minecraftforge.network.PacketDistributor;
import art.arcane.volmlib.nativelib.minecraft26_2.forge.NativeForgeProtocolNetworking;
import art.arcane.volmlib.nativelib.minecraft26_2.modded.NativeProtocolCallbacks;
import art.arcane.iris.client.IrisClient;
import art.arcane.volmlib.nativelib.minecraft26_2.modded.NativeProtocolChannel;
public final class ForgeProtocolNetworking {
private static volatile Channel<CustomPacketPayload> channel;
private static volatile NativeProtocolChannel channel;
private ForgeProtocolNetworking() {
}
public static void register() {
Channel<CustomPacketPayload> boundChannel = ChannelBuilder.named(Identifier.parse(IrisProtocol.CHANNEL))
.optional()
.payloadChannel()
.protocol(NetworkProtocol.PLAY)
.bidirectional()
.add(ModdedIrisPayload.TYPE, ModdedIrisPayload.STREAM_CODEC, ForgeProtocolNetworking::onPayload)
.build();
channel = boundChannel;
ModdedProtocolHandler.bindChannel(new ForgeProtocolChannel(boundChannel));
NativeProtocolCallbacks callbacks = new NativeProtocolCallbacks(ModdedProtocolHandler::onInbound,
ModdedProtocolHandler::onPlayerJoin, ModdedProtocolHandler::onPlayerDisconnect);
channel = NativeForgeProtocolNetworking.register(ModdedProtocolDefinition.PROTOCOL, callbacks, IrisClient::onInbound);
ModdedProtocolHandler.bindChannel(channel);
}
public static Channel<CustomPacketPayload> channel() {
public static NativeProtocolChannel channel() {
return channel;
}
private static void onPayload(ModdedIrisPayload payload, CustomPayloadEvent.Context context) {
context.setPacketHandled(true);
if (context.isClientSide()) {
ForgeClientProtocol.handleInbound(context, payload.data());
return;
}
ServerPlayer player = context.getSender();
if (player == null) {
return;
}
ModdedProtocolHandler.onInbound(player, payload.data());
}
private static final class ForgeProtocolChannel implements ModdedProtocolChannel {
private final Channel<CustomPacketPayload> channel;
private ForgeProtocolChannel(Channel<CustomPacketPayload> channel) {
this.channel = channel;
}
@Override
public boolean canReceive(ServerPlayer player) {
// Forge tracks the channels the remote side announced during handshake. Without this the
// server pushes Iris payloads at vanilla clients, which drop them as unknown custom
// payloads. Mirrors the NeoForge ICommonPacketListener.hasChannel check.
return channel.isRemotePresent(player.connection.getConnection());
}
@Override
public void send(ServerPlayer player, ModdedIrisPayload payload) {
channel.send(payload, PacketDistributor.PLAYER.with(player));
}
}
}
@@ -1,78 +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.forge;
import art.arcane.iris.modded.ModdedBlockBreakHandler;
import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.storage.loot.LootContext;
import net.minecraft.world.level.storage.loot.LootTable;
import net.minecraft.world.level.storage.loot.parameters.LootContextParams;
import net.minecraft.world.level.storage.loot.predicates.LootItemCondition;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.common.loot.IGlobalLootModifier;
import net.minecraftforge.common.loot.LootModifier;
import org.jetbrains.annotations.NotNull;
public final class IrisForgeBlockLootModifier extends LootModifier {
public static final MapCodec<IrisForgeBlockLootModifier> CODEC = RecordCodecBuilder.mapCodec(instance ->
codecStart(instance).apply(instance, IrisForgeBlockLootModifier::new));
public IrisForgeBlockLootModifier(LootItemCondition[] conditions) {
super(conditions);
}
@Override
public MapCodec<? extends IGlobalLootModifier> codec() {
return CODEC;
}
@NotNull
@Override
protected ObjectArrayList<ItemStack> doApply(LootTable table, ObjectArrayList<ItemStack> generatedLoot, LootContext context) {
Entity breaker = context.getOptionalParameter(LootContextParams.THIS_ENTITY);
BlockState state = context.getOptionalParameter(LootContextParams.BLOCK_STATE);
Vec3 origin = context.getOptionalParameter(LootContextParams.ORIGIN);
if (!(breaker instanceof Player) || state == null || origin == null) {
return generatedLoot;
}
ServerLevel level = context.getLevel();
BlockPos position = BlockPos.containing(origin);
ModdedBlockBreakHandler.Result result = ModdedBlockBreakHandler.completePrepared(level, position);
if (result == null) {
return generatedLoot;
}
if (result.routeCombinedDrops(generatedLoot)) {
generatedLoot.clear();
return generatedLoot;
}
if (result.replaceVanillaDrops()) {
generatedLoot.clear();
}
generatedLoot.addAll(result.drops());
return generatedLoot;
}
}
@@ -1,147 +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.forge;
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.ModdedProtocolHandler;
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.level.chunk.ChunkGenerator;
import net.minecraftforge.event.AddPackFindersEvent;
import net.minecraftforge.event.RegisterCommandsEvent;
import net.minecraftforge.event.TickEvent;
import net.minecraftforge.event.entity.player.PlayerEvent;
import net.minecraftforge.event.entity.player.PlayerInteractEvent;
import net.minecraftforge.event.level.BlockEvent;
import net.minecraftforge.event.level.LevelEvent;
import net.minecraftforge.event.server.ServerAboutToStartEvent;
import net.minecraftforge.event.server.ServerStartedEvent;
import net.minecraftforge.event.server.ServerStartingEvent;
import net.minecraftforge.event.server.ServerStoppingEvent;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.common.loot.IGlobalLootModifier;
import net.minecraftforge.common.util.BlockSnapshot;
import net.minecraftforge.eventbus.api.listener.Priority;
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.forge.NativeForgeLoader;
import art.arcane.volmlib.nativelib.minecraft26_2.forge.NativeForgeBootstrap;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import net.minecraftforge.fml.loading.FMLEnvironment;
import net.minecraftforge.fml.loading.FMLLoader;
import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.registries.ForgeRegistries;
import net.minecraftforge.server.permission.events.PermissionGatherEvent;
import java.util.function.Predicate;
@Mod("irisworldgen")
public final class IrisForgeBootstrap {
public IrisForgeBootstrap(FMLJavaModLoadingContext context) {
ModdedEngineBootstrap.bootCommon(new ForgeModdedLoader(), "Forge " + FMLLoader.versionInfo().forgeVersion(), () -> {
DeferredRegister<MapCodec<? extends ChunkGenerator>> chunkGenerators = DeferredRegister.create(Registries.CHUNK_GENERATOR, "irisworldgen");
chunkGenerators.register("iris", () -> IrisModdedChunkGenerator.CODEC);
chunkGenerators.register(context.getModBusGroup());
DeferredRegister<MapCodec<? extends IGlobalLootModifier>> lootModifiers = DeferredRegister.create(ForgeRegistries.GLOBAL_LOOT_MODIFIER_SERIALIZERS, "irisworldgen");
lootModifiers.register("block_drops", () -> IrisForgeBlockLootModifier.CODEC);
lootModifiers.register(context.getModBusGroup());
});
NativeForgeLoader loader = new NativeForgeLoader(new NativeLoaderOptions(
"irisworldgen", "treefeller", ModdedTreeFellerService::runBreakProbe));
NativeChunkGeneratorDefinition generator = IrisModdedChunkGenerator.DEFINITION;
ModdedEngineBootstrap.bootCommon(loader, "Forge " + FMLLoader.versionInfo().forgeVersion(),
() -> NativeForgeBootstrap.registerGenerators(context, generator, "block_drops"));
ForgeProtocolNetworking.register();
// Dist gate for every client-tainted class. DistExecutor is gone in Forge 26.2 (65.x) - only
// net.minecraftforge.api.distmarker.Dist survives, from mergetool-api - so the guard is this branch.
// It is equally safe: IrisForgeClient appears only as an invokestatic target, so the JVM resolves the
// constant-pool entry lazily on first execution and a dedicated server never loads the class.
if (FMLEnvironment.dist == Dist.CLIENT) {
if (loader.clientEnvironment()) {
IrisForgeClient.init();
}
ServerAboutToStartEvent.BUS.addListener((ServerAboutToStartEvent event) -> ModdedEngineBootstrap.serverAboutToStart(event.getServer()));
ServerStartingEvent.BUS.addListener((ServerStartingEvent event) -> ModdedEngineBootstrap.start(event.getServer()));
ServerStartedEvent.BUS.addListener((ServerStartedEvent event) -> ModdedEngineBootstrap.serverStarted(event.getServer()));
ServerStoppingEvent.BUS.addListener((ServerStoppingEvent event) -> ModdedEngineBootstrap.stop());
LevelEvent.Load.BUS.addListener((LevelEvent.Load event) -> {
if (event.getLevel() instanceof ServerLevel level) {
ModdedEngineBootstrap.levelLoaded(level);
}
});
LevelEvent.Unload.BUS.addListener((LevelEvent.Unload event) -> {
if (event.getLevel() instanceof ServerLevel level) {
ModdedEngineBootstrap.levelUnloaded(level);
}
});
PlayerEvent.PlayerLoggedInEvent.BUS.addListener((PlayerEvent.PlayerLoggedInEvent event) -> {
if (event.getEntity() instanceof ServerPlayer player) {
ModdedProtocolHandler.onPlayerJoin(player);
}
});
PlayerEvent.PlayerLoggedOutEvent.BUS.addListener((PlayerEvent.PlayerLoggedOutEvent event) -> {
if (event.getEntity() instanceof ServerPlayer player) {
ModdedProtocolHandler.onPlayerDisconnect(player);
}
});
AddPackFindersEvent.BUS.addListener((AddPackFindersEvent event) -> {
if (event.getPackType() == PackType.SERVER_DATA) {
event.addRepositorySource(ModdedForcedDatapack.repositorySource());
}
});
RegisterCommandsEvent.BUS.addListener((RegisterCommandsEvent event) -> IrisModdedCommands.register(event.getDispatcher()));
PermissionGatherEvent.Nodes.BUS.addListener((PermissionGatherEvent.Nodes event) ->
event.addNodes(ForgeModdedLoader.TREE_FELLER_PERMISSION));
BlockEvent.BreakEvent.BUS.addListener((BlockEvent.BreakEvent event) -> {
if (event.getLevel() instanceof ServerLevel level
&& event.getPlayer() instanceof ServerPlayer player
&& !event.getResult().isDenied()) {
ModdedBlockBreakHandler.prepare(level, player, event.getPos(), event.getState());
}
});
// EventBus 7: the (priority, boolean, consumer) overload's boolean means "always cancels"; passing
// false is rejected at registration for listeners that never cancel. Use (priority, consumer).
BlockEvent.EntityPlaceEvent.BUS.addListener(Priority.MONITOR, (BlockEvent.EntityPlaceEvent event) -> {
if (!(event instanceof BlockEvent.EntityMultiPlaceEvent)
&& event.getLevel() instanceof ServerLevel level) {
ModdedBlockBreakHandler.clearPlacedProvenance(level, event.getPos());
}
});
BlockEvent.EntityMultiPlaceEvent.BUS.addListener(
Priority.MONITOR,
(BlockEvent.EntityMultiPlaceEvent event) -> {
for (BlockSnapshot snapshot : event.getReplacedBlockSnapshots()) {
if (snapshot.getLevel() instanceof ServerLevel level) {
ModdedBlockBreakHandler.clearPlacedProvenance(level, snapshot.getPos());
}
}
}
);
PlayerInteractEvent.LeftClickBlock.BUS.addListener((Predicate<PlayerInteractEvent.LeftClickBlock>) (PlayerInteractEvent.LeftClickBlock event) ->
ModdedWandService.attackBlock(event.getEntity(), event.getLevel(), event.getHand(), event.getPos()));
PlayerInteractEvent.RightClickBlock.BUS.addListener((Predicate<PlayerInteractEvent.RightClickBlock>) (PlayerInteractEvent.RightClickBlock event) ->
ModdedWandService.useBlock(event.getEntity(), event.getLevel(), event.getHand(), event.getPos()));
TickEvent.ServerTickEvent.Post.BUS.addListener((TickEvent.ServerTickEvent.Post event) -> {
ModdedEngineBootstrap.tick(event.server());
ModdedWandService.serverTick(event.server());
});
NativeForgeBootstrap.install(loader, ModdedLifecycleCallbacks.create());
}
}
@@ -19,17 +19,9 @@
package art.arcane.iris.forge;
import art.arcane.iris.client.IrisClient;
import art.arcane.volmlib.nativelib.minecraft26_2.forge.NativeForgeClientHooks;
import art.arcane.iris.client.IrisClientHud;
import art.arcane.iris.client.IrisClientKeybinds;
import art.arcane.iris.modded.ModdedIrisPayload;
import net.minecraft.network.protocol.common.custom.CustomPacketPayload;
import net.minecraftforge.client.event.AddGuiOverlayLayersEvent;
import net.minecraftforge.client.event.ClientPlayerNetworkEvent;
import net.minecraftforge.client.event.InputEvent;
import net.minecraftforge.client.event.RegisterKeyMappingsEvent;
import net.minecraftforge.event.TickEvent;
import net.minecraftforge.network.Channel;
import net.minecraftforge.network.PacketDistributor;
import art.arcane.volmlib.nativelib.minecraft26_2.modded.NativeProtocolChannel;
public final class IrisForgeClient {
private IrisForgeClient() {
@@ -37,28 +29,14 @@ public final class IrisForgeClient {
public static void init() {
IrisClient.bindSender(IrisForgeClient::sendToServer);
AddGuiOverlayLayersEvent.BUS.addListener((AddGuiOverlayLayersEvent event) ->
event.getLayeredDraw().add(IrisClient.HUD_ELEMENT_ID, (graphics, delta) -> IrisClientHud.render(graphics)));
RegisterKeyMappingsEvent.BUS.addListener((RegisterKeyMappingsEvent event) -> {
event.register(IrisClientKeybinds.TOGGLE_HUD);
event.register(IrisClientKeybinds.OPEN_MAP);
event.register(IrisClientKeybinds.TOGGLE_WHAT);
});
ClientPlayerNetworkEvent.LoggingIn.BUS.addListener((ClientPlayerNetworkEvent.LoggingIn event) -> IrisClient.onWorldJoin());
ClientPlayerNetworkEvent.LoggingOut.BUS.addListener((ClientPlayerNetworkEvent.LoggingOut event) -> IrisClient.onDisconnect());
InputEvent.Key.BUS.addListener((InputEvent.Key event) -> IrisClientKeybinds.pollToggle());
TickEvent.ClientTickEvent.Post.BUS.addListener((TickEvent.ClientTickEvent.Post event) -> {
IrisClientKeybinds.pollToggle();
IrisClient.tick();
IrisClientHud.tick();
});
NativeForgeClientHooks.install(IrisClientHud.binding(), IrisClient::onWorldJoin, IrisClient::onDisconnect);
}
private static void sendToServer(byte[] frame) {
Channel<CustomPacketPayload> channel = ForgeProtocolNetworking.channel();
NativeProtocolChannel channel = ForgeProtocolNetworking.channel();
if (channel == null) {
return;
}
channel.send(new ModdedIrisPayload(frame), PacketDistributor.SERVER.noArg());
channel.sendToServer(frame);
}
}
@@ -1,3 +0,0 @@
public net.minecraft.server.MinecraftServer levels
public net.minecraft.server.MinecraftServer executor
public net.minecraft.server.MinecraftServer storageSource