Skip to content

Commit a426f18

Browse files
committed
Added Wurst Addon Support
1 parent 87f56eb commit a426f18

13 files changed

Lines changed: 487 additions & 76 deletions

File tree

README.md

Lines changed: 42 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1262,11 +1262,48 @@ Examples:
12621262
- ```.xray off``` / ```.xray on```
12631263
- Existing ```.xray add/remove/list/reset``` still works
12641264

1265-
---
1266-
1267-
## License
1268-
1269-
This code is licensed under the GNU General Public License v3.
1265+
---
1266+
1267+
## Wurst Addon API
1268+
1269+
This fork now supports Fabric-style Wurst addons through a custom entrypoint.
1270+
1271+
- Entrypoint key: `wurst`
1272+
- Entrypoint class type: `net.wurstclient.addons.WurstAddon`
1273+
- Registration API:
1274+
- `addHack(Hack hack)`
1275+
- `addCommand(Command command)`
1276+
- `addOtherFeature(OtherFeature feature)`
1277+
1278+
Minimal example:
1279+
1280+
```java
1281+
public final class MyAddon extends WurstAddon
1282+
{
1283+
@Override
1284+
public void onInitialize()
1285+
{
1286+
addHack(new MyHack());
1287+
addCommand(new MyCommand());
1288+
}
1289+
}
1290+
```
1291+
1292+
`fabric.mod.json` entrypoint example:
1293+
1294+
```json
1295+
"entrypoints": {
1296+
"wurst": ["com.example.addon.MyAddon"]
1297+
}
1298+
```
1299+
1300+
A ready-to-publish starter project is included in this repository at:
1301+
1302+
- `wurst-addon-template/`
1303+
1304+
## License
1305+
1306+
This code is licensed under the GNU General Public License v3.
12701307

12711308

12721309

src/main/java/net/wurstclient/Feature.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,12 @@ public Category getCategory()
5252
return null;
5353
}
5454

55+
public String getCategoryName()
56+
{
57+
Category category = getCategory();
58+
return category != null ? category.getName() : null;
59+
}
60+
5561
public abstract String getPrimaryAction();
5662

5763
public void doPrimaryAction()

src/main/java/net/wurstclient/WurstClient.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import java.util.stream.Collectors;
1515
import java.util.stream.Stream;
1616
import net.minecraft.client.Minecraft;
17+
import net.wurstclient.addons.AddonManager;
1718
import net.wurstclient.altmanager.AltManager;
1819
import net.wurstclient.altmanager.Encryption;
1920
import net.wurstclient.analytics.PlausibleAnalytics;
@@ -132,6 +133,8 @@ public void initialize()
132133

133134
otfs = new OtfList();
134135

