Skip to content

Commit 95f0022

Browse files
committed
Add optional support for GrandPower (mekanism/Mekanism-Feature-Requests#679)
1 parent edaeb09 commit 95f0022

File tree

9 files changed

+300
-2
lines changed

9 files changed

+300
-2
lines changed

build.gradle

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -335,7 +335,7 @@ repositories { RepositoryHandler handler ->
335335
exclusiveRepo(handler, 'https://dogforce-games.com/maven/', 'dev.gigaherz.jsonthings')
336336
exclusiveRepo(handler, 'https://maven2.bai.lol', 'lol.bai', 'mcp.mobius.waila')//WTHIT
337337
exclusiveRepo(handler, 'https://www.cursemaven.com', 'curse.maven')
338-
exclusiveRepo(handler, 'https://modmaven.dev/', 'appeng', 'mcjty.theoneprobe')
338+
exclusiveRepo(handler, 'https://modmaven.dev/', 'appeng', 'mcjty.theoneprobe', 'dev.technici4n')
339339
exclusiveRepo(handler, 'https://maven.minecraftforge.net/releases/', 'com.github.glitchfiend')
340340
exclusiveRepo(handler, 'https://maven.thiakil.com', 'com.thiakil', 'moze_intel')
341341
exclusiveRepo(handler, 'https://maven.parchmentmc.org/', 'org.parchmentmc.data')
@@ -404,6 +404,7 @@ dependencies {
404404
//compileOnly("curse.maven:projecte-api-226410:${projecte_api_id}")
405405
compileOnly('moze_intel:ProjectE-api:1.0.1')
406406
compileOnly("curse.maven:flux-networks-248020:${flux_networks_id}")
407+
compileOnly("dev.technici4n:GrandPower:${grand_power_version}")
407408
compileOnly("top.theillusivec4.curios:curios-neoforge:${curios_version}:api")
408409
compileOnly("com.blamejared.recipestages:RecipeStages:${recipe_stages_version}")
409410
compileOnly("curse.maven:opencomputers2-437654:${oc2_id}")
@@ -638,7 +639,7 @@ if (System.getenv('CURSEFORGE_KEY') != null || project.hasProperty('curseforgeKe
638639
'biomes-o-plenty',
639640
//Misc
640641
'applied-energistics-2', 'ctm', 'curios-continuation', 'dark-mode-everywhere', 'female-gender-forge', 'flux-networks',
641-
'json-things', 'perviaminvenire', 'projecte', 'recipe-stages'
642+
'grandpower', 'json-things', 'perviaminvenire', 'projecte', 'recipe-stages'
642643
)
643644
}
644645

gradle.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ crafttweaker_version=20.0.15
4141
ctm_version=1.2.0+1
4242
curios_version=9.0.4+1.21
4343
emi_version=1.1.8
44+
grand_power_version=3.0.0
4445
jade_api_id=5427895
4546
jade_id=5493270
4647
jei_version=19.0.0.14

src/main/java/mekanism/common/config/GeneralConfig.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ public class GeneralConfig extends BaseMekanismConfig {
7676
public final CachedBooleanValue blacklistForge;
7777
public final CachedFloatingLongValue forgeConversionRate;
7878
public final CachedBooleanValue blacklistFluxNetworks;
79+
public final CachedBooleanValue blacklistGrandPower;
7980
public final CachedFloatingLongValue FROM_H2;
8081
public final CachedFloatingLongValue maxEnergyPerSteam;
8182
//Radiation
@@ -208,6 +209,9 @@ public class GeneralConfig extends BaseMekanismConfig {
208209
blacklistFluxNetworks = CachedBooleanValue.wrap(this, builder.comment("Disables Flux Networks higher throughput Forge Energy (FE,RF,IF,uF,CF) power integration. Requires world restart (server-side option in SMP). Note: Disabling Forge Energy integration also disables this.")
209210
.worldRestart()
210211
.define("blacklistFluxNetworks", false));
212+
blacklistGrandPower = CachedBooleanValue.wrap(this, builder.comment("Disables Grand Power higher throughput Forge Energy (FE,RF,IF,uF,CF) power integration. Requires world restart (server-side option in SMP). Note: Disabling Forge Energy integration also disables this.")
213+
.worldRestart()
214+
.define("blacklistGrandPower", false));
211215
FROM_H2 = CachedFloatingLongValue.define(this, builder, "How much energy is produced per mB of Hydrogen, also affects Electrolytic Separator usage, Ethene burn rate and Gas generator energy capacity.",
212216
"HydrogenEnergyDensity", FloatingLong.createConst(200), CachedFloatingLongValue.POSITIVE);
213217
maxEnergyPerSteam = CachedFloatingLongValue.define(this, builder, "Maximum Joules per mB of Steam. Also affects Thermoelectric Boiler.",

src/main/java/mekanism/common/integration/MekanismHooks.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ public final class MekanismHooks {
3333
public static final String CURIOS_MODID = "curios";
3434
public static final String DARK_MODE_EVERYWHERE_MODID = "darkmodeeverywhere";
3535
public static final String FLUX_NETWORKS_MOD_ID = "fluxnetworks";
36+
public static final String GRAND_POWER_MOD_ID = "grandpower";
3637
public static final String JEI_MOD_ID = "jei";
3738
public static final String EMI_MOD_ID = "emi";
3839
public static final String JEITWEAKER_MOD_ID = "jeitweaker";
@@ -49,6 +50,7 @@ public final class MekanismHooks {
4950
public final boolean DMELoaded;
5051
public final boolean EmiLoaded;
5152
public final boolean FluxNetworksLoaded;
53+
public final boolean GrandPowerLoaded;
5254
public final boolean JEILoaded;
5355
public final boolean JsonThingsLoaded;
5456
public final boolean OC2Loaded;
@@ -67,6 +69,7 @@ public MekanismHooks() {
6769
DMELoaded = loadedCheck.test(DARK_MODE_EVERYWHERE_MODID);
6870
EmiLoaded = loadedCheck.test(EMI_MOD_ID);
6971
FluxNetworksLoaded = loadedCheck.test(FLUX_NETWORKS_MOD_ID);
72+
GrandPowerLoaded = loadedCheck.test(GRAND_POWER_MOD_ID);
7073
JEILoaded = loadedCheck.test(JEI_MOD_ID);
7174
JsonThingsLoaded = loadedCheck.test(JSON_THINGS_MOD_ID);
7275
OC2Loaded = loadedCheck.test(OC2_MOD_ID);

src/main/java/mekanism/common/integration/energy/EnergyCompatUtils.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import mekanism.common.capabilities.Capabilities;
77
import mekanism.common.integration.energy.fluxnetworks.FNEnergyCompat;
88
import mekanism.common.integration.energy.forgeenergy.ForgeEnergyCompat;
9+
import mekanism.common.integration.energy.grandpower.GPEnergyCompat;
910
import mekanism.common.registration.impl.TileEntityTypeDeferredRegister.BlockEntityTypeBuilder;
1011
import mekanism.common.tile.base.CapabilityTileEntity;
1112
import net.minecraft.core.BlockPos;
@@ -33,6 +34,8 @@ private EnergyCompatUtils() {
3334
private static final List<IEnergyCompat> energyCompats = List.of(
3435
//We always have our own energy capability as the first one we check
3536
new StrictEnergyCompat(),
37+
//Note: We check the Grand Power capability above Forge's so that we allow it to use the higher throughput amount supported by Grand Power
38+
new GPEnergyCompat(),
3639
//Note: We check the Flux Networks capability above Forge's so that we allow it to use the higher throughput amount supported by Flux Networks
3740
new FNEnergyCompat(),
3841
new ForgeEnergyCompat()
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package mekanism.common.integration.energy.grandpower;
2+
3+
import dev.technici4n.grandpower.api.ILongEnergyStorage;
4+
import mekanism.common.capabilities.MultiTypeCapability;
5+
6+
public class GPCapability {
7+
8+
//Note: this must be in a separate class to avoid class loading issues
9+
static final MultiTypeCapability<ILongEnergyStorage> ENERGY = new MultiTypeCapability<>(ILongEnergyStorage.BLOCK, ILongEnergyStorage.ITEM, ILongEnergyStorage.ENTITY);
10+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package mekanism.common.integration.energy.grandpower;
2+
3+
import dev.technici4n.grandpower.api.ILongEnergyStorage;
4+
import mekanism.api.annotations.NothingNullByDefault;
5+
import mekanism.api.energy.IStrictEnergyHandler;
6+
import mekanism.common.Mekanism;
7+
import mekanism.common.capabilities.MultiTypeCapability;
8+
import mekanism.common.config.MekanismConfig;
9+
import mekanism.common.integration.energy.IEnergyCompat;
10+
import mekanism.common.util.UnitDisplayUtils.EnergyUnit;
11+
import net.neoforged.neoforge.capabilities.ICapabilityProvider;
12+
13+
@NothingNullByDefault
14+
public class GPEnergyCompat implements IEnergyCompat {
15+
16+
@Override
17+
public MultiTypeCapability<ILongEnergyStorage> getCapability() {
18+
return GPCapability.ENERGY;
19+
}
20+
21+
@Override
22+
public boolean isUsable() {
23+
return capabilityExists() && isConfigEnabled();
24+
}
25+
26+
private boolean isConfigEnabled() {
27+
return EnergyUnit.FORGE_ENERGY.isEnabled() && !MekanismConfig.general.blacklistGrandPower.getOrDefault();
28+
}
29+
30+
@Override
31+
public boolean capabilityExists() {
32+
return Mekanism.hooks.GrandPowerLoaded;
33+
}
34+
35+
@Override
36+
public <OBJECT, CONTEXT> ICapabilityProvider<OBJECT, CONTEXT, ?> getProviderAs(ICapabilityProvider<OBJECT, CONTEXT, IStrictEnergyHandler> provider) {
37+
return (obj, ctx) -> {
38+
IStrictEnergyHandler handler = provider.getCapability(obj, ctx);
39+
return handler != null && isConfigEnabled() ? wrapStrictEnergyHandler(handler) : null;
40+
};
41+
}
42+
43+
@Override
44+
public Object wrapStrictEnergyHandler(IStrictEnergyHandler handler) {
45+
return new GPIntegration(handler);
46+
}
47+
48+
@Override
49+
public IStrictEnergyHandler wrapAsStrictEnergyHandler(Object handler) {
50+
return new GPStrictEnergyHandler((ILongEnergyStorage) handler);
51+
}
52+
}
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
package mekanism.common.integration.energy.grandpower;
2+
3+
import dev.technici4n.grandpower.api.ILongEnergyStorage;
4+
import mekanism.api.Action;
5+
import mekanism.api.energy.IStrictEnergyHandler;
6+
import mekanism.api.math.FloatingLong;
7+
import mekanism.common.util.UnitDisplayUtils.EnergyUnit;
8+
9+
public class GPIntegration implements ILongEnergyStorage {
10+
11+
private final IStrictEnergyHandler handler;
12+
13+
public GPIntegration(IStrictEnergyHandler handler) {
14+
this.handler = handler;
15+
}
16+
17+
@Override
18+
public long receive(long maxReceive, boolean simulate) {
19+
if (maxReceive <= 0) {
20+
return 0;
21+
}
22+
Action action = Action.get(!simulate);
23+
FloatingLong toInsert = EnergyUnit.FORGE_ENERGY.convertFrom(maxReceive);
24+
if (action.execute()) {
25+
//Before we can actually execute it we need to simulate to calculate how much we can actually insert
26+
FloatingLong simulatedRemainder = handler.insertEnergy(toInsert, Action.SIMULATE);
27+
if (simulatedRemainder.equals(toInsert)) {
28+
//Nothing can be inserted at all, just exit quickly
29+
return 0;
30+
}
31+
FloatingLong simulatedInserted = toInsert.subtract(simulatedRemainder);
32+
//Convert how much we could insert back to FE so that it gets appropriately clamped so that for example 1.5 FE gets treated
33+
// as trying to insert 1 FE for how much we actually will accept, and then convert that clamped value to go back to Joules
34+
// so that we don't allow inserting a tiny bit of extra for "free" and end up creating power from nowhere
35+
toInsert = convertToAndBack(simulatedInserted);
36+
if (toInsert.isZero()) {
37+
//If converting back and forth between FE and Joules causes us to be clamped at zero, that means we can't accept anything or could only
38+
// accept a partial amount; we need to exit early returning that we couldn't insert anything
39+
return 0;
40+
}
41+
}
42+
FloatingLong remainder = handler.insertEnergy(toInsert, action);
43+
if (remainder.equals(toInsert)) {
44+
//Nothing can be inserted at all, just exit quickly
45+
return 0;
46+
}
47+
FloatingLong inserted = toInsert.subtract(remainder);
48+
return EnergyUnit.FORGE_ENERGY.convertToAsLong(inserted);
49+
}
50+
51+
@Override
52+
public long extract(long maxExtract, boolean simulate) {
53+
if (maxExtract <= 0) {
54+
return 0;
55+
}
56+
Action action = Action.get(!simulate);
57+
FloatingLong toExtract = EnergyUnit.FORGE_ENERGY.convertFrom(maxExtract);
58+
if (action.execute()) {
59+
//Before we can actually execute it we need to simulate to calculate how much we can actually extract in our other units
60+
FloatingLong simulatedExtracted = handler.extractEnergy(toExtract, Action.SIMULATE);
61+
//Convert how much we could extract back to FE so that it gets appropriately clamped so that for example 1.5 FE gets treated
62+
// as trying to extract 1 FE for how much we can actually provide, and then convert that clamped value to go back to Joules
63+
// so that we don't allow extracting a tiny bit into nowhere causing some power to be voided
64+
// This is important as otherwise if we can have 1.5 FE extracted, we will reduce our amount by 1.5 FE but the caller will only receive 1 FE
65+
toExtract = convertToAndBack(simulatedExtracted);
66+
if (toExtract.isZero()) {
67+
//If converting back and forth between FE and Joules causes us to be clamped at zero, that means we can't provide anything or could only
68+
// provide a partial amount; we need to exit early returning that nothing could be extracted
69+
return 0;
70+
}
71+
}
72+
FloatingLong extracted = handler.extractEnergy(toExtract, action);
73+
return EnergyUnit.FORGE_ENERGY.convertToAsLong(extracted);
74+
}
75+
76+
private FloatingLong convertToAndBack(FloatingLong value) {
77+
return EnergyUnit.FORGE_ENERGY.convertFrom(EnergyUnit.FORGE_ENERGY.convertToAsLong(value));
78+
}
79+
80+
@Override
81+
public long getAmount() {
82+
long energy = 0;
83+
for (int container = 0, containers = handler.getEnergyContainerCount(); container < containers; container++) {
84+
long total = EnergyUnit.FORGE_ENERGY.convertToAsLong(handler.getEnergy(container));
85+
if (total > Long.MAX_VALUE - energy) {
86+
//Ensure we don't overflow
87+
return Long.MAX_VALUE;
88+
}
89+
energy += total;
90+
}
91+
return energy;
92+
}
93+
94+
@Override
95+
public long getCapacity() {
96+
long maxEnergy = 0;
97+
for (int container = 0, containers = handler.getEnergyContainerCount(); container < containers; container++) {
98+
long max = EnergyUnit.FORGE_ENERGY.convertToAsLong(handler.getMaxEnergy(container));
99+
if (max > Long.MAX_VALUE - maxEnergy) {
100+
//Ensure we don't overflow
101+
return Long.MAX_VALUE;
102+
}
103+
maxEnergy += max;
104+
}
105+
return maxEnergy;
106+
}
107+
108+
@Override
109+
public boolean canExtract() {
110+
//Mark that we can receive energy if we can insert energy
111+
if (!handler.extractEnergy(FloatingLong.ONE, Action.SIMULATE).isZero()) {
112+
return true;
113+
}
114+
//Or all our containers are empty. This isn't fully accurate but will give the best
115+
// accuracy to other mods of if we may be able to extract given we are predicate based
116+
// instead of having strict can receive checks
117+
for (int container = 0, containers = handler.getEnergyContainerCount(); container < containers; container++) {
118+
if (!handler.getEnergy(container).isZero()) {
119+
return false;
120+
}
121+
}
122+
return true;
123+
}
124+
125+
@Override
126+
public boolean canReceive() {
127+
//Mark that we can receive energy if we can insert energy
128+
if (handler.insertEnergy(FloatingLong.ONE, Action.SIMULATE).smallerThan(FloatingLong.ONE)) {
129+
return true;
130+
}
131+
//Or all our containers are full. This isn't fully accurate but will give the best
132+
// accuracy to other mods of if we may be able to receive given we are predicate based
133+
// instead of having strict can receive checks
134+
for (int container = 0, containers = handler.getEnergyContainerCount(); container < containers; container++) {
135+
if (!handler.getNeededEnergy(container).isZero()) {
136+
return false;
137+
}
138+
}
139+
return true;
140+
}
141+
}
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
package mekanism.common.integration.energy.grandpower;
2+
3+
import dev.technici4n.grandpower.api.ILongEnergyStorage;
4+
import mekanism.api.Action;
5+
import mekanism.api.annotations.NothingNullByDefault;
6+
import mekanism.api.energy.IStrictEnergyHandler;
7+
import mekanism.api.math.FloatingLong;
8+
import mekanism.common.util.UnitDisplayUtils.EnergyUnit;
9+
import org.jetbrains.annotations.NotNull;
10+
11+
//Note: When wrapping joules to a whole number based energy type we don't need to add any extra simulation steps
12+
// for insert or extract when executing as we will always round down the number and just act upon a lower max requested amount
13+
@NothingNullByDefault
14+
public class GPStrictEnergyHandler implements IStrictEnergyHandler {
15+
16+
private final ILongEnergyStorage storage;
17+
18+
public GPStrictEnergyHandler(ILongEnergyStorage storage) {
19+
this.storage = storage;
20+
}
21+
22+
@Override
23+
public int getEnergyContainerCount() {
24+
return 1;
25+
}
26+
27+
@Override
28+
public FloatingLong getEnergy(int container) {
29+
return container == 0 ? EnergyUnit.FORGE_ENERGY.convertFrom(storage.getAmount()) : FloatingLong.ZERO;
30+
}
31+
32+
@Override
33+
public void setEnergy(int container, FloatingLong energy) {
34+
//Not implemented or directly needed
35+
}
36+
37+
@Override
38+
public FloatingLong getMaxEnergy(int container) {
39+
return container == 0 ? EnergyUnit.FORGE_ENERGY.convertFrom(storage.getCapacity()) : FloatingLong.ZERO;
40+
}
41+
42+
@Override
43+
public FloatingLong getNeededEnergy(int container) {
44+
return container == 0 ? EnergyUnit.FORGE_ENERGY.convertFrom(Math.max(0, storage.getCapacity() - storage.getAmount())) : FloatingLong.ZERO;
45+
}
46+
47+
@Override
48+
public FloatingLong insertEnergy(int container, FloatingLong amount, @NotNull Action action) {
49+
return container == 0 ? insertEnergy(amount, action) : amount;
50+
}
51+
52+
@Override
53+
public FloatingLong insertEnergy(FloatingLong amount, Action action) {
54+
if (storage.canReceive()) {
55+
long toInsert = EnergyUnit.FORGE_ENERGY.convertToAsLong(amount);
56+
if (toInsert > 0) {
57+
long inserted = storage.receive(toInsert, action.simulate());
58+
if (inserted > 0) {
59+
//Only bother converting back if any was inserted
60+
return amount.subtract(EnergyUnit.FORGE_ENERGY.convertFrom(inserted));
61+
}
62+
}
63+
}
64+
return amount;
65+
}
66+
67+
@Override
68+
public FloatingLong extractEnergy(int container, FloatingLong amount, @NotNull Action action) {
69+
return container == 0 ? extractEnergy(amount, action) : FloatingLong.ZERO;
70+
}
71+
72+
@Override
73+
public FloatingLong extractEnergy(FloatingLong amount, Action action) {
74+
if (storage.canExtract()) {
75+
long toExtract = EnergyUnit.FORGE_ENERGY.convertToAsLong(amount);
76+
if (toExtract > 0) {
77+
long extracted = storage.extract(toExtract, action.simulate());
78+
return EnergyUnit.FORGE_ENERGY.convertFrom(extracted);
79+
}
80+
}
81+
return FloatingLong.ZERO;
82+
}
83+
}

0 commit comments

Comments
 (0)