Skip to content

Commit eefdab9

Browse files
committed
Chore : Air Bladder
1 parent 9da6fc6 commit eefdab9

File tree

16 files changed

+176
-40
lines changed

16 files changed

+176
-40
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,3 +61,4 @@ Using code/assets from this project requires attribution in both cases and requi
6161
Credits;
6262
Thanks to [Gregtech Modern](https://github.com/GregTechCEu/GregTech-Modern) for plenty of useful code references and invaluable knowledge in learning Java.
6363
Thanks to ULSTICK's [GregTech: Refreshed](https://modrinth.com/resourcepack/gregtech-refreshed) for helping me learn how to make Jappa-style pixel art.
64+
Thanks to TFC Water Flasks for the Air Bladder Texture (Re-used the water bladder texture)

src/generated/resources/assets/cosmiccore/lang/en_ud.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1131,6 +1131,7 @@
11311131
"item.cosmiccore.aberrant_essence": "ǝɔuǝssƎ ʇuɐɹɹǝqⱯ9§",
11321132
"item.cosmiccore.abrasive_rosin_millstones": "sǝuoʇsןןıW uısoᴚ ǝʌısɐɹqⱯ",
11331133
"item.cosmiccore.advanced_gene_kit": "ʇıʞ ǝuǝ⅁ pǝɔuɐʌpⱯ",
1134+
"item.cosmiccore.air_bladder": "ɹǝppɐןᗺ ɹıⱯ",
11341135
"item.cosmiccore.akashic_processor": "ɹossǝɔoɹԀ ɔıɥsɐʞⱯ",
11351136
"item.cosmiccore.akashic_processor_assembly": "ʎןqɯǝssⱯ ɹossǝɔoɹԀ ɔıɥsɐʞⱯ",
11361137
"item.cosmiccore.akashic_processor_mainframe": "ǝɯɐɹɟuıɐW ɹossǝɔoɹԀ ɔıɥsɐʞⱯ",

src/generated/resources/assets/cosmiccore/lang/en_us.json

Lines changed: 3 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1131,6 +1131,7 @@
11311131
"item.cosmiccore.aberrant_essence": "§6Aberrant Essence",
11321132
"item.cosmiccore.abrasive_rosin_millstones": "Abrasive Rosin Millstones",
11331133
"item.cosmiccore.advanced_gene_kit": "Advanced Gene Kit",
1134+
"item.cosmiccore.air_bladder": "Air Bladder",
11341135
"item.cosmiccore.akashic_processor": "Akashic Processor",
11351136
"item.cosmiccore.akashic_processor_assembly": "Akashic Processor Assembly",
11361137
"item.cosmiccore.akashic_processor_mainframe": "Akashic Processor Mainframe",
@@ -1429,11 +1430,11 @@
14291430
"item.cosmiccore.simple_rebreather": "Simple Rebreather",
14301431
"item.cosmiccore.simple_rebreather.tooltip": "§7Reduces oxygen drain in §bThin Air§7 environments.",
14311432
"item.cosmiccore.somatic_processing_assembly": "Somatoprocessing Assembly Board",
1432-
"item.cosmiccore.soul_reader": "Soul Network Reader",
14331433
"item.cosmiccore.soul_cut_lucid_cpu_chip": "Soul Cut Lucid CPU Chip",
14341434
"item.cosmiccore.soul_mutilator": "Soul Mutilator",
14351435
"item.cosmiccore.soul_mutilator.tooltip": "A twisted instrument that can reshape your very soul.",
14361436
"item.cosmiccore.soul_mutilator.tooltip.warning": "This choice is permanent. Choose wisely.",
1437+
"item.cosmiccore.soul_reader": "Soul Network Reader",
14371438
"item.cosmiccore.sov_blood_orb": "Sovereign Blood Orb",
14381439
"item.cosmiccore.space_advanced_nanomuscle_chestplate": "Advanced NanoMuscle™ Space Suite Chestplate",
14391440
"item.cosmiccore.space_advanced_quarktech_chestplate": "Advanced QuarkTech™ Space Suite Chestplate",
@@ -2054,42 +2055,5 @@
20542055
"tooltip.cosmiccore.thermia_hatch_limit": "§cTemp. Limit: %sK",
20552056
"tooltip.gt_scythe.energy": "Energy: %s / %s EU",
20562057
"tooltip.gt_scythe.no_energy": "§cNot enough energy.",
2057-
"tooltip.gt_scythe.per_hit": "Cost: %s EU / hit",
2058-
"recipe.cosmiccore.raw_soul_in": "Consumes: %s Raw souls",
2059-
"recipe.cosmiccore.refined_soul_in": "Consumes: %s Refined souls",
2060-
"recipe.cosmiccore.proud_soul_in": "Consumes: %s Proud souls",
2061-
"recipe.cosmiccore.greedy_soul_in": "Consumes: %s Greedy souls",
2062-
"recipe.cosmiccore.lustful_soul_in": "Consumes: %s Lustful souls",
2063-
"recipe.cosmiccore.envious_soul_in": "Consumes: %s Envious souls",
2064-
"recipe.cosmiccore.gluttonous_soul_in": "Consumes: %s Gluttonous souls",
2065-
"recipe.cosmiccore.wrathful_soul_in": "Consumes: %s Wrathful souls",
2066-
"recipe.cosmiccore.slothful_soul_in": "Consumes: %s Slothful souls",
2067-
"recipe.cosmiccore.temporal_soul_in": "Consumes: %s Temporal souls",
2068-
"recipe.cosmiccore.raw_soul_out": "Produces: %s Raw souls",
2069-
"recipe.cosmiccore.refined_soul_out": "Produces: %s Refined souls",
2070-
"recipe.cosmiccore.proud_soul_out": "Produces: %s Proud souls",
2071-
"recipe.cosmiccore.greedy_soul_out": "Produces: %s Greedy souls",
2072-
"recipe.cosmiccore.lustful_soul_out": "Produces: %s Lustful souls",
2073-
"recipe.cosmiccore.envious_soul_out": "Produces: %s Envious souls",
2074-
"recipe.cosmiccore.gluttonous_soul_out": "Produces: %s Gluttonous souls",
2075-
"recipe.cosmiccore.wrathful_soul_out": "Produces: %s Wrathful souls",
2076-
"recipe.cosmiccore.slothful_soul_out": "Produces: %s Slothful souls",
2077-
"recipe.cosmiccore.temporal_soul_out": "Produces: %s Temporal souls",
2078-
"gui.cosmiccore.soul.raw.name": "Raw souls",
2079-
"gui.cosmiccore.soul.refined.name": "Refined souls",
2080-
"gui.cosmiccore.soul.proud.name": "Proud souls",
2081-
"gui.cosmiccore.soul.greedy.name": "Greedy souls",
2082-
"gui.cosmiccore.soul.lustful.name": "Lustful souls",
2083-
"gui.cosmiccore.soul.envious.name": "Envious souls",
2084-
"gui.cosmiccore.soul.gluttonous.name": "Gluttonous souls",
2085-
"gui.cosmiccore.soul.wrathful.name": "Wrathful souls",
2086-
"gui.cosmiccore.soul.slothful.name": "Slothful souls",
2087-
"gui.cosmiccore.soul.temporal.name": "Temporal souls",
2088-
"gui.cosmiccore.soul.empty_network": "Network is empty",
2089-
"gui.cosmiccore.soul.network_contents": "--- Network Contents ---",
2090-
"gui.cosmiccore.soul.reset": "Soul network has been reset",
2091-
"gui.cosmiccore.soul.add": "Added %s %s souls to the network",
2092-
"gui.cosmiccore.soul.remove": "removed %s %s souls to the network",
2093-
"gui.cosmiccore.soul.capacity": "Capacity: %s souls",
2094-
"gui.cosmiccore.soul.set_tier": "the network is now tier %s"
2058+
"tooltip.gt_scythe.per_hit": "Cost: %s EU / hit"
20952059
}

