Skip to content

Commit af8b0f9

Browse files
committed
v0.3_a4 🧀
1 parent 0a9ba65 commit af8b0f9

12 files changed

Lines changed: 25514 additions & 17974 deletions

File tree

MODDING.md

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
# Modding guide
2+
This guide provides information on how to create modifications for Minecraft Diverge.
3+
4+
5+
## Prerequisites:
6+
- JDK 8 (more recent versions do not support modding) (preferrably downloaded from [Adoptium](https://adoptium.net/en-GB/temurin/releases/?version=8), the JDK used to compile Minecraft Diverge)
7+
- RetroMCP 1.0.1 (https://github.com/MCPHackers/RetroMCP-Java; download 1.0.1 from the "Actions" tab, select the latest workflow, download the build artifacts and use the "GUI" jar if 1.0.1 has not released it)
8+
- Minecraft Diverge's [patch file](merged.patch)
9+
- Both the Minecraft Diverge [client](https://github.com/BlueStaggo/MCDiverge/releases/download/latest/mcdiverge.zip) and [server](https://github.com/BlueStaggo/MCDiverge/releases/download/latest/mcdiverge_server.zip)
10+
- (Optional, but recommended) A Java IDE, like IntelliJ or Eclipse.
11+
12+
## Table of contents:
13+
- [Chapter 1: Development environment](#chapter-1-development-environment)
14+
- [Setting up RetroMCP](#setting-up-retromcp)
15+
- [Decompiling Minecraft Diverge (or at least try to)](#decompiling-minecraft-diverge-or-at-least-try-to)
16+
- [Decompiling and patching Alpha v1.1.2_01](#decompiling-and-patching-alpha-v112_01)
17+
- [Recompiling and running Minecraft Diverge](#recompiling-and-running-minecraft-diverge)
18+
- [Chapter 2: Basic mod development](#chapter-2-basic-mod-development)
19+
- [Loading the mod](#loading-the-mod)
20+
- [Adding mod content](#adding-mod-content)
21+
- [Publishing the mod](#publishing-the-mod)
22+
- [Additional resources](#further-resources)
23+
24+
# Chapter 1: Development environment
25+
26+
## Setting up RetroMCP
27+
First, the RetroMCP jar needs to be placed in a new folder. Before decompiling, the `Side` in the `Options` menu needs to be set to `Merged`. Then, go to the "Current version" dropdown and select "Alpha 1.1.2_01". Upon being prompted to run the setup, click yes. RetroMCP will show up a notification when setup is completed, and at that stage RetroMCP should be closed. After this, in the directory RetroMCP is in, two folders called `minecraft` and `minecraft_server` need to be created with each containing a folder called `jars`, since RetroMCP does not create them automatically despite requiring them.
28+
29+
## Decompiling Minecraft Diverge (or at least try to)
30+
In the `jars` folder (not in `minecraft` or `minecraft_server`), there should be a jar file for the client named `minecraft.jar` and a jar file for the server named `minecraft_server.jar`. Each jar needs to be opened in a file archiver and the contents of `mcdiverge.zip` and `mcdiverge_server.zip` need to be copied over to the respective jar. Make sure to delete META-INF in `minecraft.jar`, but not in `minecraft_server.jar`.
31+
32+
With Diverge ready to decompile, open up RetroMCP again and click on the `Decompile` button. Wait for it to do its work, however the decompilation will fail as there are many missing classes, duplicate members and missing generics. This is supposed to happen, as Minecraft Diverge has changed the source code so much that it is bound to have some major differences from the vanilla source code which RetroMCP cannot cope with. This is fine, as there is a different way to get Minecraft Diverge's source code that actually works.
33+
34+
## Decompiling and patching Alpha v1.1.2_01
35+
Create a new folder and copy RetroMCP into it. Open up RetroMCP, set the side to merged, select "Alpha 1.1.2_01" as the current version and click "Decompile". Once decompilation is finished, create a `patches` folder, where the patch file for Minecraft Diverge needs to be moved into and named `merged.patch`. Back in RetroMCP, to the top left of the window, click on `MCP` > `More tasks...` > `Apply patch` to apply the patch file.
36+
37+
## Recompiling and running Minecraft Diverge
38+
In the `minecraft_merged` folder, there is a `src` folder. This folder needs to be copied over to the `minecraft_merged` folder in the Minecraft Diverge decompilation after its `src` and `src_original` folders have been deleted. After that, the `src` folder needs to be copied as a new folder called `src_original`, so that RetroMCP will now use the fixed source code for recompiling as well as source code patch creation. Open up RetroMCP again and press the following buttons in this order while accepting any prompts that appear: `Recompile`, `Update MD5`, `Reobfuscate`, `Build`. After all of this, click `MCP` > `Launch client` and a decompiled version of Minecraft Diverge should be running!
39+
40+
# Chapter 2: Basic mod development
41+
42+
## Loading the mod
43+
To start off creating a mod, add a new class in the folder `minecraft_merged/src/net/minecraft/src`. This class needs to inherit `BaseMod` and override the following methods:
44+
45+
```java
46+
@Override // Name of the mod
47+
public String getName() {
48+
return "Example Mod";
49+
}
50+
51+
@Override // Mod version
52+
public String getVersion() {
53+
return "v0.3_a4";
54+
}
55+
56+
@Override // Author of the mod
57+
public String getAuthor() {
58+
return "BlueStaggo";
59+
}
60+
61+
@Override // Mod icon for mod list (optional)
62+
public String getIcon() {
63+
return "/example_mod/icon.png";
64+
}
65+
66+
@Override // Is the mod for the client or server? (defaults to both)
67+
public ModSide getSide() {
68+
return ModSide.BOTH;
69+
}
70+
71+
@Override // Load the actual mod
72+
public void load() throws Exception {
73+
// Load your mod!
74+
}
75+
```
76+
77+
All resources are loaded relative to the first `src` folder, so if the mod class was used as the icon, its path would be `/net/minecraft/src/YourMod.class`. In the case above, relative to the RetroMCP jar, the icon would need to be stored in `/minecraft_merged/src/example_mod/icon.png`.
78+
79+
Upon running the game, however, the mod will not load. To force the mod to load, go to `ModLoader.java`, and before the code that loads the example mod, add in this code:
80+
81+
```java
82+
// ...
83+
}
84+
}
85+
}
86+
87+
// v v v
88+
mods.add(new YourMod());
89+
modCount++;
90+
// ^ ^ ^
91+
92+
if (loadExampleMod) {
93+
mods.add(new ExampleMod());
94+
modCount++;
95+
}
96+
// ...
97+
```
98+
99+
Make sure to remove this extra code before publishing the mod. If `ModLoader.class` appears in the final jar, it is safe to delete it.
100+
To compile the code and run the game, click on `Recompile`, `Reobfuscate` and `Build` in RetroMCP. When the game is opened, check in the mods list and the mod should appear with its icon:
101+
102+
![Example Mod, Version v0.3_a4, By BlueStaggo](img/doc/modding/modicon.png)
103+
104+
## Adding mod content
105+
What should the mod do? One simple thing it can do is create an achievement and grant it to the player when the game loads. This is very trivial, as this is all the code that needs to be added in the mod:
106+
107+
```java
108+
public static Achievement exampleAchievement;
109+
110+
@Override
111+
public void load() {
112+
exampleAchievement = new Achievement("example_mod/got_modded", "Got Modded", "Now it is Yourcraft!")
113+
.setCreativeUnlockable();
114+
ModLoader.registry.addAchievement(exampleAchievement); // Make sure it is saved correctly
115+
if (ModLoader.isClient()) {
116+
Minecraft.getInstance().achievements.updateProgress(exampleAchievement, 1);
117+
}
118+
}
119+
```
120+
121+
As for the assets, relative to the src folder, these images need to be stored in the directory `/achievements/example_mod/` as `got_modded.png` and `got_modded_locked.png` respectively:
122+
123+
![got_modded.png](img/doc/modding/got_modded.png) ![got_modded_locked.png](img/doc/modding/got_modded_locked.png)
124+
125+
Now when the game is loaded this time, this should appear in the achievements menu:
126+
127+
![Got Modded, Now it is Yourcraft!](img/doc/modding/achievement.png)
128+
129+
## Publishing the mod
130+
First, make sure the mod is not loaded from the ModLoader class. Like before, `Recompile`, `Reobfuscate` and `Build` in RetroMCP. In the `build` folder relative to the RetroMCP jar, two files can be found: `minecraft.zip` and `minecraft_server.zip`. Both of these files contain every class you have modified, but if there are any classes in there that you have not modified then make sure to delete them. Finally, the mod can be shared across the web, but one of the best places to share it in is in the Minecraft Diverge [Discord server](https://discord.gg/rzHsJkvpqw).
131+
132+
## Additional resources
133+
This guide only shows so much, so looking through the [Example Mod](example_mod/net/minecraft/src/ExampleMod.java) and Minecraft Diverge's source code is recommended.

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
Minecraft Diverge is a Minecraft Alpha v1.1.2_01 mod that takes the game towards a different direction. Explore the new biomes, experiment with magic items and explore in a version of Minecraft, diverged! It provides fresh new world generation, extra content for the late game and plenty of tweaks.
66

7-
For guidance with installing this mod, check out the [INSTALLATION](INSTALLATION.md) document.
7+
For guidance with installing this mod, check out the [INSTALLATION](INSTALLATION.md) document. If you want to create mods for Diverge, check out the [MODDING](MODDING.md) guide.
88

99
This is the Github repository for Minecraft Diverge, where users can submit issues and download new versions. The source code for Minecraft Diverge is partially available in the form of patch files from RetroMCP-Java 1.0.
1010

2.24 KB
Loading
1.25 KB
Loading

example_mod/example_mod/icon.png

1.35 KB
Loading
328 Bytes
Loading
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
package net.minecraft.src;
2+
3+
import java.util.List;
4+
5+
public class ExampleMod extends BaseMod {
6+
public static Achievement eatTheCheese;
7+
public static Item cheese;
8+
public static Block cheeseBlock;
9+
10+
@Override
11+
public String getName() {
12+
return "Example Mod";
13+
}
14+
15+
@Override
16+
public String getVersion() {
17+
return "v0.3_a4";
18+
}
19+
20+
@Override
21+
public String getAuthor() {
22+
return "BlueStaggo";
23+
}
24+
25+
@Override
26+
public String getIcon() {
27+
return "/example_mod/icon.png";
28+
}
29+
30+
@Override
31+
public void load() throws Exception {
32+
// Create an achievement. Textures are stored in /achievements/example/eat_the_cheese.png
33+
// and /achievements/example/eat_the_cheese_locked.png depending on progress.
34+
// Creating the locked achievement image is the same as setting HSL saturation to 0
35+
// and decreasing HSL lightness by 80.
36+
eatTheCheese = new Achievement("example_mod/eat_the_cheese", "EAT THE CHEESE!", "Some random cheese fell on your head. Eat it!")
37+
.setCreativeUnlockable(); // Achievements are not unlockable in creative mode by default.
38+
ModLoader.registry.addAchievement(eatTheCheese); // Register it to the ModLoader so that it loads properly
39+
40+
// Create a new item. New IDs can be automatically used with ModLoader.registry.itemId().
41+
// The "5" in the ItemFood constructor is how much health the food heals.
42+
cheese = new ItemFood(ModLoader.registry.itemId(), 5)
43+
.setIconIndex(ModLoader.registry.addItemTexture("/example_mod/items/cheese.png")); // Load in a custom texture into the item texture atlas
44+
// Add in a tooltip for the inventory
45+
cheese.setTooltip(new ItemTooltip(ItemTooltip.LEGENDARY_GRAD, // Legendary gradient (magenta)
46+
"Cheese", ItemTooltip.LEGENDARY_COL, // Legendary color (magenta)
47+
"Very exquisite cuisine", ItemTooltip.DESCRIPTION_COL, // Description color (beige)
48+
cheese)); // Pass in item for automatic info generation (how much health the cheese heals)
49+
50+
// Create a new block. This cheese block will inherit the sponge texture,
51+
// but loading custom block textures is done in a very similar fashion
52+
// to loading custom item textures.
53+
cheeseBlock = new BlockCheese(ModLoader.registry.blockId(), Block.sponge.blockIndexInTexture, Material.plants)
54+
.setHardness(1.0F)
55+
.setStepSound(Block.soundClothFootstep);
56+
cheeseBlock.setTooltip(new ItemTooltip(ItemTooltip.LEGENDARY_GRAD,
57+
"Block of Cheese", ItemTooltip.LEGENDARY_COL,
58+
"SO MUCH CHEESE!", ItemTooltip.DESCRIPTION_COL));
59+
ModLoader.registry.registerItemBlock(cheeseBlock); // Make sure to register the block item!
60+
61+
// Create a new recipe. Make a 2x2 square of cheese
62+
// to craft a cheese block.
63+
ModLoader.registry.addRecipe(new ItemStack(cheeseBlock),
64+
"XX",
65+
"XX",
66+
'X', cheese);
67+
ModLoader.registry.addRecipe(new ItemStack(cheese), // Make sure to be able to convert the cheese back!
68+
"X",
69+
'X', cheeseBlock);
70+
71+
// Item tooltips can be overrided. Here, the Bucket
72+
// of Milk becomes the Bucket of Cheese.
73+
ItemTooltip.items[Item.bucketMilk.shiftedIndex] = new ItemTooltip("Bucket of Cheese",
74+
"What kind of cheese is this?", ItemTooltip.DESCRIPTION_COL);
75+
}
76+
77+
// Using hooks, custom code can be ran
78+
// on every tick of the world.
79+
@Override
80+
public void onWorldMiscUpdates(World world) {
81+
// Drop cheese in singleplayer worlds in 1 in 1000 ticks.
82+
int cheeseInterval = 1000;
83+
if (ModLoader.isClient() && world.canDoClientAction() && world.rand.nextInt(cheeseInterval) == 0) {
84+
for (EntityPlayer player : (List<EntityPlayer>)world.playerEntities) {
85+
EntityItem item = new EntityItem(world, player.posX, player.posY + 10, player.posZ, new ItemStack(cheese));
86+
world.spawnEntityInWorld(item);
87+
world.playSoundAtEntity(item, "random.wand", 1.0F, world.rand.nextFloat() * 0.2F + 0.9F);
88+
world.achievements.updateProgress(eatTheCheese, 1); // Award the "EAT THE CHEESE!" achievement to whoever got the cheese.
89+
}
90+
}
91+
}
92+
93+
// Add mod items to the creative inventory using a hook.
94+
@Override
95+
public void setupCreativeInventory(CreativeInventoryBuilder inv) {
96+
inv.addLabel("Example Mod");
97+
inv.addItem(cheese.shiftedIndex, 0);
98+
inv.addItem(cheeseBlock.blockID, 0);
99+
}
100+
101+
// This is a custom BlockCheese class to get the right shape.
102+
// The Block of Cheese is not a full block, so it needs special code.
103+
private static class BlockCheese extends Block {
104+
public BlockCheese(int var1, int var2, Material var3) {
105+
super(var1, var2, var3);
106+
this.setBlockBounds(0.25F, 0.0F, 0.25F, 0.75F, 0.5F, 0.75F);
107+
}
108+
109+
@Override
110+
public boolean isOpaqueCube() {
111+
return false;
112+
}
113+
114+
@Override
115+
public boolean shouldSideBeRendered(IBlockAccess var1, int var2, int var3, int var4, int var5) {
116+
return true;
117+
}
118+
}
119+
}

img/doc/modding/achievement.png

5.39 KB
Loading

img/doc/modding/got_modded.png

1022 Bytes
Loading
619 Bytes
Loading

0 commit comments

Comments
 (0)