• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

CyclopsMC / CyclopsCore / #479033818

11 Nov 2025 12:50PM UTC coverage: 22.267% (-0.002%) from 22.269%
#479033818

push

github

rubensworks
Bump mod version

2328 of 10455 relevant lines covered (22.27%)

0.22 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/main/java/org/cyclops/cyclopscore/init/ModBase.java
1
package org.cyclops.cyclopscore.init;
2

3
import com.google.common.collect.Lists;
4
import com.google.common.collect.Maps;
5
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
6
import lombok.Data;
7
import net.minecraft.commands.CommandSourceStack;
8
import net.minecraft.commands.Commands;
9
import net.minecraft.network.chat.Component;
10
import net.minecraft.world.item.CreativeModeTab;
11
import net.minecraft.world.item.ItemStack;
12
import net.minecraft.world.item.Items;
13
import net.minecraftforge.api.distmarker.Dist;
14
import net.minecraftforge.api.distmarker.OnlyIn;
15
import net.minecraftforge.client.event.RegisterKeyMappingsEvent;
16
import net.minecraftforge.common.MinecraftForge;
17
import net.minecraftforge.event.RegisterCommandsEvent;
18
import net.minecraftforge.event.server.ServerAboutToStartEvent;
19
import net.minecraftforge.event.server.ServerStartedEvent;
20
import net.minecraftforge.event.server.ServerStartingEvent;
21
import net.minecraftforge.event.server.ServerStoppingEvent;
22
import net.minecraftforge.eventbus.api.EventPriority;
23
import net.minecraftforge.eventbus.api.SubscribeEvent;
24
import net.minecraftforge.fml.DistExecutor;
25
import net.minecraftforge.fml.ModContainer;
26
import net.minecraftforge.fml.ModList;
27
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
28
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
29
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
30
import net.minecraftforge.registries.ForgeRegistries;
31
import net.minecraftforge.registries.NewRegistryEvent;
32
import net.minecraftforge.registries.RegisterEvent;
33
import org.apache.commons.lang3.tuple.Pair;
34
import org.apache.logging.log4j.Level;
35
import org.cyclops.cyclopscore.client.key.IKeyRegistry;
36
import org.cyclops.cyclopscore.client.key.KeyRegistry;
37
import org.cyclops.cyclopscore.command.CommandConfig;
38
import org.cyclops.cyclopscore.command.CommandVersion;
39
import org.cyclops.cyclopscore.config.ConfigHandler;
40
import org.cyclops.cyclopscore.config.extendedconfig.CreativeModeTabConfig;
41
import org.cyclops.cyclopscore.helper.LoggerHelper;
42
import org.cyclops.cyclopscore.modcompat.IMCHandler;
43
import org.cyclops.cyclopscore.modcompat.ModCompatLoader;
44
import org.cyclops.cyclopscore.modcompat.capabilities.CapabilityConstructorRegistry;
45
import org.cyclops.cyclopscore.network.PacketHandler;
46
import org.cyclops.cyclopscore.persist.world.WorldStorage;
47
import org.cyclops.cyclopscore.proxy.IClientProxy;
48
import org.cyclops.cyclopscore.proxy.ICommonProxy;
49

50
import javax.annotation.Nullable;
51
import java.util.List;
52
import java.util.Map;
53
import java.util.function.Consumer;
54

55
/**
56
 * Base class for mods which adds a few convenience methods.
57
 * Dont forget to call the supers for the init events.
58
 * @author rubensworks
59
 */