src/main/java/com/ghostipedia/cosmiccore/common/airControl/OxygenConfig.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,4 +63,12 @@ public static long getMaxOxygenTicks(Player player) {
6363

6464
/** Drain reduction multiplier for pressurized rebreather (0.25 = quarter drain) */
6565
public static final double PRESSURIZED_REBREATHER_DRAIN_MULT = 0.25;
66+
67+
// -------------------------------------------------------------------------
68+
// Air Bladder
69+
// -------------------------------------------------------------------------
70+
71+
public static final long AIR_BLADDER_RESTORE_TICKS = 1200; // 60 seconds of air per charge
72+
public static final int AIR_BLADDER_MAX_CHARGES = 3; // 3 uses before empty
73+
public static final int AIR_BLADDER_COOLDOWN = 40; // 2 second use cooldown
6674
}

src/main/java/com/ghostipedia/cosmiccore/common/airControl/OxygenLogic.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import net.minecraft.core.BlockPos;
1212
import net.minecraft.server.level.ServerLevel;
1313
import net.minecraft.server.level.ServerPlayer;
14+
import net.minecraft.world.effect.MobEffects;
1415
import net.minecraft.world.entity.EquipmentSlot;
1516
import net.minecraft.world.item.ItemStack;
1617
import net.minecraftforge.event.TickEvent;
@@ -81,7 +82,7 @@ public static void onPlayerTick(TickEvent.PlayerTickEvent event) {
8182
// Check if player is in a fluid (eyes submerged)
8283
BlockPos eyePos = BlockPos.containing(player.getX(), player.getEyeY(), player.getZ());
8384
boolean eyesInFluid = !level.getFluidState(eyePos).isEmpty();
84-
if (eyesInFluid) {
85+
if (eyesInFluid && !player.hasEffect(MobEffects.WATER_BREATHING)) {
8586
OxygenRules.Rates thinAir = OxygenRules.QUALITY_RATES.get(OxygenRules.AirQuality.THIN).copy();
8687
rates.oxygenDrainPerTick = Math.max(rates.oxygenDrainPerTick, thinAir.oxygenDrainPerTick);
8788
rates.oxygenRecoveryPerTick = 0.0; // No passive regen while submerged

src/main/java/com/ghostipedia/cosmiccore/common/data/CosmicItems.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66
import com.ghostipedia.cosmiccore.api.registries.CosmicRegistration;
77
import com.ghostipedia.cosmiccore.client.renderer.item.HaloItemRenderer;
88
import com.ghostipedia.cosmiccore.client.renderer.item.RadianceItemRenderer;
9+
import com.ghostipedia.cosmiccore.common.airControl.OxygenConfig;
910
import com.ghostipedia.cosmiccore.common.data.tag.item.CosmicItemTags;
11+
import com.ghostipedia.cosmiccore.common.item.AirBladderItem;
1012
import com.ghostipedia.cosmiccore.common.item.AsteroidItem;
1113
import com.ghostipedia.cosmiccore.common.item.AsteroidTargetingChipItem;
1214
import com.ghostipedia.cosmiccore.common.item.CosmicScytheItem;
@@ -2655,6 +2657,20 @@ public boolean isFoil(ItemStack stack) {
26552657
.defaultModel()
26562658
.register();
26572659

2660+
// -------------------------------------------------------------------------
2661+
// Air Bladder - pre-LV portable air
2662+
// -------------------------------------------------------------------------
2663+
2664+
public static final ItemEntry<AirBladderItem> AIR_BLADDER = REGISTRATE
2665+
.item("air_bladder", AirBladderItem::new)
2666+
.lang("Air Bladder")
2667+
.properties(p -> p.stacksTo(1))
2668+
.model((ctx, prov) -> {})
2669+
.onRegister(modelPredicate(
2670+
new ResourceLocation(CosmicCore.MOD_ID, "charges"),
2671+
stack -> (float) AirBladderItem.getCharges(stack) / OxygenConfig.AIR_BLADDER_MAX_CHARGES))
2672+
.register();
2673+
26582674
// -------------------------------------------------------------------------
26592675
// Oxygen Supply Tanks
26602676
// -------------------------------------------------------------------------
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
package com.ghostipedia.cosmiccore.common.item;
2+
3+
import com.ghostipedia.cosmiccore.common.airControl.OxygenBudgetCap;
4+
import com.ghostipedia.cosmiccore.common.airControl.OxygenConfig;
5+
import com.ghostipedia.cosmiccore.common.airControl.OxygenRules;
6+
7+
import net.minecraft.core.BlockPos;
8+
import net.minecraft.server.level.ServerLevel;
9+
import net.minecraft.server.level.ServerPlayer;
10+
import net.minecraft.sounds.SoundEvents;
11+
import net.minecraft.sounds.SoundSource;
12+
import net.minecraft.world.InteractionHand;
13+
import net.minecraft.world.InteractionResultHolder;
14+
import net.minecraft.world.entity.player.Player;
15+
import net.minecraft.world.item.Item;
16+
import net.minecraft.world.item.ItemStack;
17+
import net.minecraft.world.level.Level;
18+
19+
public class AirBladderItem extends Item {
20+
21+
private static final String TAG_CHARGES = "Charges";
22+
23+
public AirBladderItem(Properties props) {
24+
super(props);
25+
}
26+
27+
public static int getCharges(ItemStack stack) {
28+
if (!stack.hasTag() || !stack.getTag().contains(TAG_CHARGES)) {
29+
return OxygenConfig.AIR_BLADDER_MAX_CHARGES;
30+
}
31+
return stack.getTag().getInt(TAG_CHARGES);
32+
}
33+
34+
private static void setCharges(ItemStack stack, int charges) {
35+
stack.getOrCreateTag().putInt(TAG_CHARGES, charges);
36+
}
37+
38+
private static boolean isInSafeAir(ServerPlayer player) {
39+
ServerLevel serverLevel = player.serverLevel();
40+
int y = player.blockPosition().getY();
41+
OxygenRules.ResolvedAirRange resolved = OxygenRules.resolve(serverLevel.dimension(), y);
42+
if (resolved.airQuality != OxygenRules.AirQuality.SAFE) return false;
43+
44+
BlockPos eyePos = BlockPos.containing(player.getX(), player.getEyeY(), player.getZ());
45+
boolean eyesInFluid = !serverLevel.getFluidState(eyePos).isEmpty();
46+
return !eyesInFluid;
47+
}
48+
49+
@Override
50+
public InteractionResultHolder<ItemStack> use(Level level, Player player, InteractionHand hand) {
51+
ItemStack stack = player.getItemInHand(hand);
52+
53+
if (!level.isClientSide() && player instanceof ServerPlayer serverPlayer) {
54+
int charges = getCharges(stack);
55+
56+
if (charges < OxygenConfig.AIR_BLADDER_MAX_CHARGES && isInSafeAir(serverPlayer)) {
57+
setCharges(stack, OxygenConfig.AIR_BLADDER_MAX_CHARGES);
58+
level.playSound(null, player.blockPosition(),
59+
SoundEvents.BOTTLE_FILL, SoundSource.PLAYERS, 0.8f, 1.0f);
60+
player.getCooldowns().addCooldown(this, OxygenConfig.AIR_BLADDER_COOLDOWN);
61+
return InteractionResultHolder.sidedSuccess(stack, false);
62+
}
63+
64+
if (charges > 0) {
65+
ServerLevel serverLevel = serverPlayer.serverLevel();
66+
serverPlayer.getCapability(OxygenBudgetCap.CAP).ifPresent(cap -> {
67+
long current = cap.getOxygenTicks(serverLevel.dimension());
68+
long max = OxygenConfig.getMaxOxygenTicks(serverPlayer);
69+
70+
if (current < max) {
71+
long restored = Math.min(OxygenConfig.AIR_BLADDER_RESTORE_TICKS, max - current);
72+
cap.setOxygenTicks(serverLevel.dimension(), current + restored);
73+
setCharges(stack, getCharges(stack) - 1);
74+
75+
level.playSound(null, player.blockPosition(),
76+
SoundEvents.BOTTLE_EMPTY, SoundSource.PLAYERS, 1.0f, 0.8f);
77+
}
78+
});
79+
player.getCooldowns().addCooldown(this, OxygenConfig.AIR_BLADDER_COOLDOWN);
80+
return InteractionResultHolder.sidedSuccess(stack, false);
81+
}
82+
}
83+
84+
return InteractionResultHolder.pass(stack);
85+
}
86+
87+
@Override
88+
public boolean isBarVisible(ItemStack stack) {
89+
return true;
90+
}
91+
92+
@Override
93+
public int getBarWidth(ItemStack stack) {
94+
return Math.round(13.0f * getCharges(stack) / OxygenConfig.AIR_BLADDER_MAX_CHARGES);
95+
}
96+
97+
@Override
98+
public int getBarColor(ItemStack stack) {
99+
return 0x55D8FF;
100+
}
101+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
{
2+
"parent": "minecraft:item/generated",
3+
"textures": {
4+
"layer0": "cosmiccore:item/bladder/bladder-0"
5+
},
6+
"overrides": [
7+
{
8+
"predicate": {
9+
"cosmiccore:charges": 0.33
10+
},
11+
"model": "cosmiccore:item/air_bladder_1"
12+
},
13+
{
14+
"predicate": {
15+
"cosmiccore:charges": 0.66
16+
},
17+
"model": "cosmiccore:item/air_bladder_2"
18+
},
19+
{
20+
"predicate": {
21+
"cosmiccore:charges": 1.0
22+
},
23+
"model": "cosmiccore:item/air_bladder_3"
24+
}
25+
]
26+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"parent": "minecraft:item/generated",
3+
"textures": {
4+
"layer0": "cosmiccore:item/bladder/bladder-1"
5+
}
6+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"parent": "minecraft:item/generated",
3+
"textures": {
4+
"layer0": "cosmiccore:item/bladder/bladder-2"
5+
}
6+
}

0 commit comments

Comments
 (0)