-
Notifications
You must be signed in to change notification settings - Fork 0
3. Mod Developer Things
Want to integrate with CreateWorldUI? Here's what you need to know.
Well, quite simple, just add the game rules through the GameRule class like you used to do, name your Rule name then set a default boolean or number value. And then, boom, they appeared on the page. Has their name and their default value will show on your screen.
But... There's something wrong. What if I want to add tooltip descriptions for my rules, and also, how to custom vanilla Rule name tooltip?
Well, more things need to be done. And we have two ways for it.
The modpack usage is showing how to use it. That's it.
It can only be achieved by the hard code, and this doesn't like the simple way if you cannot handle it carefully it cannot show the localized name. so it's not welcomed to the only using simple ways.
Codes are belowed: (After 1.0.1)
package idk.unknown.which;
import cpw.mods.fml.common.Mod;
import cpw.mods.fml.common.event.FMLInitializationEvent;
import decok.dfcdvadstf.createworldui.gamerule.GuiScreenGameRuleEditor;
@Mod(modid = "idk", name = "idk", version = "idk")
public class idk {
@Mod.EventHandler
public void init(FMLInitializationEvent event){
// There are two ways to register this
// registerTooltip() can add one single tooltip
// registerTooltips() can add a Map, which contains many rules and tooltips, to the tooltip list.
GuiScreenGameRuleEditor.registerTooltip("randomTickSpeed", "Controls how fast random ticks occur");
GuiScreenGameRuleEditor.registerTooltip("myCustomRule", "This is a rule added by another mod"); // Former is ruleName, latter is tooltips.
Map<String,String> myCustomTooltips = new HashMap<>();
myCustomTooltips.put("myCustomRule2","This is a rule added by another mod");
myCustomTooltips.put("myCustomRule3","This is a rule added by another mod");
myCustomTooltips.put("myCustomRule4","This is a rule added by another mod");
// myCustomTooltips.put(........);
GuiScreenGameRuleEditor.registerTooltips("myCustomToolTips");
}
}Here are the API classes you can use.
Package: decok.dfcdvadstf.createworldui.api.gamerule.GameRuleApplier
Handles applying game rules when a world loads.
| Method | What it does |
|---|---|
setPendingGameRules(Map<String, String>) |
Queue up game rules to apply when the next world is created. |
getPendingGameRules() |
Get the currently pending rules (may be null). |
Pending rules are applied via WorldEvent.Load and then cleared.
Package: decok.dfcdvadstf.createworldui.api.gamerule.GameRuleMonitorNSetter
For getting, setting, and adding game rules.
| Method | What it does |
|---|---|
getAllGamerules(World) |
Get all game rules from a world as Map<String, GameruleValue>. |
setGamerule(World, String, String) |
Set a game rule on a world. |
The GameruleValue inner class stores values in multiple types (String, boolean, int, double) and has getOptimalValue() to pick the best one.
Package: decok.dfcdvadstf.createworldui.api.DifficultyApplier
Applies difficulty settings when a world is created. Works with the tab system to set difficulty on the IntegratedServer via Mixin.
Package: decok.dfcdvadstf.createworldui.api.GuiCyclableButton
A button that cycles through values on click. Used for game mode, difficulty, and world type. You can use it in your own tabs.
Package: decok.dfcdvadstf.createworldui.api.tab.TabRegistry
The static registry for external mods to register custom tabs. See Adding a Custom Tab for details and examples.
After 2.0.0, the world creation screen uses a tab system. Each tab implements AbstractScreenTab. And after 4.0.0, this mod finally abled to registry the tabs.
| Class | Tab ID | What it does |
|---|---|---|
GameTab |
100 | World name, game mode, difficulty, cheats |
WorldTab |
101 | Seed, world type, structures, bonus chest |
MoreTab |
102 | GameRule Editor, experiments, data packs |
Package: decok.dfcdvadstf.createworldui.api.tab.TabManager
TabManager handles tab switching, state persistence (survives window resizes), and gives you accessors for the shared state:
| Method | What it does |
|---|---|
getWorldName() / setWorldName(String)
|
Get or set the world name. |
getGameMode() / setGameMode(String)
|
Get or set the game mode. |
getDifficulty() / setDifficulty(EnumDifficulty)
|
Get or set the difficulty. |
getHardcore() / setHardcore(boolean)
|
Get or set hardcore mode. |
getAllowCheats() / setAllowCheats(boolean)
|
Get or set allow cheats. |
getSeed() / setSeed(String)
|
Get or set the world seed. |
getWorldTypeIndex() / setWorldTypeIndex(int)
|
Get or set the world type. |
getGenerateStructures() / setGenerateStructures(boolean)
|
Get or set generate structures. |
getBonusChest() / setBonusChest(boolean)
|
Get or set bonus chest. |
Package: decok.dfcdvadstf.createworldui.api.tab.TabState
Stores tab state (active tab, all tab fields) that persists across GUI reinitialization — like when you resize the window.
You can register custom tabs into the world creation screen using the TabRegistry API.
Package: decok.dfcdvadstf.createworldui.api.tab.TabRegistry
It's a static registry — you register your tabs during mod init, and when the world creation screen opens, TabManager freezes the registry and creates all the tabs.
| Method | What it does |
|---|---|
registerTab(Supplier<Tab>, int, String, int) |
Register a tab with factory, ID, name key, and priority. |
registerTab(Supplier<Tab>, int, String) |
Same thing, but priority defaults to tabId. |
getEntries() |
Get all entries sorted by priority (unmodifiable). |
isFrozen() |
Check if the registry is frozen (GUI already initialized). |
freeze() |
Freeze the registry. Called internally by TabManager. |
| Parameter | Type | What it means |
|---|---|---|
factory |
Supplier<Tab> |
A factory that creates your Tab instance. Called once when TabManager is constructed. |
tabId |
int |
Unique tab ID. Built-in tabs use 100–102, so start from 103. |
nameKey |
String |
Localization key for the tab name (like "mymod.tab.custom"). |
priority |
int |
Sort order — lower comes first. Defaults to tabId if not specified. Built-in tabs use 0, 1, 2. |
Entries are sorted by priority ascending, then tabId ascending as a tiebreaker.
import cpw.mods.fml.common.Mod;
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
import decok.dfcdvadstf.createworldui.api.tab.AbstractScreenTab;
import decok.dfcdvadstf.createworldui.api.tab.Tab;
import decok.dfcdvadstf.createworldui.api.tab.TabManager;
import decok.dfcdvadstf.createworldui.api.tab.TabRegistry;
import net.minecraft.client.gui.GuiButton;
@Mod(modid = "mymod", name = "My Mod", version = "1.0")
public class MyMod {
@Mod.EventHandler
public void preInit(FMLPreInitializationEvent event) {
TabRegistry.registerTab(
MyCustomTab::new, // Supplier<Tab> factory
103, // Unique tab ID (start from 103)
"mymod.tab.custom", // Localization key
5 // Sort priority (lower = earlier)
);
}
}
// Your custom tab
public class MyCustomTab extends AbstractScreenTab {
public MyCustomTab() {
super(103, "mymod.tab.custom"); // Must match what you registered
}
@Override
public void initGui(TabManager tabManager, int width, int height) {
super.initGui(tabManager, width, height);
// Add your buttons and fields here
setVisible(false);
}
@Override
public void drawScreen(int mouseX, int mouseY, float partialTicks) {
if (!visible) return;
// Draw your tab content here
}
@Override
public void actionPerformed(GuiButton button) {
// Handle button clicks here
}
@Override
public void mouseClicked(int mouseX, int mouseY, int mouseButton) {
// Handle mouse clicks here
}
@Override
public void keyTyped(char typedChar, int keyCode) {
// Handle key input here
}
}And don't forget the localization in your lang file:
mymod.tab.custom=My Tab-
Register early — like
FMLPreInitializationEvent. OnceTabManageris constructed the registry freezes, and registering after that throws anIllegalStateException. -
Tab IDs must be unique — duplicate IDs throw an
IllegalArgumentException. -
AbstractScreenTabconstructor must match — thetabIdandnameKeyyou pass there need to be the same ones you gaveTabRegistry.registerTab(). -
initGui()gets called byTabManager— on init and on resize. Always callsuper.initGui()and setsetVisible(false)at the end. -
Use
tabManageraccessors (likegetWorldName(),setGameMode()) to read/write the shared world creation state.
Two ways to do it:
-
Localization files (Recommended) — just add entries like this:
gamerule.yourRuleName.tooltip.description=Your description here gamerule.yourRuleName.name=Display Name
-
Code — Use
GuiScreenGameRuleEditor.registerTooltip()orregisterTooltips()duringFMLInitializationEvent. The hard way section above shows how.
Same idea as tooltips:
gamerule.yourRuleName.name=Your Display NameIf no name localization is provided, the raw rule name is shown instead.
Class: decok.dfcdvadstf.createworldui.command.CommandGameRuleEditor
Opens the GameRule Editor in-game. You need either:
-
igGameruleEditconfig option enabled, or - ModernDifficultyLocker installed.
Requires permission level 2 (same as /gamerule).
Here's what gets mixed into what:
| Mixin Class | Target | What it does |
|---|---|---|
MixinModernCreateWorld |
GuiCreateWorld |
Replaces the world creation screen with the tabbed UI. |
MixinGuiSelectWorld |
GuiSelectWorld |
Enhances the world selection screen. |
MixinIntegratedServer |
IntegratedServer |
Applies difficulty and game rules when the world loads. |
MixinMinecraft |
Minecraft |
Client-side hooks. |
To use CreateWorldUI as a dependency, add this to your build.gradle:
dependencies {
implementation 'com.github.song682:CreateWorldUI:Tag'
}Replace Tag with the version you want from the repository.
Also, the -deobf suffix jars are also available.