60
@Data
×
61
public abstract class ModBase<T extends ModBase> {
62

63
    public static final EnumReferenceKey<String> REFKEY_TEXTURE_PATH_GUI = EnumReferenceKey.create("texture_path_gui", String.class);
×
64
    public static final EnumReferenceKey<String> REFKEY_TEXTURE_PATH_MODELS = EnumReferenceKey.create("texture_path_models", String.class);
×
65
    public static final EnumReferenceKey<String> REFKEY_TEXTURE_PATH_SKINS = EnumReferenceKey.create("texture_path_skins", String.class);
×
66
    public static final EnumReferenceKey<Boolean> REFKEY_RETROGEN = EnumReferenceKey.create("retrogen", Boolean.class);
×
67
    public static final EnumReferenceKey<Boolean> REFKEY_CRASH_ON_INVALID_RECIPE = EnumReferenceKey.create("crash_on_invalid_recipe", Boolean.class);
×
68
    public static final EnumReferenceKey<Boolean> REFKEY_CRASH_ON_MODCOMPAT_CRASH = EnumReferenceKey.create("crash_on_modcompat_crash", Boolean.class);
×
69
    public static final EnumReferenceKey<Boolean> REFKEY_INFOBOOK_REWARDS = EnumReferenceKey.create("rewards", Boolean.class);
×
70

71
    private final String modId;
×
72
    private final LoggerHelper loggerHelper;
×
73
    private final ConfigHandler configHandler;
×
74
    private final Map<EnumReferenceKey<?>, Object> genericReference = Maps.newHashMap();
×
75
    private final List<WorldStorage> worldStorages = Lists.newLinkedList();
×
76
    private final RegistryManager registryManager;
×
77
    private final IKeyRegistry keyRegistry;
×
78
    private final PacketHandler packetHandler;
×
79
    private final ModCompatLoader modCompatLoader;
×
80
    private final CapabilityConstructorRegistry capabilityConstructorRegistry;
×
81
    private final IMCHandler imcHandler;
×
82

83
    private ICommonProxy proxy;
84
    private ModContainer container;
85

86
    @Nullable
×
87
    private CreativeModeTab defaultCreativeTab = null;
×
88
    private final List<Pair<ItemStack, CreativeModeTab.TabVisibility>> defaultCreativeTabEntries = Lists.newArrayList();
×
89

90
    public ModBase(String modId, Consumer<T> instanceSetter) {
×
91
        instanceSetter.accept((T) this);
×
92
        this.modId = modId;
×
93
        this.loggerHelper = constructLoggerHelper();
×
94
        this.configHandler = constructConfigHandler();
×
95
        this.registryManager = constructRegistryManager();
×
96
        this.keyRegistry = new KeyRegistry();
×
97
        this.packetHandler = constructPacketHandler();
×
98
        this.modCompatLoader = constructModCompatLoader();
×
99
        this.capabilityConstructorRegistry = constructCapabilityConstructorRegistry();
×
100
        this.imcHandler = constructIMCHandler();
×
101

102
        // Register listeners
103
        FMLJavaModLoadingContext.get().getModEventBus().addListener(this::setup);
×
104
        DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> FMLJavaModLoadingContext.get().getModEventBus().addListener(this::setupClient));
×
105
        FMLJavaModLoadingContext.get().getModEventBus().addListener(EventPriority.LOWEST, this::afterRegistriesCreated);
×
106
        FMLJavaModLoadingContext.get().getModEventBus().addListener(EventPriority.HIGHEST, this::beforeRegistriedFilled);
×
107
        DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> FMLJavaModLoadingContext.get().getModEventBus().addListener(this::onRegisterKeyMappings));
×
108
        MinecraftForge.EVENT_BUS.register(this);
×
109

110
        // Register proxies
111
        DistExecutor.runForDist(
×
112
                () -> () -> this.proxy = this.constructClientProxy(),
×
113
                () -> () -> this.proxy = this.constructCommonProxy()
×
114
        );
115

116
        populateDefaultGenericReferences();
×
117

118
        // Initialize config handler
119
        this.onConfigsRegister(getConfigHandler());
×
120
        getConfigHandler().initialize(Lists.newArrayList());
×
121
        getConfigHandler().loadModInit();
×
122

123
        // Register default creative tab
124
        if (this.hasDefaultCreativeModeTab()) {
×
125
            this.getConfigHandler().addConfigurable(this.constructDefaultCreativeModeTabConfig());
×
126
        }
127

128
        loadModCompats(getModCompatLoader());
