Skip to content

Commit dca01b0

Browse files
committed
BREAKING CHANGE: Port AutoOffhand to Minecraft 1.18.2
This commit ports the AutoOffhand mod from Minecraft 1.16.5 to 1.18.2, adapting to significant changes in the Forge API and Minecraft mappings. Not all changes may be listed here. **Key Changes:** **1. API Updates & Package/Class Renames:** * Updated numerous imports to reflect package changes in Forge and Minecraft (e.g., `net.minecraft.world.entity`, `net.minecraft.network.chat`, `com.mojang.blaze3d.platform`). * Renamed core classes: * `PlayerEntity` -> `Player` * `ServerPlayerEntity` -> `ServerPlayer` * `ProjectileEntity` -> `Projectile` * `TridentEntity` -> `ThrownTrident` * `CompoundNBT` -> `CompoundTag` * `KeyBinding` -> `KeyMapping` * `ITextComponent` -> `Component` * `TranslationTextComponent` -> `TranslatableComponent` * `PlayerInventory` -> `Inventory` * `NetworkManager` -> `Connection` * Updated method calls for renamed/refactored vanilla classes (e.g., `player.getLevel().isClientSide()`, `player.getInventory()`, `entity.isRemoved()`, `entity.discard()`). * Registry names are now primarily accessed via `ForgeRegistries` (e.g., `ForgeRegistries.ITEMS.getKey(item)`, `ForgeRegistries.ENTITIES.getKey(entityType)`). **2. Event System Changes:** * **Capability Registration:** Moved from `FMLCommonSetupEvent` using `CapabilityManager` to the dedicated `RegisterCapabilitiesEvent` on the MOD event bus. * **Command Registration:** Moved from `FMLServerStartingEvent` (Forge bus) to the dedicated `RegisterCommandsEvent` (Forge bus). * **Setup Events:** Utilized `event.enqueueWork()` more consistently in `FMLCommonSetupEvent` and `FMLClientSetupEvent` for thread-safe operations like network registration and screen registration. **3. Capability Handling:** * Capability interface (`IPlayerConfig`) and provider (`PlayerConfigProvider`) remain structurally similar. * Registration logic updated as described above. * Event handlers (`onAttachCapabilitiesPlayer`, `onPlayerClone`, `onPlayerLoggedIn`, `onPlayerChangedDimension`) updated to use new class names (`Player`, `ServerPlayer`). **4. Networking:** * Network packet classes (`SyncConfigPacket`, `RequestConfigPacket`, etc.) remain largely the same. * `NetworkHandler` registration moved to `commonSetup`'s `enqueueWork`. * Checking if a client has the mod installed during login (`onPlayerLoggedIn`) now uses the `Connection` object instead of `NetworkManager`. **5. Client-Side Changes:** * **Container/Menu:** * Registered `ConfigItemListContainer` using a `DeferredRegister<MenuType<?>>` in `ClientSetup`. * Screen factory registered using `MenuScreens.register` within `clientSetup`'s `enqueueWork`. * **Keybinding:** * Uses `KeyMapping` and `InputConstants` instead of `KeyBinding` and `InputMappings`. Registration is often handled automatically for static final fields. * **GUI:** Updated `ConfigItemListScreen` to use `Component` and `Inventory`. **6. Item/Entity Handling:** * **Pickup Logic (`onPlayerPickupItem`):** Updated to use `InteractionHand`, `player.getLevel().isClientSide()`, `entity.discard()`, `entity.isRemoved()`. Item registry name logging adapted. * **Config Check (`shouldMoveToOffhand`):** Updated to use `Player` and `ForgeRegistries.ITEMS.getKey()`. Item comparison logic (`ConfigItemUtils.stacksMatchIgnoreDamageAndCount`) remains, assuming internal compatibility or necessary updates within that utility class. * **Projectile Return (`onProjectileReturn`, `checkAndMoveSpecificInventoryItem`):** * Updated entity types (`ThrownTrident`, `Projectile`). * Uses `CompoundTag` for NBT handling. * Uses `ForgeRegistries.ENTITIES.getKey()` for entity type comparison. * Uses `TickTask` instead of `TickDelayedTask` for scheduling the inventory check. * Uses `ItemStack.isSameItemSameTags()` for more precise item comparison when moving returned items. * Updated inventory access (`player.getInventory()`). **7. Configuration:** * `ModConfig` loading remains registered in the main mod class constructor. * `ConfigItemUtils` parsing logic is assumed to be compatible, interacting with updated APIs where necessary (e.g., registry names).
1 parent c89dd30 commit dca01b0