136+
AddonManager.init();
137+
135138
Path settingsFile = wurstFolder.resolve("settings.json");
136139
settingsProfileFolder = wurstFolder.resolve("settings");
137140
this.settingsFile = new SettingsFile(settingsFile, hax, cmds, otfs);
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
/*
2+
* Copyright (c) 2014-2026 Wurst-Imperium and contributors.
3+
*
4+
* This source code is subject to the terms of the GNU General Public
5+
* License, version 3. If a copy of the GPL was not distributed with this
6+
* file, You can obtain one at: https://www.gnu.org/licenses/gpl-3.0.txt
7+
*/
8+
package net.wurstclient.addons;
9+
10+
import java.util.ArrayList;
11+
import java.util.Collections;
12+
import java.util.List;
13+
import java.util.stream.Collectors;
14+
import net.fabricmc.loader.api.FabricLoader;
15+
import net.fabricmc.loader.api.entrypoint.EntrypointContainer;
16+
import net.fabricmc.loader.api.metadata.ModMetadata;
17+
import net.fabricmc.loader.api.metadata.Person;
18+
19+
public final class AddonManager
20+
{
21+
private static final ArrayList<WurstAddon> addons = new ArrayList<>();
22+
private static boolean initialized;
23+
24+
private AddonManager()
25+
{}
26+
27+
public static void init()
28+
{
29+
if(initialized)
30+
return;
31+
32+
initialized = true;
33+
34+
loadAddons();
35+
initializeAddons();
36+
37+
if(!addons.isEmpty())
38+
System.out.println("Loaded Wurst addons: " + addons.stream()
39+
.map(a -> a.name).collect(Collectors.joining(", ")));
40+
}
41+
42+
private static void loadAddons()
43+
{
44+
for(EntrypointContainer<WurstAddon> entrypoint : FabricLoader
45+
.getInstance().getEntrypointContainers("wurst", WurstAddon.class))
46+
{
47+
ModMetadata metadata = entrypoint.getProvider().getMetadata();
48+
WurstAddon addon;
49+
try
50+
{
51+
addon = entrypoint.getEntrypoint();
52+
53+
}catch(Throwable t)
54+
{
55+
throw new RuntimeException(
56+
"Exception while preparing Wurst addon \""
57+
+ metadata.getName() + "\".",
58+
t);
59+
}
60+
61+
addon.id = metadata.getId();
62+
addon.name = metadata.getName();
63+
addon.version = metadata.getVersion().getFriendlyString();
64+
65+
if(metadata.getAuthors().isEmpty())
66+
throw new RuntimeException("Wurst addon \"" + addon.name
67+
+ "\" requires at least one author in fabric.mod.json.");
68+
69+
addon.authors = new String[metadata.getAuthors().size()];
70+
int i = 0;
71+
for(Person author : metadata.getAuthors())
72+
addon.authors[i++] = author.getName();
73+
74+
addons.add(addon);
75+
}
76+
}
77+
78+
private static void initializeAddons()
79+
{
80+
for(WurstAddon addon : addons)
81+
try
82+
{
83+
addon.onInitialize();
84+
85+
}catch(Throwable t)
86+
{
87+
throw new RuntimeException(
88+
"Exception during Wurst addon init \"" + addon.name + "\".",
89+
t);
90+
}
91+
}
92+
93+
public static List<WurstAddon> getAddons()
94+
{
95+
return Collections.unmodifiableList(addons);
96+
}
97+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*
2+
* Copyright (c) 2014-2026 Wurst-Imperium and contributors.
3+
*
4+
* This source code is subject to the terms of the GNU General Public
5+
* License, version 3. If a copy of the GPL was not distributed with this
6+
* file, You can obtain one at: https://www.gnu.org/licenses/gpl-3.0.txt
7+
*/
8+
package net.wurstclient.addons;
9+
10+
import net.wurstclient.WurstClient;
11+
import net.wurstclient.command.Command;
12+
import net.wurstclient.hack.Hack;
13+
import net.wurstclient.other_feature.OtherFeature;
14+
15+
public abstract class WurstAddon
16+
{
17+
/** Automatically assigned from fabric.mod.json. */
18+
public String id;
19+
20+
/** Automatically assigned from fabric.mod.json. */
21+
public String name;
22+
23+
/** Automatically assigned from fabric.mod.json. */
24+
public String version;
25+
26+
/** Automatically assigned from fabric.mod.json. */
27+
public String[] authors;
28+
29+
/**
30+
* Called during Wurst startup after hack/cmd/feature registries are
31+
* available but before GUI/HUD initialization.
32+
*
33+
* Register addon hacks, commands, and other features here.
34+
*/
35+
public abstract void onInitialize();
36+
37+
public String getWebsite()
38+
{
39+
return null;
40+
}
41+
42+
protected final WurstClient getWurst()
43+
{
44+
return WurstClient.INSTANCE;
45+
}
46+
47+
protected final void addHack(Hack hack)
48+
{
49+
WurstClient.INSTANCE.getHax().addHack(hack);
50+
}
51+
52+
protected final void addCommand(Command command)
53+
{
54+
WurstClient.INSTANCE.getCmds().addCmd(command);
55+
}
56+
57+
protected final void addOtherFeature(OtherFeature otherFeature)
58+
{
59+
WurstClient.INSTANCE.getOtfs().addOtf(otherFeature);
60+
}
61+
}

0 commit comments

Comments
 (0)