×
129
    }
×
130

131
    public String getModName() {
132
        return getContainer().getModInfo().getDisplayName();
×
133
    }
134

135
    /**
136
     * @return The mod container of this mod.
137
     */
138
    public ModContainer getContainer() {
139
        if (container == null) {
×
140
            container = ModList.get().getModContainerByObject(this).get();
×
141
        }
142
        return container;
×
143
    }
144

145
    protected LoggerHelper constructLoggerHelper() {
146
        return new LoggerHelper(getModId());
×
147
    }
148

149
    protected ConfigHandler constructConfigHandler() {
150
        return new ConfigHandler(this);
×
151
    }
152

153
    protected RegistryManager constructRegistryManager() {
154
        return new RegistryManager();
×
155
    }
156

157
    protected PacketHandler constructPacketHandler() {
158
        return new PacketHandler(this);
×
159
    }
160

161
    protected ModCompatLoader constructModCompatLoader() {
162
        return new ModCompatLoader(this);
×
163
    }
164

165
    protected CapabilityConstructorRegistry constructCapabilityConstructorRegistry() {
166
        return new CapabilityConstructorRegistry(this);
×
167
    }
168

169
    protected IMCHandler constructIMCHandler() {
170
        return new IMCHandler(this);
×
171
    }
172

173
    protected LiteralArgumentBuilder<CommandSourceStack> constructBaseCommand() {
174
        LiteralArgumentBuilder<CommandSourceStack> root = Commands.literal(this.getModId());
×
175

176
        root.then(CommandConfig.make(this));
×
177
        root.then(CommandVersion.make(this));
×
178

179
        return root;
×
180
    }
181

182
    /**
183
     * Save a mod value.
184
     * @param key The key.
185
     * @param value The value.
186
     * @param <T> The value type.
187
     */
188
    public <T> void putGenericReference(EnumReferenceKey<T> key, T value) {
189
        genericReference.put(key, value);
×
190
    }
×
191

192
    private void populateDefaultGenericReferences() {
193
        putGenericReference(REFKEY_TEXTURE_PATH_GUI, "textures/gui/");
×
194
        putGenericReference(REFKEY_TEXTURE_PATH_MODELS, "textures/models/");
×
195
        putGenericReference(REFKEY_TEXTURE_PATH_SKINS, "textures/skins/");
×
196
        putGenericReference(REFKEY_RETROGEN, false);
×
197
        putGenericReference(REFKEY_CRASH_ON_INVALID_RECIPE, false);
×
198
        putGenericReference(REFKEY_CRASH_ON_MODCOMPAT_CRASH, false);
×
199
        putGenericReference(REFKEY_INFOBOOK_REWARDS, true);
×
200
    }
×
201

202
    /**
203
     * This is called only once to let the mod compatibilities register themselves.
204
     * @param modCompatLoader The loader.
205
     */
206
    protected void loadModCompats(ModCompatLoader modCompatLoader) {
207

208
    }
×
209

210
    /**
211
     * Get the value for a generic reference key.
212
     * The default keys can be found in {@link org.cyclops.cyclopscore.init.ModBase}.
213
     * @param key The key of a value.
214
     * @param <T> The type of value.
215
     * @return The value for the given key.
216
     */
217
    @SuppressWarnings("unchecked")
218
    public <T> T getReferenceValue(EnumReferenceKey<T> key) {
219
        if(!genericReference.containsKey(key)) throw new IllegalArgumentException("Could not find " + key + " as generic reference item.");
×
220
        return (T) genericReference.get(key);
×
221
    }
222

223
    /**
224
     * Log a new info message for this mod.
225
     * @param message The message to show.
226
     */
227
    public void log(String message) {
228
        log(Level.INFO, message);
×
229
    }
×
230

231
    /**
232
     * Log a new message of the given level for this mod.
233
     * @param level The level in which the message must be shown.
234
     * @param message The message to show.
235
     */
236
    public void log(Level level, String message) {
237
        loggerHelper.log(level, message);
×
238
    }