23 files changed

Lines changed: 547 additions & 642 deletions

README.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
## Description
44

5-
AutoOffhand is a server-side Minecraft Forge mod for Minecraft 1.16.5, designed to automatically manage your offhand slot. It moves specific items directly into your offhand when you pick them up, provided the slot is empty. It also intelligently handles returning projectiles like Loyalty Tridents, placing them back into your offhand if configured.
5+
AutoOffhand is a server-side Minecraft Forge mod for Minecraft [1.16.5](https://github.com/Th-Underscore/AutoOffhand/releases/tag/v0.0.1) and [1.18.2](https://github.com/Th-Underscore/AutoOffhand/releases/tag/v0.0.2), designed to automatically manage your offhand slot. It moves specific items directly into your offhand when you pick them up, provided the slot is empty. It also intelligently handles returning projectiles like Loyalty Tridents, placing them back into your offhand if configured.
66

77
## Features
88

@@ -25,6 +25,11 @@ AutoOffhand is a server-side Minecraft Forge mod for Minecraft 1.16.5, designed
2525
* Add or remove item registry names (right-click) or specific item NBT strings (left-click) to customize your personal list.
2626
* Use the `/autooffhand toggle` command to switch between using the server's global config list and your own.
2727

28+
## Compatibility
29+
30+
* Tetra's Modular Items (https://www.curseforge.com/minecraft/mc-mods/tetra)
31+
* If you want me to add more, please let me know!
32+
2833
## Building
2934

3035
This project uses Forge Gradle. Use the following commands:

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ base {
1313
}
1414

1515
// Mojang ships Java 17 to end users in 1.18+, so your mod should target Java 17.
16-
java.toolchain.languageVersion = JavaLanguageVersion.of(8)
16+
java.toolchain.languageVersion = JavaLanguageVersion.of(17)
1717

1818
println "Java: ${System.getProperty 'java.version'}, JVM: ${System.getProperty 'java.vm.version'} (${System.getProperty 'java.vendor'}), Arch: ${System.getProperty 'os.arch'}"
1919
minecraft {

gradle.properties

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,17 @@ org.gradle.daemon=false
77
## Environment Properties
88

99
# The Minecraft version must agree with the Forge version to get a valid artifact
10-
minecraft_version=1.16.5
10+
minecraft_version=1.18.2
1111
# The Minecraft version range can use any release version of Minecraft as bounds.
1212
# Snapshots, pre-releases, and release candidates are not guaranteed to sort properly
1313
# as they do not follow standard versioning conventions.
14-
minecraft_version_range=[1.16.5,1.17)
14+
minecraft_version_range=[1.18,1.18.2]
1515
# The Forge version must agree with the Minecraft version to get a valid artifact
16-
forge_version=36.2.42
16+
forge_version=40.2.17
1717
# The Forge version range can use any version of Forge as bounds or match the loader version range
18-
forge_version_range=[36,)
18+
forge_version_range=[40,)
1919
# The loader version range can only use the major version of Forge/FML as bounds
20-
loader_version_range=[36,)
20+
loader_version_range=[40,)
2121
# The mapping channel to use for mappings.
2222
# The default set of supported mapping channels are ["official", "snapshot", "snapshot_nodoc", "stable", "stable_nodoc"].
2323
# Additional mapping channels can be registered through the "channelProviders" extension in a Gradle plugin.
@@ -35,7 +35,7 @@ loader_version_range=[36,)
3535
mapping_channel=official
3636
# The mapping version to query from the mapping channel.
3737
# This must match the format required by the mapping channel.
38-
mapping_version=1.16.5
38+
mapping_version=1.18.2
3939

4040

4141
## Mod Properties
@@ -48,12 +48,12 @@ mod_name=AutoOffhand
4848
# The license of the mod. Review your options at https://choosealicense.com/. All Rights Reserved is the default.
4949
mod_license=All Rights Reserved
5050
# The mod version. See https://semver.org/
51-
mod_version=0.0.1
51+
mod_version=0.0.2+1.18.2
5252
# The group ID for the mod. It is only important when publishing as an artifact to a Maven repository.
5353
# This should match the base package used for the mod sources.
5454
# See https://maven.apache.org/guides/mini/guide-naming-conventions.html
55-
mod_group_id=com.example.autooffhand
55+
mod_group_id=com.thunderscore.autooffhand
5656
# The authors of the mod. This is a simple text string that is used for display purposes in the mod list.
5757
mod_authors=Th-Underscore
5858
# The description of the mod. This is a simple multiline text string that is used for display purposes in the mod list.
59-
mod_description=Example mod description.\nNewline characters can be used and will be replaced properly.
59+
mod_description=Automatically switch specific items to the offhand on pickup.
Lines changed: 33 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,101 +1,87 @@
11
package com.thunderscore.autooffhand;
22

3-
import org.apache.logging.log4j.LogManager;
4-
import org.apache.logging.log4j.Logger;
5-
63
import com.thunderscore.autooffhand.capability.IPlayerConfig;
7-
import com.thunderscore.autooffhand.capability.PlayerConfig;
8-
import com.thunderscore.autooffhand.capability.PlayerConfigStorage;
94
import com.thunderscore.autooffhand.command.ModCommands;
105
import com.thunderscore.autooffhand.config.ModConfig;
11-
import com.thunderscore.autooffhand.inventory.ModContainers;
126
import com.thunderscore.autooffhand.network.NetworkHandler;
13-
147
import net.minecraftforge.api.distmarker.Dist;
158
import net.minecraftforge.common.MinecraftForge;
16-
import net.minecraftforge.common.capabilities.CapabilityManager;
9+
import net.minecraftforge.common.capabilities.RegisterCapabilitiesEvent;
10+
import net.minecraftforge.event.RegisterCommandsEvent;
1711
import net.minecraftforge.eventbus.api.IEventBus;
1812
import net.minecraftforge.eventbus.api.SubscribeEvent;
1913
import net.minecraftforge.fml.ModLoadingContext;
2014
import net.minecraftforge.fml.common.Mod;
2115
import net.minecraftforge.fml.config.ModConfig.Type;
2216
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
2317
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
24-
import net.minecraftforge.fml.event.server.FMLServerStartingEvent;
2518
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
2619
import net.minecraftforge.fml.loading.FMLEnvironment;
20+
import org.apache.logging.log4j.LogManager;
21+
import org.apache.logging.log4j.Logger;
2722

2823
// The value here should match an entry in the META-INF/mods.toml file
29-
@Mod(AutoOffhand.MOD_ID) // Updated class name reference
30-
public class AutoOffhand { // Updated class name
31-
24+
@Mod(AutoOffhand.MOD_ID)
25+
public class AutoOffhand {
3226
// Make logger public so other classes can access it
3327
public static final Logger LOGGER = LogManager.getLogger();
34-
public static final String MOD_ID = "autooffhand"; // Define mod ID constant
28+
public static final String MOD_ID = "autooffhand";
3529

3630
public AutoOffhand() {
3731
final IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus();
3832

39-
// Register the config - Changed to SERVER type and SERVER_SPEC
4033
ModLoadingContext.get().registerConfig(Type.SERVER, ModConfig.SERVER_SPEC);
4134

42-
// Register ContainerType Deferred Register ONLY on the client side
4335
if (FMLEnvironment.dist == Dist.CLIENT) {
44-
ModContainers.CONTAINERS.register(modEventBus);
45-
LOGGER.debug("Registered ModContainers DeferredRegister on CLIENT.");
46-
} else {
47-
LOGGER.debug("Skipped registering ModContainers DeferredRegister on SERVER.");
36+
ClientSetup.CONTAINERS.register(modEventBus);
37+
LOGGER.debug("Registered ClientSetup.CONTAINERS DeferredRegister on CLIENT.");
4838
}
4939

40+
// Register setup methods
5041
modEventBus.addListener(this::commonSetup);
5142
modEventBus.addListener(this::clientSetup);
43+
// Register capability registration event handler
44+
modEventBus.addListener(this::registerCapabilities);
5245
// Register the static onCommonSetup method from ForgeEventHandler for the FMLCommonSetupEvent
5346
modEventBus.addListener(ForgeEventHandler::onCommonSetup);
5447

55-
MinecraftForge.EVENT_BUS.register(this);
48+
// Register Forge event bus listeners
49+
MinecraftForge.EVENT_BUS.register(this); // For onRegisterCommands
50+
MinecraftForge.EVENT_BUS.register(ForgeEventHandler.class); // For other game events
5651

5752
LOGGER.debug("AutoOffhand Mod Initialized");
5853
}
5954

60-
// Runs during common setup (both client and server)
55+
// Common setup (client and server)
6156
private void commonSetup(final FMLCommonSetupEvent event) {
6257
LOGGER.debug("AutoOffhand common setup starting.");
6358

64-
// Register Capability
65-
event.enqueueWork(() -> { // Capabilities should be registered during enqueueWork
66-
CapabilityManager.INSTANCE.register(
67-
IPlayerConfig.class, // Capability Interface
68-
new PlayerConfigStorage(), // Storage Implementation
69-
PlayerConfig::new // Factory for default instance
70-
);
71-
LOGGER.debug("Registered PlayerConfig capability.");
72-
});
73-
74-
75-
// Register the new top-level event handler class (includes capability events now)
76-
MinecraftForge.EVENT_BUS.register(ForgeEventHandler.class);
77-
LOGGER.debug("AutoOffhand ForgeEventHandler class registered on Forge event bus.");
59+
// Old capability registration removed. It's handled by registerCapabilities event now.
7860

7961
// Register network packets
80-
NetworkHandler.register();
81-
LOGGER.debug("Registered network packets."); // Added log
62+
event.enqueueWork(NetworkHandler::register); // Network registration often needs enqueueWork
63+
LOGGER.debug("Scheduled network packet registration.");
8264
}
8365

84-
// Renamed from 'setup' - Runs during client setup ONLY
66+
// Client setup ONLY
8567
private void clientSetup(final FMLClientSetupEvent event) {
8668
LOGGER.debug("AutoOffhand client setup starting.");
87-
// Call client setup directly (removed enqueueWork)
88-
ClientSetup.init(event);
89-
LOGGER.debug("AutoOffhand client setup complete."); // Adjusted log message
69+
// Call client setup directly
70+
event.enqueueWork(() -> ClientSetup.init(event)); // ClientSetup might need enqueueWork too
71+
LOGGER.debug("Scheduled client setup initialization.");
9072
}
9173

92-
// Event handler for FMLServerStartingEvent (called on the Forge bus, needs @SubscribeEvent)
74+
// Event handler for RegisterCapabilitiesEvent (called on the MOD bus)
75+
public void registerCapabilities(final RegisterCapabilitiesEvent event) {
76+
event.register(IPlayerConfig.class);
77+
LOGGER.debug("Registered PlayerConfig capability via RegisterCapabilitiesEvent.");
78+
}
79+
80+
// Event handler for RegisterCommandsEvent (called on the FORGE bus)
9381
@SubscribeEvent
94-
public void onServerStarting(FMLServerStartingEvent event) {
95-
LOGGER.debug("Registering AutoOffhand commands...");
96-
ModCommands.register(event.getServer().getCommands().getDispatcher());
82+
public void onRegisterCommands(RegisterCommandsEvent event) {
83+
LOGGER.debug("Registering AutoOffhand commands via RegisterCommandsEvent...");
84+
ModCommands.register(event.getDispatcher()); // Pass the dispatcher directly
9785
LOGGER.debug("AutoOffhand commands registered.");
9886
}
99-
100-
// Removed the static inner ForgeEvents class as it's now in ForgeEventHandler.java
10187
}

src/main/java/com/thunderscore/autooffhand/ClientSetup.java

Lines changed: 42 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -6,59 +6,65 @@
66
import org.apache.logging.log4j.Logger;
77
import org.lwjgl.glfw.GLFW;
88

9+
import com.mojang.blaze3d.platform.InputConstants;
910
import com.thunderscore.autooffhand.gui.ConfigItemListScreen;
1011
import com.thunderscore.autooffhand.inventory.ConfigItemListContainer;
11-
import com.thunderscore.autooffhand.inventory.ModContainers;
1212
import com.thunderscore.autooffhand.network.NetworkHandler;
1313
import com.thunderscore.autooffhand.network.RequestConfigPacket;
1414

15+
import net.minecraft.world.inventory.MenuType;
16+
import net.minecraftforge.common.extensions.IForgeMenuType;
17+
import net.minecraftforge.registries.DeferredRegister;
18+
import net.minecraftforge.registries.ForgeRegistries;
19+
import net.minecraftforge.registries.RegistryObject;
20+
21+
import net.minecraft.client.KeyMapping;
1522
import net.minecraft.client.Minecraft;
16-
import net.minecraft.client.gui.ScreenManager;
17-
import net.minecraft.client.settings.KeyBinding;
18-
import net.minecraft.client.util.InputMappings;
19-
import net.minecraft.entity.player.PlayerInventory;
20-
import net.minecraft.util.text.ITextComponent;
21-
import net.minecraft.util.text.TranslationTextComponent;
23+
import net.minecraft.client.gui.screens.MenuScreens;
24+
import net.minecraft.network.chat.Component;
25+
import net.minecraft.network.chat.TranslatableComponent;
26+
import net.minecraft.world.entity.player.Inventory;
2227
import net.minecraftforge.api.distmarker.Dist;
2328
import net.minecraftforge.client.event.InputEvent;
2429
import net.minecraftforge.common.MinecraftForge;
2530
import net.minecraftforge.eventbus.api.SubscribeEvent;
26-
import net.minecraftforge.fml.client.registry.ClientRegistry;
2731
import net.minecraftforge.fml.common.Mod;
2832
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
2933

3034
@Mod.EventBusSubscriber(modid = AutoOffhand.MOD_ID, bus = Mod.EventBusSubscriber.Bus.MOD, value = Dist.CLIENT)
3135
public class ClientSetup {
32-
// Add logger for this class
3336
private static final Logger LOGGER = LogManager.getLogger();
3437

35-
// Define the keybinding
36-
public static final KeyBinding OPEN_CONFIG_GUI_KEY = new KeyBinding(
38+
public static final DeferredRegister<MenuType<?>> CONTAINERS = DeferredRegister.create(ForgeRegistries.CONTAINERS, AutoOffhand.MOD_ID);
39+
40+
public static final RegistryObject<MenuType<ConfigItemListContainer>> CONFIG_ITEM_LIST_CONTAINER = CONTAINERS.register(
41+
"config_item_list_container", // Registry name must match the one expected by packets/screens
42+
() -> IForgeMenuType.create((windowId, inv, data) -> new ConfigItemListContainer(windowId, inv))
43+
);
44+
45+
public static final KeyMapping OPEN_CONFIG_GUI_KEY = new KeyMapping(
3746
"key." + AutoOffhand.MOD_ID + ".open_config_gui", // Translation key
38-
InputMappings.Type.KEYSYM, // Type of input (keyboard)
39-
GLFW.GLFW_KEY_O, // Default key (O) - Choose an appropriate default
47+
InputConstants.Type.KEYSYM,
48+
GLFW.GLFW_KEY_O, // Default key (O)
4049
"key.categories." + AutoOffhand.MOD_ID // Translation key for category
4150
);
4251

43-
// Called during FMLClientSetupEvent
4452
public static void init(final FMLClientSetupEvent event) {
45-
// ContainerType Deferred Register is registered in the main mod constructor
46-
47-
// Register the keybinding
48-
ClientRegistry.registerKeyBinding(OPEN_CONFIG_GUI_KEY);
49-
50-
// Register the ScreenFactory for our ContainerType
51-
// Assumes ModContainers.CONFIG_ITEM_LIST_CONTAINER is registered elsewhere
52-
ScreenManager.register(
53-
ModContainers.CONFIG_ITEM_LIST_CONTAINER.get(), // Get the registered ContainerType
54-
// Explicit lambda matching the IScreenFactory signature
55-
(ConfigItemListContainer container, PlayerInventory inv, ITextComponent title) -> new ConfigItemListScreen(container, inv, title)
56-
);
57-
58-
// Register an INSTANCE of this class to the Forge event bus for non-static methods
53+
// Register an INSTANCE of this class to the Forge event bus for non-static methods like onKeyInput
5954
MinecraftForge.EVENT_BUS.register(new ClientSetup());
6055

61-
LOGGER.debug("Client setup complete.");
56+
// Use enqueueWork for thread-safe operations like screen registration
57+
event.enqueueWork(() -> {
58+
// Register Menu Screen
59+
MenuScreens.register(
60+
CONFIG_ITEM_LIST_CONTAINER.get(),
61+
// Use a lambda to explicitly call the constructor matching (container, inv, title)
62+
(ConfigItemListContainer container, Inventory inv, Component title) -> new ConfigItemListScreen(container, inv, title)
63+
);
64+
LOGGER.debug("Registered menu screens.");
65+
});
66+
67+
LOGGER.debug("Client setup init phase complete.");
6268
}
6369

6470
/**
@@ -68,7 +74,7 @@ public static void init(final FMLClientSetupEvent event) {
6874
* @param initialConfigEntries The list of entries sent by the server.
6975
* @param isServerConfig True if the entries are for the server config, false for player config.
7076
*/
71-
public static void openConfigScreen(List<String> initialConfigEntries, boolean isServerConfig) { // Add isServerConfig parameter
77+
public static void openConfigScreen(List<String> initialConfigEntries, boolean isServerConfig) {
7278
// Ensure we have a player and are on the client
7379
Minecraft mc = Minecraft.getInstance();
7480
if (mc.player != null) {
@@ -78,12 +84,12 @@ public static void openConfigScreen(List<String> initialConfigEntries, boolean i
7884
// Create a new container instance on the client
7985
// Note: The windowId (0) might be okay for client-opened screens,
8086
// but needs verification if server interaction causes issues.
81-
new ConfigItemListContainer(0, mc.player.inventory),
82-
mc.player.inventory,
83-
// Dynamically change title based on config type (Explicit cast added)
84-
(ITextComponent) new TranslationTextComponent(isServerConfig ? "gui." + AutoOffhand.MOD_ID + ".config_item_list.title_server" : "gui." + AutoOffhand.MOD_ID + ".config_item_list.title_player"),
85-
initialConfigEntries, // Pass the list
86-
isServerConfig // Pass the flag to the screen constructor
87+
new ConfigItemListContainer(0, mc.player.getInventory()),
88+
mc.player.getInventory(),
89+
// Dynamically change title based on config type
90+
new TranslatableComponent(isServerConfig ? "gui." + AutoOffhand.MOD_ID + ".config_item_list.title_server" : "gui." + AutoOffhand.MOD_ID + ".config_item_list.title_player"), // Reverted to new TranslatableComponent
91+
initialConfigEntries,
92+
isServerConfig
8793
)
8894
);
8995
LOGGER.debug("Opened config screen (isServerConfig={}). Initial entries provided: {}", isServerConfig, initialConfigEntries != null);

0 commit comments

Comments
 (0)