×
239

240
    /**
241
     * Called on the Forge setup lifecycle event.
242
     * @param event The setup event.
243
     */
244
    protected void setup(FMLCommonSetupEvent event) {
245
        log(Level.TRACE, "setup()");
×
246

247
        // Iterate over all configs again
248
        getConfigHandler().loadSetup();
×
249

250
        // Register proxy things
251
        ICommonProxy proxy = getProxy();
×
252
        if(proxy != null) {
×
253
            proxy.registerEventHooks();
×
254
            getPacketHandler().init();
×
255
            proxy.registerPacketHandlers(getPacketHandler());
×
256
            proxy.registerTickHandlers();
×
257
        }
258
    }
×
259

260
    /**
261
     * Called on the Forge client setup lifecycle event.
262
     * @param event The setup event.
263
     */
264
    protected void setupClient(FMLClientSetupEvent event) {
265
        // Register proxy things
266
        ICommonProxy proxy = getProxy();
×
267
        if(proxy != null) {
×
268
            proxy.registerRenderers();
×
269
        }
270
    }
×
271

272
    protected void onRegisterKeyMappings(RegisterKeyMappingsEvent event) {
273
        ICommonProxy proxy = getProxy();
×
274
        if(proxy != null) {
×
275
            proxy.registerKeyBindings(getKeyRegistry(), event);
×
276
        }
277
    }
×
278

279
    /**
280
     * Load things after Forge registries have been created.
281
     * @param event The Forge registry creation event.
282
     */
283
    private void afterRegistriesCreated(NewRegistryEvent event) {
284
        getConfigHandler().loadForgeRegistries();
×
285
    }
×
286

287
    /**
288
     * Load things before Forge registries are being filled.
289
     * @param event The Forge registry filling event.
290
     */
291
    private void beforeRegistriedFilled(RegisterEvent event) {
292
        if (event.getRegistryKey().equals(ForgeRegistries.BLOCKS.getRegistryKey())) {
×
293
            // We only need to call this once, and the blocks event is emitted first.
294
            getConfigHandler().loadForgeRegistriesFilled();
×
295
        }
296
    }
×
297

298
    /**
299
     * Register the things that are related to when the server is starting.
300
     * @param event The Forge server starting event.
301
     */
302
    @SubscribeEvent
303
    protected void onServerStarting(ServerStartingEvent event) {
304

305
    }
×
306

307
    @SubscribeEvent
308
    protected void onRegisterCommands(RegisterCommandsEvent event) {
309
        event.getDispatcher().register(constructBaseCommand());
×
310
    }
×
311

312
    /**
313
     * Register the things that are related to when the server is about to start.
314
     * @param event The Forge server about to start event.
315
     */
316
    @SubscribeEvent
317
    protected void onServerAboutToStart(ServerAboutToStartEvent event) {
318
        for(WorldStorage worldStorage : worldStorages) {
×
319
            worldStorage.onAboutToStartEvent(event);
×
320
        }
×
321
    }
×
322

323
    /**
324
     * Register the things that are related to server starting.
325
     * @param event The Forge server started event.
326
     */
327
    @SubscribeEvent
328
    protected void onServerStarted(ServerStartedEvent event) {
329
        for(WorldStorage worldStorage : worldStorages) {
×
330
            worldStorage.onStartedEvent(event);
×
331
        }
×
332
    }
×
333

334
    /**
335
     * Register the things that are related to server stopping, like persistent storage.
336
     * @param event The Forge server stopping event.
337
     */
338
    @SubscribeEvent
339
    protected void onServerStopping(ServerStoppingEvent event) {
340
        for(WorldStorage worldStorage : worldStorages) {
×
341
            worldStorage.onStoppingEvent(event);
×
342
        }
×
343
    }
×
344

345
    /**
346
     * Register a new world storage type.
347
     * Make sure to call this at least before the event
348
     * {@link net.minecraftforge.event.server.ServerStartedEvent} is called.
349
     * @param worldStorage The world storage to register.
350
     */
351
    public void registerWorldStorage(WorldStorage worldStorage) {
352
        worldStorages.add(worldStorage);
×
353
    }
×
354

355
    @OnlyIn(Dist.CLIENT)
356
    protected abstract IClientProxy constructClientProxy();
357

358
    @OnlyIn(Dist.DEDICATED_SERVER)
359
    protected abstract ICommonProxy constructCommonProxy();
360

361
    public void registerDefaultCreativeTabEntry(ItemStack itemStack, CreativeModeTab.TabVisibility visibility) {
362
        if (defaultCreativeTabEntries == null) {
×
363
            throw new IllegalStateException("Tried to register default tab entries after the CreativeModeTabEvent.BuildContents event");
×
364
        }
365
        if (itemStack.getCount() != 1) {
×
366
            throw new IllegalStateException("Tried to register default tab entries with a non-1-count ItemStack");
×
367
        }
368
        defaultCreativeTabEntries.add(Pair.of(itemStack, visibility));
×
369
    }
×
370

371
    protected CreativeModeTabConfig constructDefaultCreativeModeTabConfig() {
372
        return new CreativeModeTabConfig(this, "default", (config) -> this.defaultCreativeTab = this.constructDefaultCreativeModeTab(CreativeModeTab.builder()).build());
×
373
    }
374

375
    protected CreativeModeTab.Builder constructDefaultCreativeModeTab(CreativeModeTab.Builder builder) {
376
        return builder
×
377
                .title(Component.translatable("itemGroup." + getModId()))
×
378
                .icon(() -> new ItemStack(Items.BARRIER))
×
379
                .displayItems((parameters, output) -> {
×
380
                    for (Pair<ItemStack, CreativeModeTab.TabVisibility> entry : defaultCreativeTabEntries) {
×
381
                        output.accept(entry.getLeft(), entry.getRight());
×
382
                    }
×
383
                });
×
384
    }
385

386
    /**
387
     * @return If a default creative tab should be constructed.
388
     *         If so, make sure to override {@link #constructDefaultCreativeModeTab(CreativeModeTab.Builder)}.
389
     */
390
    protected boolean hasDefaultCreativeModeTab() {
391
        return true;
×
392
    };
393

394
    /**
395
     * Called when the configs should be registered.
396
     * @param configHandler The config handler to register to.
397
     */
398
    protected void onConfigsRegister(ConfigHandler configHandler) {
399

400
    }
×
401

402
    /**
403
     * @return The proxy for this mod.
404
     */
405
    public ICommonProxy getProxy() {
406
        return this.proxy;
×
407
    }
408

409
    @Override
410
    public String toString() {
411
        return getModId();
×
412
    }
413

414
    @Override
415
    public int hashCode() {
416
        return toString().hashCode();
×
417
    }
418

419
    @Override
420
    public boolean equals(Object object) {
421
        return object == this;
×
422
    }
423

424
    /**
425
     * Get the mod by id.
426
     * @param modId The mod id.
427
     * @return The mod instance or null.
428
     */
429
    public static ModBase get(String modId) {
430
        ModContainer modContainer = ModList.get().getModContainerById(modId).orElse(null);
×
431
        Object mod = modContainer.getMod();
×
432
        if (mod instanceof ModBase) {
×
433
            return (ModBase) mod;
×
434
        }
435
        return null;
×
436
    }
437

438
    /**
439
     * Unique references to values that can be registered inside a mod.
440
     * @param <T> The type of value.
441
     */
442
    @Data
×
443
    public static class EnumReferenceKey<T> {
444

445
        private final String key;
×
446
        private final Class<T> type;
×
447

448
        private EnumReferenceKey(String key, Class<T> type) {
×
449
            this.key = key;
×
450
            this.type = type;
×
451
        }
×
452

453
        public static <T> EnumReferenceKey<T> create(String key, Class<T> type) {
454
            return new EnumReferenceKey<>(key, type);
×
455
        }
456

457
    }
458

459
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc