I see a red door, I must have it painted black.

- All tanks in the vat are scaled properly
- Vats now render their fluids similarly to basins.
- PipeEntry now annotates the attachmentModel as client only.
- Re-Introduced renderers for Advanced & Quad Potato Cannons.
- Electrodes can now perform actions on tick.

Flamethrower Changes
- Flamethrowers now have datapack registered fuel types.
- Updated Flamethrowers to use one component to handle fuel data.
- Flamethrowers can now take fuel from any block entity with a fluid capability, as long as you interact with the side containing the handler.
- Spark entities now set entities ablaze for 4 seconds and do an additional 1 damage to an entity that is already on fire.
This commit is contained in:
PouffyDev
2025-07-30 21:56:17 +01:00
parent 55c10c1d33
commit 235548291d
39 changed files with 911 additions and 297 deletions

View File

@@ -513,6 +513,12 @@
"create.distillation_output.mode.void_when_full": "pınןℲ ssǝɔxƎ pıoΛ",
"create.distillation_output.when_tank_is_full": "ןןnℲ sı ʞuɐ⟘ ןɐuɹǝʇuI uǝɥM",
"create.fe": "%1$s :ƎℲ",
"create.flamethrower.fuel.amount": "ʇunoɯⱯ ǝןıʇɔǝظoɹԀ %s",
"create.flamethrower.fuel.capacity": "%s :ʎʇıɔɐdɐƆ ןǝnℲ",
"create.flamethrower.fuel.cold": "ǝɯɐןℲ pןoƆ",
"create.flamethrower.fuel.hellfire": "ǝɯɐןℲ buıɥɔɹoɔS",
"create.flamethrower.fuel.speed": "pǝǝdS ǝןıʇɔǝظoɹԀ %s",
"create.flamethrower.fuel.spread": "pɐǝɹdS ǝןıʇɔǝظoɹԀ %s",
"create.goggles.ammeter": ":ɹǝʇǝɯɯⱯ",
"create.goggles.ammeter.amps": "Λ %1$s :sdɯⱯ pǝɹnsɐǝW ",
"create.goggles.blast_furnace.fuel_amount": "%1$s : ןǝnℲ ",

View File

@@ -513,6 +513,12 @@
"create.distillation_output.mode.void_when_full": "Void Excess Fluid",
"create.distillation_output.when_tank_is_full": "When Internal Tank is Full",
"create.fe": "FE: %1$s",
"create.flamethrower.fuel.amount": "%s Projectile Amount",
"create.flamethrower.fuel.capacity": "Fuel Capacity: %s",
"create.flamethrower.fuel.cold": "Cold Flame",
"create.flamethrower.fuel.hellfire": "Scorching Flame",
"create.flamethrower.fuel.speed": "%s Projectile Speed",
"create.flamethrower.fuel.spread": "%s Projectile Spread",
"create.goggles.ammeter": "Ammeter:",
"create.goggles.ammeter.amps": " Measured Amps: %1$s V",
"create.goggles.blast_furnace.fuel_amount": " Fuel : %1$s",

View File

@@ -0,0 +1,7 @@
{
"amount": 3,
"color": 12226935,
"fluids": "tfmg:diesel",
"speed": 2.0,
"spread": 7
}

View File

@@ -0,0 +1,7 @@
{
"amount": 0,
"color": 0,
"fluids": [],
"speed": 0.0,
"spread": 0
}

View File

@@ -0,0 +1,4 @@
{
"amount": 3,
"fluids": "tfmg:gasoline"
}

View File

@@ -0,0 +1,6 @@
{
"color": 7894741,
"fluids": "tfmg:kerosene",
"speed": 1.3,
"spread": 10
}

View File

@@ -0,0 +1,7 @@
{
"amount": 16,
"color": 14728008,
"fluids": "tfmg:lpg",
"speed": 0.6,
"spread": 35
}

View File

@@ -0,0 +1,6 @@
{
"amount": 15,
"color": 16747520,
"fluids": "tfmg:molten_slag",
"speed": 0.3
}

View File

@@ -0,0 +1,7 @@
{
"amount": 15,
"color": 10733129,
"fluids": "tfmg:napalm",
"speed": 1.8,
"spread": 20
}

View File

@@ -0,0 +1,7 @@
{
"amount": 1,
"color": 6167306,
"fluids": "tfmg:naphtha",
"speed": 0.8,
"spread": 20
}

View File

@@ -3,16 +3,35 @@ package com.drmangotea.tfmg;
import com.drmangotea.tfmg.content.items.weapons.advanced_potato_cannon.AdvancedPotatoCannonRenderHandler;
import com.drmangotea.tfmg.content.items.weapons.flamethrover.FlamethrowerRenderHandler;
import com.drmangotea.tfmg.content.items.weapons.quad_potato_cannon.QuadPotatoCannonRenderHandler;
import com.drmangotea.tfmg.content.machinery.vat.electrode_holder.ElectrodeHolderRenderer;
import com.drmangotea.tfmg.ponder.TFMGPonderPlugin;
import com.drmangotea.tfmg.registry.TFMGParticleTypes;
import com.mojang.blaze3d.vertex.MeshData;
import com.mojang.blaze3d.vertex.PoseStack;
import com.simibubi.create.Create;
import com.simibubi.create.CreateClient;
import com.simibubi.create.content.equipment.potatoCannon.PotatoCannonRenderHandler;
import com.simibubi.create.content.kinetics.base.KineticBlockEntityRenderer;
import com.simibubi.create.foundation.ponder.CreatePonderPlugin;
import dev.engine_room.flywheel.lib.model.baked.EmptyVirtualBlockGetter;
import dev.engine_room.flywheel.lib.model.baked.PartialModel;
import net.createmod.catnip.client.render.model.BakedModelBufferer;
import net.createmod.catnip.render.SuperBufferFactory;
import net.createmod.catnip.render.SuperByteBuffer;
import net.createmod.catnip.render.SuperByteBufferCache;
import net.createmod.ponder.foundation.PonderIndex;
import net.minecraft.client.resources.model.BakedModel;
import net.minecraft.core.BlockPos;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.state.BlockState;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.bus.api.IEventBus;
import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.fml.common.Mod;
import net.neoforged.fml.event.lifecycle.FMLClientSetupEvent;
import net.neoforged.neoforge.common.NeoForge;
import javax.annotation.Nullable;
@Mod(value = TFMG.MOD_ID, dist = Dist.CLIENT)
public class TFMGClient {
@@ -25,24 +44,21 @@ public class TFMGClient {
public static final FlamethrowerRenderHandler FLAMETHROWER_RENDER_HANDLER = new FlamethrowerRenderHandler();
@SuppressWarnings("removal")
public TFMGClient(net.neoforged.bus.api.IEventBus modEventBus) {
//IEventBus forgeEventBus = MinecraftForge.EVENT_BUS;
modEventBus.addListener(TFMGParticleTypes::registerFactories);
modEventBus.register(this);
PonderIndex.addPlugin(new TFMGPonderPlugin());
// ADVANCED_POTATO_CANNON_RENDER_HANDLER.registerListeners(forgeEventBus);
// QUAD_POTATO_CANNON_RENDER_HANDLER.registerListeners(forgeEventBus);
// FLAMETHROWER_RENDER_HANDLER.registerListeners(forgeEventBus);
public TFMGClient(IEventBus modEventBus) {
onCtorClient(modEventBus);
}
public static void onCtorClient(IEventBus modEventBus) {
IEventBus neoEventBus = NeoForge.EVENT_BUS;
@SubscribeEvent
public void setup(final FMLClientSetupEvent event) {
//TFMGPonderIndex.register();
//TFMGPonderIndex.registerTags();
modEventBus.addListener(TFMGClient::clientInit);
modEventBus.addListener(TFMGParticleTypes::registerFactories);
QUAD_POTATO_CANNON_RENDER_HANDLER.registerListeners(neoEventBus);
ADVANCED_POTATO_CANNON_RENDER_HANDLER.registerListeners(neoEventBus);
}
public static void clientInit(final FMLClientSetupEvent event) {
PonderIndex.addPlugin(new TFMGPonderPlugin());
}
}

View File

@@ -1,7 +1,9 @@
package com.drmangotea.tfmg;
import com.drmangotea.tfmg.content.electricity.connection.cable_type.CableType;
import com.drmangotea.tfmg.content.items.weapons.flamethrover.FlamethrowerFuelType;
import com.drmangotea.tfmg.content.machinery.vat.electrode_holder.electrode.Electrode;
import com.simibubi.create.api.equipment.potatoCannon.PotatoCannonProjectileType;
import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceKey;
import net.neoforged.neoforge.registries.RegistryBuilder;
@@ -12,6 +14,8 @@ public class TFMGRegistries {
public static final ResourceKey<Registry<CableType>> CABLE_TYPE = createRegistryKey("cable_types");
public static final ResourceKey<Registry<Electrode>> ELECTRODE = createRegistryKey("electrodes");
public static final ResourceKey<Registry<FlamethrowerFuelType>> FLAMETHROWER_FUEL_TYPE = createRegistryKey("flamethrower_fuel/type");
public static final Registry<CableType> CABLE_TYPE_REGISTRY = makeSyncedRegistry(CABLE_TYPE);
public static final Registry<Electrode> ELECTRODE_REGISTRY = makeSyncedRegistry(ELECTRODE);

View File

@@ -1,8 +1,12 @@
package com.drmangotea.tfmg.base.events;
import com.drmangotea.tfmg.TFMG;
import com.drmangotea.tfmg.TFMGClient;
import com.drmangotea.tfmg.content.electricity.measurement.MultimeterOverlayRenderer;
import com.drmangotea.tfmg.content.engines.engine_controller.EngineControllerClientHandler;
import com.drmangotea.tfmg.content.items.weapons.advanced_potato_cannon.AdvancedPotatoCannonItemRenderer;
import com.drmangotea.tfmg.content.items.weapons.quad_potato_cannon.QuadPotatoCannonItemRenderer;
import com.drmangotea.tfmg.registry.TFMGItems;
import net.minecraft.client.Minecraft;
import net.minecraft.world.entity.player.Player;
import net.neoforged.api.distmarker.Dist;
@@ -10,6 +14,7 @@ import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.fml.common.EventBusSubscriber;
import net.neoforged.neoforge.client.event.ClientTickEvent;
import net.neoforged.neoforge.client.event.RegisterGuiLayersEvent;
import net.neoforged.neoforge.client.event.RegisterItemDecorationsEvent;
import net.neoforged.neoforge.client.gui.VanillaGuiLayers;
import net.neoforged.neoforge.event.entity.player.PlayerEvent;
@@ -33,10 +38,12 @@ public class TFMGClientEvents {
if (!isGameActive())
return;
TFMGClient.QUAD_POTATO_CANNON_RENDER_HANDLER.tick();
TFMGClient.ADVANCED_POTATO_CANNON_RENDER_HANDLER.tick();
TFMGClient.FLAMETHROWER_RENDER_HANDLER.tick();
if (isPreEvent) {
EngineControllerClientHandler.tick();
}
}
@SubscribeEvent
@@ -55,4 +62,13 @@ public class TFMGClientEvents {
protected static boolean isGameActive() {
return !(Minecraft.getInstance().level == null || Minecraft.getInstance().player == null);
}
@EventBusSubscriber(value = Dist.CLIENT, bus = EventBusSubscriber.Bus.MOD)
public static class ModBusEvents {
@SubscribeEvent
public static void registerItemDecorations(RegisterItemDecorationsEvent event) {
event.register(TFMGItems.QUAD_POTATO_CANNON, QuadPotatoCannonItemRenderer.DECORATOR);
event.register(TFMGItems.ADVANCED_POTATO_CANNON, AdvancedPotatoCannonItemRenderer.DECORATOR);
}
}
}

View File

@@ -0,0 +1,21 @@
package com.drmangotea.tfmg.base.events;
import com.drmangotea.tfmg.TFMGRegistries;
import com.drmangotea.tfmg.content.items.weapons.flamethrover.FlamethrowerFuelType;
import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.fml.common.EventBusSubscriber;
import net.neoforged.neoforge.registries.DataPackRegistryEvent;
import org.jetbrains.annotations.ApiStatus;
@EventBusSubscriber(bus = EventBusSubscriber.Bus.MOD)
public class TFMGRegistriesImpl {
@ApiStatus.Internal
@SubscribeEvent
public static void registerDatapackRegistries(DataPackRegistryEvent.NewRegistry event) {
event.dataPackRegistry(
TFMGRegistries.FLAMETHROWER_FUEL_TYPE,
FlamethrowerFuelType.CODEC,
FlamethrowerFuelType.CODEC
);
}
}

View File

@@ -67,12 +67,12 @@ public class Spark extends ThrowableProjectile {
}
}
}
protected void onHitBlock(BlockHitResult p_37384_) {
super.onHitBlock(p_37384_);
protected void onHitBlock(BlockHitResult hitResult) {
super.onHitBlock(hitResult);
if (!this.level().isClientSide) {
Entity entity = this.getOwner();
if (!(entity instanceof Mob) ) {
BlockPos blockpos = p_37384_.getBlockPos().relative(p_37384_.getDirection());
BlockPos blockpos = hitResult.getBlockPos().relative(hitResult.getDirection());
if (this.level().isEmptyBlock(blockpos)) {
this.level().setBlockAndUpdate(blockpos, BaseFireBlock.getState(this.level(), blockpos));
}
@@ -84,7 +84,10 @@ public class Spark extends ThrowableProjectile {
super.onHitEntity(p_37386_);
if (!this.level().isClientSide) {
Entity entity = p_37386_.getEntity();
entity.setRemainingFireTicks(10);
entity.igniteForSeconds(4.0F);
if (entity.getRemainingFireTicks() > 0 && !entity.fireImmune()) {
entity.hurt(this.damageSources().onFire(), 1.0F);
}
}
}

View File

@@ -20,6 +20,8 @@ import net.minecraft.client.resources.model.BakedModel;
import net.minecraft.core.Direction;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.level.material.MapColor;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.api.distmarker.OnlyIn;
import net.neoforged.neoforge.client.model.generators.ConfiguredModel;
import static com.simibubi.create.foundation.data.ModelGen.customItemModel;
@@ -37,7 +39,9 @@ public class TFMGPipeEntry {
private final BlockEntry<? extends TFMGSmartFluidPipeBlock> smart;
private final BlockEntry<? extends TFMGFluidValveBlock> valve;
@OnlyIn(Dist.CLIENT)
private NonNullFunction<BakedModel, ? extends BakedModel> attachmentModel;
private CTSpriteShiftEntry encasedSpriteShift;
public TFMGPipeEntry(TFMGPipes.PipeMaterial material, TFMGRegistrate registrate) {
@@ -51,6 +55,7 @@ public class TFMGPipeEntry {
this.valve = registerValve();
}
@OnlyIn(Dist.CLIENT)
public TFMGPipeEntry attachmentModel(NonNullFunction<BakedModel, ? extends BakedModel> attachmentModel) {
this.attachmentModel = attachmentModel;
return this;

View File

@@ -90,14 +90,7 @@ public class AdvancedPotatoCannonItem extends ProjectileWeaponItem implements Cu
@Override
public InteractionResultHolder<ItemStack> use(Level world, Player player, InteractionHand hand) {
ItemStack stack = player.getItemInHand(hand);
return findAmmoInInventory(world, player, stack).map(itemStack -> {
//if(itemStack.isEmpty())
// return InteractionResultHolder.fail(stack);
return findAmmoInInventory(player).map(itemStack -> {
if (ShootableGadgetItemMethods.shouldSwap(player, stack, hand, this::isCannon))
return InteractionResultHolder.fail(stack);
@@ -147,8 +140,8 @@ public class AdvancedPotatoCannonItem extends ProjectileWeaponItem implements Cu
AllSoundEvents.FWOOMP.play(world,player,player.getX(),player.getY(),player.getZ(),1,0.2f);
ShootableGadgetItemMethods.applyCooldown(player, stack, hand, this::isCannon, cooldown);
//ShootableGadgetItemMethods.sendPackets(player,
// b -> new AdvancedPotatoCannonPacket(barrelPos, lookVec.normalize(), itemStack, hand, soundPitch, b));
ShootableGadgetItemMethods.sendPackets(player,
b -> new AdvancedPotatoCannonPacket(barrelPos, lookVec.normalize(), itemStack, hand, soundPitch, b));
return InteractionResultHolder.success(stack);
})
.orElse(InteractionResultHolder.pass(stack));
@@ -159,9 +152,7 @@ public class AdvancedPotatoCannonItem extends ProjectileWeaponItem implements Cu
return slotChanged || newStack.getItem() != oldStack.getItem();
}
private Optional<ItemStack> findAmmoInInventory(Level world, Player player, ItemStack held) {
protected static Optional<ItemStack> findAmmoInInventory(Player player) {
for(int i = 0; i < player.getInventory().getContainerSize(); ++i) {
ItemStack stack = player.getInventory().getItem(i);
if(stack.is(TFMGItems.NAPALM_POTATO.get())){

View File

@@ -2,8 +2,11 @@ package com.drmangotea.tfmg.content.items.weapons.advanced_potato_cannon;
import com.drmangotea.tfmg.TFMGClient;
import com.drmangotea.tfmg.content.items.weapons.quad_potato_cannon.QuadPotatoCannonItem;
import com.drmangotea.tfmg.registry.TFMGItems;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.math.Axis;
import com.simibubi.create.content.equipment.potatoCannon.PotatoCannonItem;
import com.simibubi.create.foundation.item.render.CustomRenderedItemModel;
import com.simibubi.create.foundation.item.render.CustomRenderedItemModelRenderer;
import com.simibubi.create.foundation.item.render.PartialItemModelRenderer;
@@ -16,31 +19,53 @@ import net.minecraft.util.Mth;
import net.minecraft.world.entity.HumanoidArm;
import net.minecraft.world.item.ItemDisplayContext;
import net.minecraft.world.item.ItemStack;
import net.neoforged.neoforge.client.IItemDecorator;
import java.util.Optional;
public class AdvancedPotatoCannonItemRenderer extends CustomRenderedItemModelRenderer {
public static final IItemDecorator DECORATOR = (guiGraphics, font, stack, xOffset, yOffset) -> {
LocalPlayer player = Minecraft.getInstance().player;
if (player == null) {
return false;
}
Optional<ItemStack> ammo = AdvancedPotatoCannonItem.findAmmoInInventory(player);
if (ammo.isEmpty()) {
return false;
}
PoseStack poseStack = guiGraphics.pose();
poseStack.pushPose();
poseStack.translate(xOffset, yOffset + 8, 100);
poseStack.scale(.5f, .5f, .5f);
guiGraphics.renderItem(ammo.get(), 0, 0);
poseStack.popPose();
return false;
};
@Override
protected void render(ItemStack stack, CustomRenderedItemModel model, PartialItemModelRenderer renderer,
ItemDisplayContext transformType, PoseStack ms, MultiBufferSource buffer, int light, int overlay) {
ItemRenderer itemRenderer = Minecraft.getInstance()
.getItemRenderer();
protected void render(ItemStack stack, CustomRenderedItemModel model, PartialItemModelRenderer renderer, ItemDisplayContext transformType, PoseStack ms, MultiBufferSource buffer, int light, int overlay) {
renderer.render(model.getOriginalModel(), light);
LocalPlayer player = Minecraft.getInstance().player;
boolean mainHand = player.getMainHandItem() == stack;
boolean offHand = player.getOffhandItem() == stack;
boolean leftHanded = player.getMainArm() == HumanoidArm.LEFT;
Minecraft mc = Minecraft.getInstance();
LocalPlayer player = mc.player;
float offset = .5f / 16;
float worldTime = AnimationTickHolder.getRenderTime() / 10;
float angle = worldTime * -25;
float speed = TFMGClient.ADVANCED_POTATO_CANNON_RENDER_HANDLER.getAnimation(mainHand ^ leftHanded,
AnimationTickHolder.getPartialTicks());
float angle = AnimationTickHolder.getRenderTime() * -2.5f;
if (player != null) {
boolean inMainHand = player.getMainHandItem() == stack;
boolean inOffHand = player.getOffhandItem() == stack;
if (inMainHand || inOffHand) {
boolean leftHanded = player.getMainArm() == HumanoidArm.LEFT;
float speed = TFMGClient.ADVANCED_POTATO_CANNON_RENDER_HANDLER.getAnimation(inMainHand ^ leftHanded,
AnimationTickHolder.getPartialTicks());
angle += 360 * Mth.clamp(speed * 5, 0, 1);
}
}
if (mainHand || offHand)
angle += 360 * Mth.clamp(speed * 5, 0, 1);
angle %= 360;
float offset = .5f / 16;
ms.pushPose();
ms.translate(0, offset, 0);

View File

@@ -21,8 +21,6 @@ import net.neoforged.api.distmarker.OnlyIn;
public class AdvancedPotatoCannonPacket extends ShootGadgetPacket {
public static final StreamCodec<RegistryFriendlyByteBuf, AdvancedPotatoCannonPacket> STREAM_CODEC = StreamCodec.composite(
CatnipStreamCodecs.VEC3, packet -> packet.location,
CatnipStreamCodecs.VEC3, packet -> packet.motion,
@@ -47,17 +45,17 @@ public class AdvancedPotatoCannonPacket extends ShootGadgetPacket {
@Override
@OnlyIn(Dist.CLIENT)
protected void handleAdditional() {
CreateClient.POTATO_CANNON_RENDER_HANDLER.beforeShoot(pitch, location, motion, item);
TFMGClient.ADVANCED_POTATO_CANNON_RENDER_HANDLER.beforeShoot(pitch, location, motion, item);
}
@Override
@OnlyIn(Dist.CLIENT)
protected ShootableGadgetRenderHandler getHandler() {
return CreateClient.POTATO_CANNON_RENDER_HANDLER;
return TFMGClient.ADVANCED_POTATO_CANNON_RENDER_HANDLER;
}
@Override
public PacketTypeProvider getTypeProvider() {
return AllPackets.POTATO_CANNON;
return TFMGPackets.ADVANCED_POTATO_CANNON;
}
}

View File

@@ -1,10 +1,10 @@
package com.drmangotea.tfmg.content.items.weapons.advanced_potato_cannon;
import com.drmangotea.tfmg.registry.TFMGItems;
import com.mojang.blaze3d.vertex.PoseStack;
import com.simibubi.create.content.equipment.potatoCannon.PotatoProjectileEntity;
import com.simibubi.create.content.equipment.zapper.ShootableGadgetRenderHandler;
import com.simibubi.create.foundation.particle.AirParticleData;
import dev.engine_room.flywheel.lib.transform.TransformStack;
import net.createmod.catnip.math.VecHelper;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.ClientLevel;
@@ -25,7 +25,7 @@ public class AdvancedPotatoCannonRenderHandler extends ShootableGadgetRenderHand
@Override
protected boolean appliesTo(ItemStack stack) {
return false;
return stack.getItem() instanceof AdvancedPotatoCannonItem;
}
public void beforeShoot(float nextPitch, Vec3 location, Vec3 motion, ItemStack stack) {
@@ -33,7 +33,6 @@ public class AdvancedPotatoCannonRenderHandler extends ShootableGadgetRenderHand
if (stack.isEmpty())
return;
ClientLevel world = Minecraft.getInstance().level;
for (int i = 0; i < 2; i++) {
Vec3 m = VecHelper.offsetRandomly(motion.scale(0.1f), world.random, .025f);
@@ -47,12 +46,17 @@ public class AdvancedPotatoCannonRenderHandler extends ShootableGadgetRenderHand
@Override
protected void transformTool(PoseStack ms, float flip, float equipProgress, float recoil, float pt) {
ms.translate(flip * -.1f, 0.125, .34f);
ms.scale(.75f, .75f, .75f);
TransformStack.of(ms)
.rotateXDegrees(recoil * 80);
}
@Override
protected void transformHand(PoseStack ms, float flip, float equipProgress, float recoil, float pt) {
ms.translate(flip * -.09, -.275, -.25);
TransformStack.of(ms)
.rotateZDegrees(flip * -10);
}
}

View File

@@ -0,0 +1,82 @@
package com.drmangotea.tfmg.content.items.weapons.flamethrover;
import com.drmangotea.tfmg.TFMGRegistries;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import io.netty.buffer.ByteBuf;
import net.minecraft.core.Holder;
import net.minecraft.core.RegistryAccess;
import net.minecraft.network.codec.ByteBufCodecs;
import net.minecraft.network.codec.StreamCodec;
import net.minecraft.resources.ResourceKey;
import net.minecraft.world.level.material.Fluid;
import net.neoforged.neoforge.fluids.FluidStack;
import org.jetbrains.annotations.Nullable;
import java.util.Optional;
public record FlamethrowerFuel(@Nullable ResourceKey<FlamethrowerFuelType> fuelType, int amount, int color) {
public static final Codec<FlamethrowerFuel> CODEC = RecordCodecBuilder.create(instance -> instance.group(
ResourceKey.codec(TFMGRegistries.FLAMETHROWER_FUEL_TYPE).fieldOf("fuel_type").forGetter(FlamethrowerFuel::fuelType),
Codec.INT.fieldOf("amount").forGetter(FlamethrowerFuel::amount),
Codec.INT.optionalFieldOf("color", 0xFFFFFF).forGetter(fuel -> fuel.color == 0 ? 0xFFFFFF : fuel.color)
).apply(instance, FlamethrowerFuel::new));
public static final StreamCodec<ByteBuf, FlamethrowerFuel> STREAM_CODEC = StreamCodec.composite(
ResourceKey.streamCodec(TFMGRegistries.FLAMETHROWER_FUEL_TYPE),
FlamethrowerFuel::fuelType,
ByteBufCodecs.INT,
FlamethrowerFuel::amount,
ByteBufCodecs.INT,
fuel -> fuel.color == 0 ? 0xFFFFFF : fuel.color,
FlamethrowerFuel::new
);
public static final FlamethrowerFuel EMPTY = new FlamethrowerFuel(null, 0, 0xFFFFFF);
public FlamethrowerFuel decrement(int amount) {
if (this.amount <= amount || fuelType == null) {
return EMPTY;
}
return new FlamethrowerFuel(fuelType, this.amount - amount, color);
}
public FlamethrowerFuel increment(int amount, int capacity) {
if (fuelType == null) {
return EMPTY;
}
if (this.amount + amount > capacity) {
return new FlamethrowerFuel(fuelType, capacity, color);
}
return new FlamethrowerFuel(fuelType, this.amount + amount, color);
}
public static FlamethrowerFuel createForType(RegistryAccess registryAccess, Fluid fluid, int amount) {
Optional<Holder.Reference<FlamethrowerFuelType>> type = FlamethrowerFuelType.getTypeForFluid(registryAccess, fluid);
return type.map(typeReference -> new FlamethrowerFuel(typeReference.getKey(), amount, typeReference.value().color())).orElse(null);
}
public static FlamethrowerFuel createForType(RegistryAccess registryAccess, FluidStack stack) {
return createForType(registryAccess, stack.getFluid(), stack.getAmount());
}
public boolean isEmpty() {
if (fuelType == null) {
return true;
}
return this.amount <= 0;
}
public boolean hasFuel() {
return fuelType != null;
}
public Optional<FlamethrowerFuelType> getFuelType(RegistryAccess registryAccess) {
return registryAccess.registryOrThrow(TFMGRegistries.FLAMETHROWER_FUEL_TYPE).getOptional(fuelType);
}
public FlamethrowerFuelType getFuelTypeOrThrow(RegistryAccess registryAccess) {
return getFuelType(registryAccess).orElseThrow(() -> new IllegalStateException("No fuel type found for " + fuelType));
}
}

View File

@@ -0,0 +1,91 @@
package com.drmangotea.tfmg.content.items.weapons.flamethrover;
import com.drmangotea.tfmg.TFMGRegistries;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import com.simibubi.create.api.equipment.potatoCannon.PotatoCannonProjectileType;
import com.simibubi.create.api.registry.CreateRegistries;
import com.simibubi.create.foundation.fluid.FluidHelper;
import net.minecraft.core.Holder;
import net.minecraft.core.HolderSet;
import net.minecraft.core.RegistryAccess;
import net.minecraft.core.RegistryCodecs;
import net.minecraft.core.registries.Registries;
import net.minecraft.world.item.Item;
import net.minecraft.world.level.ItemLike;
import net.minecraft.world.level.material.Fluid;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
public record FlamethrowerFuelType(HolderSet<Fluid> fluids, int spread, float speed, int amount, boolean isCold, boolean hellfire, int color) {
public static final Codec<FlamethrowerFuelType> CODEC = RecordCodecBuilder.create(i -> i.group(
RegistryCodecs.homogeneousList(Registries.FLUID).fieldOf("fluids").forGetter(FlamethrowerFuelType::fluids),
Codec.INT.optionalFieldOf("spread", 15).forGetter(FlamethrowerFuelType::spread),
Codec.FLOAT.optionalFieldOf("speed", 1f).forGetter(FlamethrowerFuelType::speed),
Codec.INT.optionalFieldOf("amount", 4).forGetter(FlamethrowerFuelType::amount),
Codec.BOOL.optionalFieldOf("is_cold", false).forGetter(FlamethrowerFuelType::isCold),
Codec.BOOL.optionalFieldOf("hellfire", false).forGetter(FlamethrowerFuelType::hellfire),
Codec.INT.optionalFieldOf("color", 0xC4AA76). forGetter(FlamethrowerFuelType::color)
).apply(i, FlamethrowerFuelType::new));
public static Optional<Holder.Reference<FlamethrowerFuelType>> getTypeForFluid(RegistryAccess registryAccess, Fluid fluid) {
// Cache this if it causes performance issues, but it probably won't
return registryAccess.lookupOrThrow(TFMGRegistries.FLAMETHROWER_FUEL_TYPE)
.listElements()
.filter(ref -> ref.value().fluids.contains(fluid.builtInRegistryHolder()))
.findFirst();
}
public static class Builder {
private final List<Holder<Fluid>> fluids = new ArrayList<>();
private int spread = 15;
private float speed = 1f;
private int amount = 4;
private boolean isCold = false;
private boolean hellfire = false;
private int color = 0xC4AA76;
public Builder spread(int spread) {
this.spread = spread;
return this;
}
public Builder speed(float speed) {
this.speed = speed;
return this;
}
public Builder amount(int amount) {
this.amount = amount;
return this;
}
public Builder isCold(boolean isCold) {
this.isCold = isCold;
return this;
}
public Builder hellfire(boolean hellfire) {
this.hellfire = hellfire;
return this;
}
public Builder color(int color) {
this.color = color;
return this;
}
public Builder addFluids(Fluid... fluids) {
for (Fluid fluid : fluids)
this.fluids.add(FluidHelper.convertToStill(fluid).builtInRegistryHolder());
return this;
}
public FlamethrowerFuelType build() {
return new FlamethrowerFuelType(HolderSet.direct(fluids), spread, speed, amount, isCold, hellfire, color);
}
}
}

View File

@@ -1,32 +1,50 @@
package com.drmangotea.tfmg.content.items.weapons.flamethrover;
import com.drmangotea.tfmg.TFMG;
import com.drmangotea.tfmg.TFMGClient;
import com.drmangotea.tfmg.base.spark.Spark;
import com.drmangotea.tfmg.registry.TFMGDataComponents;
import com.drmangotea.tfmg.registry.TFMGEntityTypes;
import com.simibubi.create.content.fluids.tank.FluidTankBlockEntity;
import com.simibubi.create.content.equipment.zapper.ShootableGadgetItemMethods;
import com.simibubi.create.foundation.item.CustomArmPoseItem;
import com.simibubi.create.foundation.utility.CreateLang;
import net.minecraft.ChatFormatting;
import net.minecraft.client.Minecraft;
import net.minecraft.client.model.HumanoidModel;
import net.minecraft.client.player.AbstractClientPlayer;
import net.minecraft.client.player.LocalPlayer;
import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.core.RegistryAccess;
import net.minecraft.network.chat.CommonComponents;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.MutableComponent;
import net.minecraft.resources.ResourceKey;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.util.Mth;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.InteractionResultHolder;
import net.minecraft.world.entity.HumanoidArm;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.TooltipFlag;
import net.minecraft.world.item.UseAnim;
import net.minecraft.world.item.context.UseOnContext;
import net.minecraft.world.level.Level;
import net.minecraft.world.phys.HitResult;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.phys.Vec3;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.api.distmarker.OnlyIn;
import net.neoforged.neoforge.capabilities.Capabilities;
import net.neoforged.neoforge.fluids.FluidStack;
import net.neoforged.neoforge.fluids.capability.IFluidHandler;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.Objects;
public class FlamethrowerItem extends Item implements CustomArmPoseItem {
@@ -39,78 +57,84 @@ public class FlamethrowerItem extends Item implements CustomArmPoseItem {
public void onUseTick(Level level, LivingEntity entity, ItemStack stack, int time) {
if (stack.getOrDefault(TFMGDataComponents.FLAMETHROWER_FUEL, FlamethrowerFuel.EMPTY) == FlamethrowerFuel.EMPTY)
return;
if(stack.get(TFMGDataComponents.AMOUNT)==null)
stack.set(TFMGDataComponents.AMOUNT,0);
int fuelAmount = stack.getOrDefault(TFMGDataComponents.FLAMETHROWER_FUEL, FlamethrowerFuel.EMPTY).amount();
Spark spark = TFMGEntityTypes.SPARK.create(level);
spark.setPos(entity.getX(),entity.getY()+1.2f,entity.getZ());
if(!stack.has(TFMGDataComponents.FLAMETHROWER_FUEL))
stack.set(TFMGDataComponents.FLAMETHROWER_FUEL, FlamethrowerFuel.EMPTY);
if(stack.get(TFMGDataComponents.AMOUNT)==0) {
stack.set(TFMGDataComponents.FLAMETHROWER_FUEL,"");
if(fuelAmount==0) {
stack.set(TFMGDataComponents.FLAMETHROWER_FUEL, FlamethrowerFuel.EMPTY);
return;
}
level.playSound((Player)null, entity.getX(), entity.getY(), entity.getZ(), SoundEvents.FIRE_EXTINGUISH, SoundSource.NEUTRAL, 0.1F, 0.04F);
level.playSound(null, entity.getX(), entity.getY(), entity.getZ(), SoundEvents.FIRE_EXTINGUISH, SoundSource.NEUTRAL, 0.1F, 0.04F);
FlamethrowerFuel fuel = Enum.valueOf(FlamethrowerFuel.class,stack.get(TFMGDataComponents.FLAMETHROWER_FUEL).toUpperCase());
FlamethrowerFuel fuel = stack.getOrDefault(TFMGDataComponents.FLAMETHROWER_FUEL, FlamethrowerFuel.EMPTY);
FlamethrowerFuelType fuelType = getFuel(level.registryAccess(), stack);
for(int i =0;i<fuel.amount;i++) {
if(stack.get(TFMGDataComponents.AMOUNT)==0) {
stack.set(TFMGDataComponents.FLAMETHROWER_FUEL,"");
return;
Vec3 barrelPos = getGunBarrelVec(entity, entity.getUsedItemHand() == InteractionHand.MAIN_HAND,
new Vec3(.75f, -0.65f, 1.5f));
for(int i =0; i < fuelType.amount(); i++) {
Spark spark = TFMGEntityTypes.SPARK.create(level);
if (spark != null) {
spark.setPos(barrelPos.x, barrelPos.y, barrelPos.z);
spark.shoot(entity.getLookAngle().x, entity.getLookAngle().y, entity.getLookAngle().z, fuelType.speed(), fuelType.spread());
level.addFreshEntity(spark);
stack.set(TFMGDataComponents.FLAMETHROWER_FUEL, fuel.decrement(1));
}
stack.set(TFMGDataComponents.AMOUNT,stack.get(TFMGDataComponents.AMOUNT)-1);
spark.shoot(entity.getLookAngle().x,entity.getLookAngle().y,entity.getLookAngle().z,fuel.speed,fuel.spread);
level.addFreshEntity(spark);
}
}
public int getUseDuration(ItemStack p_77626_1_) {
return 696969;
public static Vec3 getGunBarrelVec(LivingEntity entity, boolean mainHand, Vec3 rightHandForward) {
Vec3 start = entity.position()
.add(0, entity.getEyeHeight(), 0);
float yaw = (float) ((entity.getYRot()) / -180 * Math.PI);
float pitch = (float) ((entity.getXRot()) / -180 * Math.PI);
int flip = mainHand == (entity.getMainArm() == HumanoidArm.RIGHT) ? -1 : 1;
Vec3 barrelPosNoTransform = new Vec3(flip * rightHandForward.x, rightHandForward.y, rightHandForward.z);
Vec3 barrelPos = start.add(barrelPosNoTransform.xRot(pitch)
.yRot(yaw));
return barrelPos;
}
@Override
public boolean isBarVisible(ItemStack stack) {
if(stack.get(TFMGDataComponents.AMOUNT)==null)
if(!stack.has(TFMGDataComponents.FLAMETHROWER_FUEL) || stack.getOrDefault(TFMGDataComponents.FLAMETHROWER_FUEL, FlamethrowerFuel.EMPTY).isEmpty())
return false;
return stack.get(TFMGDataComponents.AMOUNT)!=0;
return !stack.getOrDefault(TFMGDataComponents.FLAMETHROWER_FUEL, FlamethrowerFuel.EMPTY).isEmpty();
}
@Override
public int getBarColor(ItemStack stack) {
return stack.get(TFMGDataComponents.FLAMETHROWER_FUEL).isEmpty() ? 0xffffff :
Enum.valueOf(FlamethrowerFuel.class,stack.get(TFMGDataComponents.FLAMETHROWER_FUEL).toUpperCase()).color;
if(!stack.has(TFMGDataComponents.FLAMETHROWER_FUEL))
stack.set(TFMGDataComponents.FLAMETHROWER_FUEL, FlamethrowerFuel.EMPTY);
return stack.getOrDefault(TFMGDataComponents.FLAMETHROWER_FUEL, FlamethrowerFuel.EMPTY).color();
}
@Override
public int getBarWidth(ItemStack stack) {
if(!stack.has(TFMGDataComponents.FLAMETHROWER_FUEL))
stack.set(TFMGDataComponents.FLAMETHROWER_FUEL, FlamethrowerFuel.EMPTY);
if(stack.get(TFMGDataComponents.AMOUNT)==null)
stack.set(TFMGDataComponents.AMOUNT,0);
return Math.round( 13* ((float)((float)stack.get(TFMGDataComponents.AMOUNT)/(float)FUEL_CAPACITY)));
return Math.round( 13* ((float)stack.getOrDefault(TFMGDataComponents.FLAMETHROWER_FUEL, FlamethrowerFuel.EMPTY).amount()/(float)FUEL_CAPACITY));
}
public InteractionResultHolder<ItemStack> use(Level level, Player player, InteractionHand hand) {
player.startUsingItem(hand);
if (level.isClientSide) {
TFMGClient.FLAMETHROWER_RENDER_HANDLER.dontAnimateItem(hand);
}
@@ -130,47 +154,134 @@ public class FlamethrowerItem extends Item implements CustomArmPoseItem {
BlockPos pos = context.getClickedPos();
ItemStack stack = context.getItemInHand();
BlockEntity blockEntity = level.getBlockEntity(pos);
if (!stack.has(TFMGDataComponents.FLAMETHROWER_FUEL)) stack.set(TFMGDataComponents.FLAMETHROWER_FUEL, FlamethrowerFuel.EMPTY);
FlamethrowerFuel existingFuel = stack.getOrDefault(TFMGDataComponents.FLAMETHROWER_FUEL, FlamethrowerFuel.EMPTY);
if(stack.get(TFMGDataComponents.FLAMETHROWER_FUEL)==null)
stack.set(TFMGDataComponents.FLAMETHROWER_FUEL,"");
if(stack.get(TFMGDataComponents.AMOUNT)==null)
stack.set(TFMGDataComponents.AMOUNT,0);
if(level.getBlockEntity(pos)!=null)
if(level.getBlockEntity(pos) instanceof FluidTankBlockEntity fluidTankBe){
FluidTankBlockEntity be = fluidTankBe.isController() ? fluidTankBe : fluidTankBe.getControllerBE();
for(FlamethrowerFuel fuel : FlamethrowerFuel.values()) {
String fluid = be.getFluid(0).getFluid().getFluidType().toString().replaceFirst("tfmg:","");
if (fluid.equals(fuel.name().toLowerCase())) {
if(stack.get(TFMGDataComponents.FLAMETHROWER_FUEL).equals(fluid)||stack.get(TFMGDataComponents.AMOUNT)==0) {
int toDrain = Math.min(FUEL_CAPACITY - stack.get(TFMGDataComponents.AMOUNT), be.getFluid(0).getAmount());
stack.set(TFMGDataComponents.FLAMETHROWER_FUEL, fluid);
be.getTankInventory().drain(toDrain, IFluidHandler.FluidAction.EXECUTE);
stack.set(TFMGDataComponents.AMOUNT, stack.get(TFMGDataComponents.AMOUNT) + toDrain);
context.getPlayer().getCooldowns().addCooldown(stack.getItem(), 20);
int containedFuel = existingFuel.amount();
@Nullable ResourceKey<FlamethrowerFuelType> fuelType = existingFuel.fuelType();
boolean foundFluid = false;
if (blockEntity != null) {
IFluidHandler capability = level.getCapability(Capabilities.FluidHandler.BLOCK, blockEntity.getBlockPos(), context.getClickedFace());
if (capability != null) {
if (!foundFluid) {
for (int i = 0; i < capability.getTanks(); i++) {
if (capability.getFluidInTank(i).isEmpty()) continue;
FluidStack fluidStack = capability.getFluidInTank(i);
int toDrain = Math.min(FUEL_CAPACITY - containedFuel, fluidStack.getAmount());
FluidStack stackToDrain = fluidStack.copyWithAmount(toDrain);
FlamethrowerFuel fuel = FlamethrowerFuel.createForType(level.registryAccess(), fluidStack.getFluid(), toDrain);
if (fuel == null) continue;
if (fuelType != null) {
if (fuelType.equals(fuel.fuelType())) {
stack.set(TFMGDataComponents.FLAMETHROWER_FUEL, existingFuel.increment(toDrain, FUEL_CAPACITY));
capability.drain(stackToDrain, IFluidHandler.FluidAction.EXECUTE);
context.getPlayer().getCooldowns().addCooldown(stack.getItem(), 20);
foundFluid = true;
}
} else {
stack.set(TFMGDataComponents.FLAMETHROWER_FUEL, fuel);
capability.drain(stackToDrain, IFluidHandler.FluidAction.EXECUTE);
context.getPlayer().getCooldowns().addCooldown(stack.getItem(), 20);
foundFluid = true;
}
}
}
}
}
return foundFluid ? InteractionResult.SUCCESS : InteractionResult.PASS;
}
}
@Nullable
public static FlamethrowerFuelType getFuel(RegistryAccess registryAccess, ItemStack heldStack) {
var type = heldStack.get(TFMGDataComponents.FLAMETHROWER_FUEL).getFuelType(registryAccess);
return type.orElse(null);
}
@Override
@OnlyIn(Dist.CLIENT)
public void appendHoverText(ItemStack stack, TooltipContext context, List<Component> tooltip, TooltipFlag flag) {
if (!stack.has(TFMGDataComponents.FLAMETHROWER_FUEL) || stack.get(TFMGDataComponents.FLAMETHROWER_FUEL) == FlamethrowerFuel.EMPTY) {
super.appendHoverText(stack, context, tooltip, flag);
return;
}
LocalPlayer player = Minecraft.getInstance().player;
if (player == null) {
super.appendHoverText(stack, context, tooltip, flag);
return;
}
FlamethrowerFuelType fuelType = getFuel(player.registryAccess(), stack);
if (fuelType == null) {
super.appendHoverText(stack, context, tooltip, flag);
return;
}
FluidStack fuelFluid = new FluidStack(fuelType.fluids().get(0).value(), 1);
FlamethrowerFuel fuel = stack.getOrDefault(TFMGDataComponents.FLAMETHROWER_FUEL, FlamethrowerFuel.EMPTY);
String _spread = "flamethrower.fuel.spread";
String _speed = "flamethrower.fuel.speed";
String _amount = "flamethrower.fuel.amount";
String _cold = "flamethrower.fuel.cold";
String _hellfire = "flamethrower.fuel.hellfire";
return InteractionResult.PASS;
String _capacity = "flamethrower.fuel.capacity";
tooltip.add(CommonComponents.EMPTY);
tooltip.add(Component.translatable(fuelFluid.getDescriptionId()).append(Component.literal(":")).withStyle(ChatFormatting.GRAY));
MutableComponent spacing = CommonComponents.space();
ChatFormatting green = ChatFormatting.GREEN;
ChatFormatting darkGreen = ChatFormatting.DARK_GREEN;
ChatFormatting red = ChatFormatting.RED;
int spreadF = fuelType.spread();
float speedF = fuelType.speed();
int amountF = fuelType.amount();
boolean coldF = fuelType.isCold();
boolean hellfireF = fuelType.hellfire();
MutableComponent spread = Component.literal("" + spreadF);
MutableComponent speed = Component.literal(speedF == Mth.floor(speedF) ? "" + Mth.floor(speedF) : "" + speedF);
MutableComponent amount = Component.literal("" + amountF);
MutableComponent fuelCapacity = Component.literal(fuel.amount() + " / " + FUEL_CAPACITY + " mB");
spread = spread.withStyle(spreadF > 20 ? green : darkGreen);
speed = speed.withStyle(speedF > 1 ? green : darkGreen);
amount = amount.withStyle(amountF > 10 ? green : darkGreen);
fuelCapacity = fuelCapacity.withStyle(stack.get(TFMGDataComponents.FLAMETHROWER_FUEL).amount() == 0 ? red : green);
tooltip.add(spacing.plainCopy()
.append(CreateLang.translateDirect(_capacity, fuelCapacity)
.withStyle(darkGreen)));
tooltip.add(spacing.plainCopy()
.append(CreateLang.translateDirect(_spread, spread)
.withStyle(darkGreen)));
tooltip.add(spacing.plainCopy()
.append(CreateLang.translateDirect(_speed, speed)
.withStyle(darkGreen)));
tooltip.add(spacing.plainCopy()
.append(CreateLang.translateDirect(_amount, amount)
.withStyle(darkGreen)));
if (coldF) {
tooltip.add(spacing.plainCopy()
.append(CreateLang.translateDirect(_cold)
.withStyle(darkGreen)));
} else if (hellfireF) {
tooltip.add(spacing.plainCopy()
.append(CreateLang.translateDirect(_hellfire)
.withStyle(darkGreen)));
}
}
@Override
public boolean shouldCauseReequipAnimation(ItemStack oldStack, ItemStack newStack, boolean slotChanged) {
return slotChanged || newStack.getItem() != oldStack.getItem();
}
@Override
@@ -187,40 +298,4 @@ public class FlamethrowerItem extends Item implements CustomArmPoseItem {
public UseAnim getUseAnimation(ItemStack pStack) {
return UseAnim.NONE;
}
enum FlamethrowerFuel{
GASOLINE(15,1,3,0xC4AA76),
DIESEL(7,2,3,0xBA9177),
KEROSENE(10,1.3f,4,0x7876D5),
NAPHTHA(20,0.8f,1,0x5E1B0A),
LPG(35,0.6f,15,0xE0BB48),
NAPALM(20,1.8f,15,0xA3C649),
MOLTEN_SLAG(15,0.3f,15,0xFF9621)
;
public final float spread;
public final float speed;
public final int amount;
public final int color;
FlamethrowerFuel(float spread, float speed, int amount,int color){
this.spread = spread;
this.speed = speed;
this.amount = amount;
this.color = color;
}
}
}

View File

@@ -4,16 +4,16 @@ package com.drmangotea.tfmg.content.items.weapons.quad_potato_cannon;
import com.drmangotea.tfmg.TFMGClient;
import com.simibubi.create.AllEnchantments;
import com.simibubi.create.AllEntityTypes;
import com.simibubi.create.CreateClient;
import com.simibubi.create.api.equipment.potatoCannon.PotatoCannonProjectileType;
import com.simibubi.create.content.equipment.armor.BacktankUtil;
import com.simibubi.create.content.equipment.potatoCannon.PotatoCannonItem;
import com.simibubi.create.content.equipment.potatoCannon.PotatoCannonPacket;
import com.simibubi.create.content.equipment.potatoCannon.PotatoProjectileEntity;
import com.simibubi.create.content.equipment.zapper.ShootableGadgetItemMethods;
import com.simibubi.create.foundation.item.CustomArmPoseItem;
import com.simibubi.create.foundation.item.render.SimpleCustomRenderer;
import com.simibubi.create.foundation.utility.CreateLang;
import com.simibubi.create.foundation.utility.GlobalRegistryAccess;
import com.simibubi.create.infrastructure.config.AllConfigs;
@@ -44,7 +44,6 @@ import net.minecraft.world.item.TooltipFlag;
import net.minecraft.world.item.UseAnim;
import net.minecraft.world.item.context.UseOnContext;
import net.minecraft.world.item.enchantment.Enchantment;
import net.minecraft.world.item.enchantment.EnchantmentHelper;
import net.minecraft.world.item.enchantment.Enchantments;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.state.BlockState;
@@ -53,10 +52,12 @@ import net.minecraft.world.phys.Vec3;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.api.distmarker.OnlyIn;
import net.neoforged.neoforge.client.extensions.common.IClientItemExtensions;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Predicate;
public class QuadPotatoCannonItem extends ProjectileWeaponItem implements CustomArmPoseItem {
@@ -91,7 +92,7 @@ public class QuadPotatoCannonItem extends ProjectileWeaponItem implements Custom
@Override
public InteractionResultHolder<ItemStack> use(Level level, Player player, InteractionHand hand) {
ItemStack heldStack = player.getItemInHand(hand);
if (ShootableGadgetItemMethods.shouldSwap(player, heldStack, hand, s -> s.getItem() instanceof PotatoCannonItem)) {
if (ShootableGadgetItemMethods.shouldSwap(player, heldStack, hand, s -> s.getItem() instanceof QuadPotatoCannonItem)) {
return InteractionResultHolder.fail(heldStack);
}
@@ -103,7 +104,7 @@ public class QuadPotatoCannonItem extends ProjectileWeaponItem implements Custom
PotatoCannonProjectileType projectileType = ammo.type();
if (level.isClientSide) {
CreateClient.POTATO_CANNON_RENDER_HANDLER.dontAnimateItem(hand);
TFMGClient.QUAD_POTATO_CANNON_RENDER_HANDLER.dontAnimateItem(hand);
return InteractionResultHolder.success(heldStack);
}
@@ -157,9 +158,9 @@ public class QuadPotatoCannonItem extends ProjectileWeaponItem implements Custom
if (!BacktankUtil.canAbsorbDamage(player, maxUses()))
heldStack.hurtAndBreak(1, player, LivingEntity.getSlotForHand(hand));
ShootableGadgetItemMethods.applyCooldown(player, heldStack, hand, s -> s.getItem() instanceof PotatoCannonItem, projectileType.reloadTicks());
ShootableGadgetItemMethods.applyCooldown(player, heldStack, hand, s -> s.getItem() instanceof QuadPotatoCannonItem, projectileType.reloadTicks());
ShootableGadgetItemMethods.sendPackets(player,
b -> new PotatoCannonPacket(barrelPos, lookVec.normalize(), ammoStack, hand, soundPitch, b));
b -> new QuadPotatoCannonPacket(barrelPos, lookVec.normalize(), ammoStack, hand, soundPitch, b));
return InteractionResultHolder.success(heldStack);
}
@@ -302,6 +303,12 @@ public class QuadPotatoCannonItem extends ProjectileWeaponItem implements Custom
return null;
}
@Override
@OnlyIn(Dist.CLIENT)
public void initializeClient(Consumer<IClientItemExtensions> consumer) {
consumer.accept(SimpleCustomRenderer.create(this, new QuadPotatoCannonItemRenderer()));
}
public record Ammo(ItemStack stack, PotatoCannonProjectileType type) {
}

View File

@@ -2,6 +2,7 @@ package com.drmangotea.tfmg.content.items.weapons.quad_potato_cannon;
import com.drmangotea.tfmg.TFMGClient;
import com.drmangotea.tfmg.registry.TFMGItems;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.math.Axis;
import com.simibubi.create.content.equipment.potatoCannon.PotatoCannonItem;
@@ -12,39 +13,59 @@ import net.createmod.catnip.animation.AnimationTickHolder;
import net.minecraft.client.Minecraft;
import net.minecraft.client.player.LocalPlayer;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.entity.ItemRenderer;
import net.minecraft.util.Mth;
import net.minecraft.world.entity.HumanoidArm;
import net.minecraft.world.item.ItemDisplayContext;
import net.minecraft.world.item.ItemStack;
import net.neoforged.neoforge.client.IItemDecorator;
public class QuadPotatoCannonItemRenderer extends CustomRenderedItemModelRenderer {
@Override
protected void render(ItemStack stack, CustomRenderedItemModel model, PartialItemModelRenderer renderer,
ItemDisplayContext transformType, PoseStack ms, MultiBufferSource buffer, int light, int overlay) {
ItemRenderer itemRenderer = Minecraft.getInstance()
.getItemRenderer();
renderer.render(model.getOriginalModel(), light);
public static final IItemDecorator DECORATOR = (guiGraphics, font, stack, xOffset, yOffset) -> {
LocalPlayer player = Minecraft.getInstance().player;
boolean mainHand = player.getMainHandItem() == stack;
boolean offHand = player.getOffhandItem() == stack;
boolean leftHanded = player.getMainArm() == HumanoidArm.LEFT;
if (player == null) {
return false;
}
float offset = .5f / 16;
float worldTime = AnimationTickHolder.getRenderTime() / 10;
float angle = worldTime * -25;
float speed = TFMGClient.QUAD_POTATO_CANNON_RENDER_HANDLER.getAnimation(mainHand ^ leftHanded,
AnimationTickHolder.getPartialTicks());
PotatoCannonItem.Ammo ammo = QuadPotatoCannonItem.getAmmo(player, stack);
if (ammo == null || TFMGItems.QUAD_POTATO_CANNON.is(ammo.stack())) {
return false;
}
PoseStack poseStack = guiGraphics.pose();
poseStack.pushPose();
poseStack.translate(xOffset, yOffset + 8, 100);
poseStack.scale(.5f, .5f, .5f);
guiGraphics.renderItem(ammo.stack(), 0, 0);
poseStack.popPose();
return false;
};
@Override
protected void render(ItemStack stack, CustomRenderedItemModel model, PartialItemModelRenderer renderer, ItemDisplayContext transformType, PoseStack ms, MultiBufferSource buffer, int light, int overlay) {
renderer.render(model.getOriginalModel(), light);
Minecraft mc = Minecraft.getInstance();
LocalPlayer player = mc.player;
float angle = AnimationTickHolder.getRenderTime() * -2.5f;
if (player != null) {
boolean inMainHand = player.getMainHandItem() == stack;
boolean inOffHand = player.getOffhandItem() == stack;
if (inMainHand || inOffHand) {
boolean leftHanded = player.getMainArm() == HumanoidArm.LEFT;
float speed = TFMGClient.QUAD_POTATO_CANNON_RENDER_HANDLER.getAnimation(inMainHand ^ leftHanded,
AnimationTickHolder.getPartialTicks());
angle += 360 * Mth.clamp(speed * 5, 0, 1);
}
}
if (mainHand || offHand)
angle += 360 * Mth.clamp(speed * 5, 0, 1);
angle %= 360;
float offset = .5f / 16;
ms.pushPose();
ms.translate(0, offset, 0);
ms.mulPose(Axis.ZP.rotationDegrees(angle));
ms.translate(0, -offset, 0);
// renderer.render(model.getPartial("cog"), light);
ms.popPose();

View File

@@ -0,0 +1,51 @@
package com.drmangotea.tfmg.content.items.weapons.quad_potato_cannon;
import com.drmangotea.tfmg.TFMGClient;
import com.drmangotea.tfmg.registry.TFMGPackets;
import com.simibubi.create.content.equipment.zapper.ShootGadgetPacket;
import com.simibubi.create.content.equipment.zapper.ShootableGadgetRenderHandler;
import net.createmod.catnip.codecs.stream.CatnipStreamCodecs;
import net.minecraft.network.RegistryFriendlyByteBuf;
import net.minecraft.network.codec.ByteBufCodecs;
import net.minecraft.network.codec.StreamCodec;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.phys.Vec3;
public class QuadPotatoCannonPacket extends ShootGadgetPacket {
public static final StreamCodec<RegistryFriendlyByteBuf, QuadPotatoCannonPacket> STREAM_CODEC = StreamCodec.composite(
CatnipStreamCodecs.VEC3, packet -> packet.location,
CatnipStreamCodecs.VEC3, packet -> packet.motion,
ItemStack.OPTIONAL_STREAM_CODEC, packet -> packet.item,
CatnipStreamCodecs.HAND, packet -> packet.hand,
ByteBufCodecs.FLOAT, packet -> packet.pitch,
ByteBufCodecs.BOOL, packet -> packet.self,
QuadPotatoCannonPacket::new
);
private final float pitch;
private final Vec3 motion;
private final ItemStack item;
public QuadPotatoCannonPacket(Vec3 location, Vec3 motion, ItemStack item, InteractionHand hand, float pitch, boolean self) {
super(location, hand, self);
this.motion = motion;
this.item = item;
this.pitch = pitch;
}
@Override
protected void handleAdditional() {
TFMGClient.QUAD_POTATO_CANNON_RENDER_HANDLER.beforeShoot(pitch, location, motion, item);
}
@Override
protected ShootableGadgetRenderHandler getHandler() {
return TFMGClient.QUAD_POTATO_CANNON_RENDER_HANDLER;
}
@Override
public PacketTypeProvider getTypeProvider() {
return TFMGPackets.QUAD_POTATO_CANNON;
}
}

View File

@@ -1,10 +1,10 @@
package com.drmangotea.tfmg.content.items.weapons.quad_potato_cannon;
import com.drmangotea.tfmg.registry.TFMGItems;
import com.mojang.blaze3d.vertex.PoseStack;
import com.simibubi.create.content.equipment.potatoCannon.PotatoProjectileEntity;
import com.simibubi.create.content.equipment.zapper.ShootableGadgetRenderHandler;
import com.simibubi.create.foundation.particle.AirParticleData;
import dev.engine_room.flywheel.lib.transform.TransformStack;
import net.createmod.catnip.math.VecHelper;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.ClientLevel;
@@ -25,7 +25,7 @@ public class QuadPotatoCannonRenderHandler extends ShootableGadgetRenderHandler
@Override
protected boolean appliesTo(ItemStack stack) {
return false;
return stack.getItem() instanceof QuadPotatoCannonItem;
}
public void beforeShoot(float nextPitch, Vec3 location, Vec3 motion, ItemStack stack) {
@@ -47,12 +47,17 @@ public class QuadPotatoCannonRenderHandler extends ShootableGadgetRenderHandler
@Override
protected void transformTool(PoseStack ms, float flip, float equipProgress, float recoil, float pt) {
ms.translate(flip * -.1f, 0, .14f);
ms.scale(.75f, .75f, .75f);
TransformStack.of(ms)
.rotateXDegrees(recoil * 80);
}
@Override
protected void transformHand(PoseStack ms, float flip, float equipProgress, float recoil, float pt) {
ms.translate(flip * -.09, -.275, -.25);
TransformStack.of(ms)
.rotateZDegrees(flip * -10);
}
}

View File

@@ -1,10 +1,8 @@
package com.drmangotea.tfmg.content.machinery.vat.base;
import com.drmangotea.tfmg.TFMG;
import com.drmangotea.tfmg.mixin.accessor.TankSegmentAccessor;
import com.drmangotea.tfmg.recipes.VatMachineRecipe;
import com.drmangotea.tfmg.registry.TFMGBlockEntities;
import com.drmangotea.tfmg.registry.TFMGPackets;
import com.drmangotea.tfmg.registry.TFMGRecipeTypes;
import com.simibubi.create.api.boiler.BoilerHeater;
import com.simibubi.create.api.connectivity.ConnectivityHandler;
@@ -24,9 +22,8 @@ import com.simibubi.create.foundation.recipe.RecipeFinder;
import com.simibubi.create.foundation.utility.CreateLang;
import com.simibubi.create.infrastructure.config.AllConfigs;
import net.createmod.catnip.animation.LerpedFloat;
import net.createmod.catnip.data.Couple;
import net.createmod.catnip.lang.LangBuilder;
import net.createmod.catnip.platform.CatnipServices;
import net.createmod.catnip.theme.Color;
import net.createmod.ponder.api.level.PonderLevel;
import net.minecraft.ChatFormatting;
import net.minecraft.core.BlockPos;
@@ -35,13 +32,11 @@ import net.minecraft.core.HolderLookup;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtUtils;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.crafting.Ingredient;
import net.minecraft.world.item.crafting.Recipe;
import net.minecraft.world.item.crafting.RecipeHolder;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
@@ -59,7 +54,6 @@ import net.neoforged.neoforge.items.IItemHandlerModifiable;
import net.neoforged.neoforge.items.wrapper.CombinedInvWrapper;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -73,6 +67,7 @@ public class VatBlockEntity extends SmartBlockEntity implements IHaveGoggleInfor
public VatInventory outputInventory;
public SmartFluidTankBehaviour inputTank;
public SmartFluidTankBehaviour outputTank;
private Couple<SmartFluidTankBehaviour> tanks;
protected IFluidHandler fluidCapability;
protected IItemHandlerModifiable itemCapability;
protected boolean forceFluidLevelUpdate;
@@ -112,6 +107,7 @@ public class VatBlockEntity extends SmartBlockEntity implements IHaveGoggleInfor
// window = false;
inputInventory = new VatInventory(4, this);
outputInventory = new VatInventory(4, this);
tanks = Couple.create(inputTank, outputTank);
itemCapability = new CombinedInvWrapper(inputInventory, outputInventory);
forceFluidLevelUpdate = true;
updateConnectivity = false;
@@ -124,6 +120,10 @@ public class VatBlockEntity extends SmartBlockEntity implements IHaveGoggleInfor
}
public Couple<SmartFluidTankBehaviour> getTanks() {
return tanks;
}
public static void registerCapabilities(RegisterCapabilitiesEvent event) {
event.registerBlockEntity(
Capabilities.FluidHandler.BLOCK,
@@ -186,9 +186,7 @@ public class VatBlockEntity extends SmartBlockEntity implements IHaveGoggleInfor
int tankNumber = 0;
for (int i = 0; i < 8; i++) {
IFluidHandler fluidHandler = fluidCapability;
if(fluidHandler != null) {
fluidLevel[i].chase((double) (fluidHandler.getFluidInTank(tankNumber).getAmount()) / inputTank.getPrimaryHandler().getCapacity(), .5f, LerpedFloat.Chaser.EXP);
getFillState();
tankNumber++;
@@ -602,8 +600,7 @@ public class VatBlockEntity extends SmartBlockEntity implements IHaveGoggleInfor
recipe = getMatchingRecipe();
FluidStack newFluidStack = inputTank.getPrimaryHandler().getFluid();
FluidType attributes = newFluidStack.getFluid()
.getFluidType();
FluidType attributes = newFluidStack.getFluid().getFluidType();
int luminosity = (int) (attributes.getLightLevel(newFluidStack) / 1.2f);
boolean reversed = attributes.isLighterThanAir();
int maxY = (int) ((getFillState() * height) + 1);
@@ -707,6 +704,43 @@ public class VatBlockEntity extends SmartBlockEntity implements IHaveGoggleInfor
notifyUpdate();
}
public int getTotalCapacity() {
int totalCapacity = 0;
for (SmartFluidTankBehaviour behaviour : getTanks()) {
if (behaviour == null)
continue;
for (SmartFluidTankBehaviour.TankSegment tankSegment : behaviour.getTanks()) {
totalCapacity += ((TankSegmentAccessor)tankSegment).tfmg$tank().getCapacity();
}
}
return totalCapacity;
}
public float getTotalFluidUnits(float partialTicks) {
int renderedFluids = 0;
float totalUnits = 0;
for (SmartFluidTankBehaviour behaviour : getTanks()) {
if (behaviour == null)
continue;
for (SmartFluidTankBehaviour.TankSegment tankSegment : behaviour.getTanks()) {
if (tankSegment.getRenderedFluid()
.isEmpty())
continue;
float units = tankSegment.getTotalUnits(partialTicks);
if (units < 1)
continue;
totalUnits += units;
renderedFluids++;
}
}
if (renderedFluids == 0)
return 0;
if (totalUnits < 1)
return 0;
return totalUnits;
}
public boolean isAtValidLocation(IVatMachine.PositionRequirement requirement, BlockPos pos) {
return switch (requirement) {
@@ -725,25 +759,20 @@ public class VatBlockEntity extends SmartBlockEntity implements IHaveGoggleInfor
}
public void applyVatSize(int blocks) {
//inputTank.getPrimaryHandler().setCapacity(blocks * getCapacityMultiplier());
//outputTank.getPrimaryHandler().setCapacity(blocks * getCapacityMultiplier());
inputTank.forEach(s -> {
((TankSegmentAccessor) s).tfmg$tank().setCapacity(blocks * getCapacityMultiplier());
SmartFluidTank tank = ((TankSegmentAccessor) s).tfmg$tank();
tank.setCapacity(blocks * getCapacityMultiplier());
int overflow = tank.getFluidAmount() - tank.getCapacity();
if (overflow > 0)
tank.drain(overflow, IFluidHandler.FluidAction.EXECUTE);
});
outputTank.forEach(s -> {
((TankSegmentAccessor) s).tfmg$tank().setCapacity(blocks * getCapacityMultiplier());
SmartFluidTank tank = ((TankSegmentAccessor) s).tfmg$tank();
tank.setCapacity(blocks * getCapacityMultiplier());
int overflow = tank.getFluidAmount() - tank.getCapacity();
if (overflow > 0)
tank.drain(overflow, IFluidHandler.FluidAction.EXECUTE);
});
int overflow = inputTank.getPrimaryHandler().getFluidAmount() - inputTank.getPrimaryHandler().getCapacity();
if (overflow > 0)
inputTank.getPrimaryHandler().drain(overflow, IFluidHandler.FluidAction.EXECUTE);
int overflow2 = outputTank.getPrimaryHandler().getFluidAmount() - outputTank.getPrimaryHandler().getCapacity();
if (overflow2 > 0)
outputTank.getPrimaryHandler().drain(overflow2, IFluidHandler.FluidAction.EXECUTE);
forceFluidLevelUpdate = true;
@@ -1012,12 +1041,18 @@ public class VatBlockEntity extends SmartBlockEntity implements IHaveGoggleInfor
window = compound.getBoolean("Window");
width = compound.getInt("Size");
height = compound.getInt("Height");
inputTank.getPrimaryHandler().setCapacity(getTotalTankSize() * getCapacityMultiplier());
outputTank.getPrimaryHandler().setCapacity(getTotalTankSize() * getCapacityMultiplier());
if (inputTank.getPrimaryHandler().getSpace() < 0)
inputTank.getPrimaryHandler().drain(-inputTank.getPrimaryHandler().getSpace(), IFluidHandler.FluidAction.EXECUTE);
if (outputTank.getPrimaryHandler().getSpace() < 0)
outputTank.getPrimaryHandler().drain(-outputTank.getPrimaryHandler().getSpace(), IFluidHandler.FluidAction.EXECUTE);
inputTank.forEach(s -> {
SmartFluidTank tank = ((TankSegmentAccessor) s).tfmg$tank();
tank.setCapacity(getTotalTankSize() * getCapacityMultiplier());
if (tank.getSpace() < 0)
tank.drain(-tank.getSpace(), IFluidHandler.FluidAction.EXECUTE);
});
outputTank.forEach(s -> {
SmartFluidTank tank = ((TankSegmentAccessor) s).tfmg$tank();
tank.setCapacity(getTotalTankSize() * getCapacityMultiplier());
if (tank.getSpace() < 0)
tank.drain(-tank.getSpace(), IFluidHandler.FluidAction.EXECUTE);
});
inputInventory.deserializeNBT(registries,compound.getCompound("InputItems"));
outputInventory.deserializeNBT(registries,compound.getCompound("OutputItems"));
//
@@ -1041,8 +1076,8 @@ public class VatBlockEntity extends SmartBlockEntity implements IHaveGoggleInfor
if (hasLevel())
level.sendBlockUpdated(getBlockPos(), getBlockState(), getBlockState(), 16);
if (isController()) {
inputTank.getPrimaryHandler().setCapacity(getCapacityMultiplier() * getTotalTankSize());
outputTank.getPrimaryHandler().setCapacity(getCapacityMultiplier() * getTotalTankSize());
inputTank.forEach(s -> ((TankSegmentAccessor) s).tfmg$tank().setCapacity(getCapacityMultiplier() * getTotalTankSize()));
outputTank.forEach(s -> ((TankSegmentAccessor) s).tfmg$tank().setCapacity(getCapacityMultiplier() * getTotalTankSize()));
}
invalidateRenderBoundingBox();
}

View File

@@ -2,6 +2,8 @@ package com.drmangotea.tfmg.content.machinery.vat.base;
import com.mojang.blaze3d.vertex.PoseStack;
import com.simibubi.create.content.processing.basin.BasinBlockEntity;
import com.simibubi.create.foundation.blockEntity.behaviour.fluid.SmartFluidTankBehaviour;
import com.simibubi.create.foundation.blockEntity.renderer.SafeBlockEntityRenderer;
import com.simibubi.create.foundation.fluid.FluidRenderer;
import com.simibubi.create.foundation.fluid.SmartFluidTank;
@@ -10,6 +12,7 @@ import net.createmod.catnip.platform.NeoForgeCatnipServices;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider;
import net.minecraft.util.Mth;
import net.neoforged.neoforge.fluids.FluidStack;
import net.neoforged.neoforge.fluids.capability.IFluidHandler;
@@ -24,73 +27,54 @@ public class VatRenderer extends SafeBlockEntityRenderer<VatBlockEntity> {
if (!be.isController())
return;
LerpedFloat[] fluidLevel = be.getFluidLevel();
if (fluidLevel == null)
return;
if (!be.window)
return;
float fluidLevel = renderFluids(be, partialTicks, ms, bufferSource, light, overlay);
}
protected float renderFluids(VatBlockEntity vat, float partialTicks, PoseStack ms, MultiBufferSource buffer, int light, int overlay) {
SmartFluidTankBehaviour inputFluids = vat.getBehaviour(SmartFluidTankBehaviour.INPUT);
SmartFluidTankBehaviour outputFluids = vat.getBehaviour(SmartFluidTankBehaviour.OUTPUT);
SmartFluidTankBehaviour[] tanks = { inputFluids, outputFluids };
float totalUnits = vat.getTotalFluidUnits(partialTicks);
if (totalUnits < 1)
return 0;
float fluidLevel = Mth.clamp(totalUnits / vat.getTotalCapacity(), 0, 1);
fluidLevel = 1 - ((1 - fluidLevel) * (1 - fluidLevel));
float capHeight = 1 / 4f;
float tankHullWidth = 1 / 16f + 1 / 128f;
float minPuddleHeight = 1 / 16f;
ms.pushPose();
float totalFluidHeight = 0;
float xMin = tankHullWidth;
float xMax = xMin + be.width - 2 * tankHullWidth;
float xMax = xMin + vat.width - 2 * tankHullWidth;
float zMin = tankHullWidth;
float zMax = zMin + be.width - 2 * tankHullWidth;
float zMax = zMin + vat.width - 2 * tankHullWidth;
int tankNumber = 0;
for (int i = 0; i < 8; i++) {
float level = 0;
IFluidHandler fluidHandler = be.fluidCapability;
if (fluidHandler.getFluidInTank(tankNumber).isEmpty())
for (SmartFluidTankBehaviour behaviour : tanks) {
if (behaviour == null)
continue;
for (SmartFluidTankBehaviour.TankSegment tankSegment : behaviour.getTanks()) {
FluidStack renderedFluid = tankSegment.getRenderedFluid();
if (renderedFluid.isEmpty())
continue;
float units = tankSegment.getTotalUnits(partialTicks);
if (units < 1)
continue;
float yMin = capHeight + level;
float yMax = yMin + (fluidLevel * (vat.height - (2 * capHeight))) / 5;
float level = fluidLevel[i].getValue(partialTicks);
float yMin = capHeight + totalFluidHeight;
float yMax = yMin + (level * (be.height - (2 * capHeight))) / 8;
NeoForgeCatnipServices.FLUID_RENDERER.renderFluidBox(renderedFluid, xMin, yMin, zMin, xMax, yMax, zMax,
buffer, ms, light, false, false);
NeoForgeCatnipServices.FLUID_RENDERER.renderFluidBox(fluidHandler.getFluidInTank(tankNumber), xMin, yMin, zMin, xMax, yMax, zMax, bufferSource, ms, light, false, false);
tankNumber++;
totalFluidHeight += yMax-yMin;
level += yMax - yMin;
}
}
ms.popPose();
// float level = fluidLevel.getValue(partialTicks);
// if (level < 1 / (512f * totalHeight))
// return;
//
// float clampedLevel = Mth.clamp(level * totalHeight, 0, totalHeight);
//
//
// IFluidHandler fluidHandler = be.getCapability(ForgeCapabilities.FLUID_HANDLER).orElse(null);
//
//
// float xMin = tankHullWidth;
// float xMax = xMin + be.width - 2 * tankHullWidth;
// float yMin = totalHeight + capHeight + minPuddleHeight - clampedLevel;
// float yMax = yMin + clampedLevel;
//
//
// float zMin = tankHullWidth;
// float zMax = zMin + be.width - 2 * tankHullWidth;
//
// ms.pushPose();
// ms.translate(0, clampedLevel - totalHeight, 0);
//
// for (int i = 0; i < fluidHandler.getTanks(); i++) {
// if (!fluidHandler.getFluidInTank(i).isEmpty()) {
// //FluidStack stack = fluidHandler.getFluidInTank()
// //FluidRenderer.renderFluidBox(fluidHandler.getFluidInTank(i), xMin, yMin, zMin, xMax, yMax, zMax, bufferSource, ms, light, false);
// //break;
// }
// }
// ms.popPose();
return level;
}
@Override

View File

@@ -69,6 +69,19 @@ public class ElectrodeHolderBlockEntity extends ElectricBlockEntity implements I
return true;
}
@Override
public void tick() {
super.tick();
if (level == null) return;
var vatBE = level.getBlockEntity(getBlockPos().relative(Direction.DOWN));
if (vatBE instanceof VatBlockEntity vat) {
BlockPos electrodePos = getBlockPos().relative(Direction.DOWN);
this.electrode.tick(vat.getControllerBE(), this.level, electrodePos, isOperational(), this.level.isClientSide());
}
}
@Override
public float resistance() {
return this.electrode.getResistance();

View File

@@ -2,17 +2,13 @@ package com.drmangotea.tfmg.content.machinery.vat.electrode_holder;
import com.drmangotea.tfmg.TFMG;
import com.drmangotea.tfmg.base.TFMGUtils;
import com.drmangotea.tfmg.registry.TFMGPartialModels;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.math.Axis;
import com.simibubi.create.foundation.blockEntity.renderer.SafeBlockEntityRenderer;
import net.createmod.catnip.render.CachedBuffers;
import net.minecraft.client.renderer.LevelRenderer;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider;
import net.minecraft.client.renderer.entity.ItemRenderer;
import net.minecraft.client.renderer.texture.OverlayTexture;
import net.minecraft.world.item.ItemDisplayContext;
import net.minecraft.world.level.block.state.BlockState;
@@ -25,8 +21,7 @@ public class ElectrodeHolderRenderer extends SafeBlockEntityRenderer<ElectrodeHo
}
@Override
protected void renderSafe(ElectrodeHolderBlockEntity be, float partialTicks, PoseStack ms, MultiBufferSource buffer,
int light, int overlay) {
protected void renderSafe(ElectrodeHolderBlockEntity be, float partialTicks, PoseStack ms, MultiBufferSource buffer, int light, int overlay) {
BlockState blockState = be.getBlockState();
@@ -36,12 +31,13 @@ public class ElectrodeHolderRenderer extends SafeBlockEntityRenderer<ElectrodeHo
return;
if (be.electrode.getStack().isEmpty())
return;
if (be.getLevel() == null)
return;
ms.pushPose();
ms.mulPose(Axis.XP.rotationDegrees(0));
ms.translate(0.5, -1.4369, 0.5);
ms.scale(3.33f, 3.33f, 3.33f);
itemRenderer.renderStatic(be.electrode.getStack(), ItemDisplayContext.GROUND, LevelRenderer.getLightColor(be.getLevel(), be.getBlockPos().below()), OverlayTexture.NO_OVERLAY, ms, buffer, be.getLevel(), 0);
itemRenderer.renderStatic(be.electrode.getStack(), ItemDisplayContext.GROUND, LevelRenderer.getLightColor(be.getLevel(), be.getBlockPos().below()), overlay, ms, buffer, be.getLevel(), 0);
ms.popPose();
}

View File

@@ -0,0 +1,22 @@
package com.drmangotea.tfmg.content.machinery.vat.electrode_holder.electrode;
import com.drmangotea.tfmg.content.machinery.vat.base.VatBlockEntity;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.particles.ParticleTypes;
import net.minecraft.util.ParticleUtils;
import net.minecraft.util.valueproviders.UniformInt;
import net.minecraft.world.level.Level;
public class ArcElectrode extends Electrode {
public ArcElectrode(Properties properties) {
super(properties.operationId("tfmg:graphite_electrode"));
}
@Override
public void tick(VatBlockEntity controllerVat, Level level, BlockPos pos, boolean active, boolean clientTick) {
if (active && clientTick) {
ParticleUtils.spawnParticlesAlongAxis(Direction.Axis.Y, level, pos, 0.25F, ParticleTypes.ELECTRIC_SPARK, UniformInt.of(1, 2));
}
}
}

View File

@@ -1,10 +1,13 @@
package com.drmangotea.tfmg.content.machinery.vat.electrode_holder.electrode;
import com.drmangotea.tfmg.content.machinery.vat.base.VatBlockEntity;
import com.tterrag.registrate.util.entry.ItemEntry;
import net.minecraft.Util;
import net.minecraft.core.BlockPos;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
public class Electrode {
private String descriptionId;
@@ -36,6 +39,10 @@ public class Electrode {
return this.operationId;
}
public void tick(VatBlockEntity controllerVat, Level level, BlockPos pos, boolean active, boolean clientTick) {
}
public String getOrCreateDescriptionId() {
if (this.descriptionId == null) {
this.descriptionId = Util.makeDescriptionId("electrode", getKey());

View File

@@ -2,6 +2,8 @@ package com.drmangotea.tfmg.datagen;
import com.drmangotea.tfmg.TFMG;
import com.drmangotea.tfmg.TFMGRegistries;
import com.drmangotea.tfmg.registry.TFMGFlamethrowerFuelTypes;
import com.drmangotea.tfmg.worldgen.TFMGBiomeModifiers;
import com.drmangotea.tfmg.worldgen.TFMGConfiguredFeatures;
import com.drmangotea.tfmg.worldgen.TFMGPlacedFeatures;
@@ -17,7 +19,8 @@ import java.util.concurrent.CompletableFuture;
public class TFMGGeneratedEntriesProvider extends DatapackBuiltinEntriesProvider {
private static final RegistrySetBuilder BUILDER = new RegistrySetBuilder()
.add(Registries.CONFIGURED_FEATURE, (RegistrySetBuilder.RegistryBootstrap) TFMGConfiguredFeatures::bootstrap)
.add(TFMGRegistries.FLAMETHROWER_FUEL_TYPE, TFMGFlamethrowerFuelTypes::bootstrap)
.add(Registries.CONFIGURED_FEATURE, TFMGConfiguredFeatures::bootstrap)
.add(Registries.PLACED_FEATURE, TFMGPlacedFeatures::bootstrap)
.add(NeoForgeRegistries.Keys.BIOME_MODIFIERS, TFMGBiomeModifiers::bootstrap)
.add(Registries.DAMAGE_TYPE, TFMGDamageTypes::bootstrap);

View File

@@ -5,6 +5,8 @@ import java.util.UUID;
import java.util.function.UnaryOperator;
import com.drmangotea.tfmg.TFMG;
import com.drmangotea.tfmg.content.items.weapons.flamethrover.FlamethrowerFuel;
import net.minecraft.resources.ResourceLocation;
import org.jetbrains.annotations.ApiStatus.Internal;
import com.mojang.serialization.Codec;
@@ -77,9 +79,9 @@ public class TFMGDataComponents {
"timer",
builder -> builder.persistent(Codec.INT).networkSynchronized(ByteBufCodecs.VAR_INT)
);
public static final DataComponentType<String> FLAMETHROWER_FUEL = register(
public static final DataComponentType<FlamethrowerFuel> FLAMETHROWER_FUEL = register(
"flamethrower_fuel",
builder -> builder.persistent(Codec.STRING).networkSynchronized(ByteBufCodecs.STRING_UTF8)
builder -> builder.persistent(FlamethrowerFuel.CODEC).networkSynchronized(FlamethrowerFuel.STREAM_CODEC)
);
public static final DataComponentType<Integer> ACCUMULATOR_STORAGE = register(
"storage",

View File

@@ -1,5 +1,6 @@
package com.drmangotea.tfmg.registry;
import com.drmangotea.tfmg.content.machinery.vat.electrode_holder.electrode.ArcElectrode;
import com.drmangotea.tfmg.content.machinery.vat.electrode_holder.electrode.Electrode;
import com.drmangotea.tfmg.content.machinery.vat.electrode_holder.electrode.ElectrodeEntry;
@@ -27,11 +28,10 @@ public class TFMGElectrodes {
)
.register();
public static final ElectrodeEntry<Electrode> graphite = REGISTRATE.electrode("graphite", Electrode::new)
public static final ElectrodeEntry<ArcElectrode> graphite = REGISTRATE.electrode("graphite", ArcElectrode::new)
.properties((p) -> p
.resistance(300)
.item(TFMGItems.GRAPHITE_ELECTRODE)
.operationId("tfmg:graphite_electrode")
)
.register();

View File

@@ -0,0 +1,65 @@
package com.drmangotea.tfmg.registry;
import com.drmangotea.tfmg.TFMG;
import com.drmangotea.tfmg.TFMGRegistries;
import com.drmangotea.tfmg.content.items.weapons.flamethrover.FlamethrowerFuelType;
import net.minecraft.data.worldgen.BootstrapContext;
import net.minecraft.resources.ResourceKey;
public class TFMGFlamethrowerFuelTypes {
public static final ResourceKey<FlamethrowerFuelType> FALLBACK = ResourceKey.create(TFMGRegistries.FLAMETHROWER_FUEL_TYPE, TFMG.asResource("fallback"));
public static void bootstrap(BootstrapContext<FlamethrowerFuelType> ctx) {
register(ctx, "fallback", new FlamethrowerFuelType.Builder()
.spread(0).speed(0)
.amount(0).color(0x000000)
.build());
register(ctx, "gasoline", new FlamethrowerFuelType.Builder()
.spread(15).speed(1)
.amount(3).color(0xC4AA76)
.addFluids(TFMGFluids.GASOLINE.get())
.build());
register(ctx, "diesel", new FlamethrowerFuelType.Builder()
.spread(7).speed(2)
.amount(3).color(0xBA9177)
.addFluids(TFMGFluids.DIESEL.get())
.build());
register(ctx, "kerosene", new FlamethrowerFuelType.Builder()
.spread(10).speed(1.3f)
.amount(4).color(0x7876D5)
.addFluids(TFMGFluids.KEROSENE.get())
.build());
register(ctx, "naphtha", new FlamethrowerFuelType.Builder()
.spread(20).speed(0.8f)
.amount(1).color(0x5E1B0A)
.addFluids(TFMGFluids.NAPHTHA.get())
.build());
register(ctx, "lpg", new FlamethrowerFuelType.Builder()
.spread(35).speed(0.6f)
.amount(16).color(0xE0BB48)
.addFluids(TFMGFluids.LPG.get())
.build());
register(ctx, "napalm", new FlamethrowerFuelType.Builder()
.spread(20).speed(1.8f)
.amount(15).color(0xA3C649)
.addFluids(TFMGFluids.NAPALM.get())
.build());
register(ctx, "molten_slag", new FlamethrowerFuelType.Builder()
.spread(15).speed(0.3f)
.amount(15).color(0xFF8C00)
.addFluids(TFMGFluids.MOLTEN_SLAG.get())
.build());
}
private static void register(BootstrapContext<FlamethrowerFuelType> ctx, String name, FlamethrowerFuelType type) {
ctx.register(ResourceKey.create(TFMGRegistries.FLAMETHROWER_FUEL_TYPE, TFMG.asResource(name)), type);
}
}

View File

@@ -10,6 +10,7 @@ import com.drmangotea.tfmg.content.electricity.configuration_wrench.Electricians
import com.drmangotea.tfmg.content.engines.engine_controller.TransmissionRemovePacket;
import com.drmangotea.tfmg.content.engines.engine_controller.packets.*;
import com.drmangotea.tfmg.content.items.weapons.advanced_potato_cannon.AdvancedPotatoCannonPacket;
import com.drmangotea.tfmg.content.items.weapons.quad_potato_cannon.QuadPotatoCannonPacket;
import com.drmangotea.tfmg.content.machinery.metallurgy.coke_oven.CokeOvenPacket;
import com.drmangotea.tfmg.content.machinery.oil_processing.distillation_tower.controller.DistillationTowerPacket;
import com.drmangotea.tfmg.content.machinery.vat.base.VatEvaluationPacket;
@@ -26,8 +27,9 @@ import java.util.Locale;
public enum TFMGPackets implements BasePacketPayload.PacketTypeProvider {
// Server to Client
ADVANCED_POTATO_CANNON(AdvancedPotatoCannonPacket.class, AdvancedPotatoCannonPacket.STREAM_CODEC),
//QUAD_POTATO_CANNON(QuadPotatoCannonPacket.class, QuadPotatoCannonPacket::new, PLAY_TO_CLIENT),
QUAD_POTATO_CANNON(QuadPotatoCannonPacket.class, QuadPotatoCannonPacket.STREAM_CODEC),
CONNECT_NEIGHBORS(ConnectNeightborsPacket.class, ConnectNeightborsPacket.STREAM_CODEC),
NETWORK_UPDATE(NetworkUpdatePacket.class, NetworkUpdatePacket.STREAM_CODEC),
CONNECTION_PACKET(ConnectionPacket.class, ConnectionPacket.STREAM_CODEC),
@@ -39,7 +41,7 @@ public enum TFMGPackets implements BasePacketPayload.PacketTypeProvider {
CABLE_PLACE_PACKET(CablePlacePacket.class, CablePlacePacket.STREAM_CODEC),
// Client to Server
ELECTRICIANS_WRENCH_PACKET(ElectriciansWrenchPacket.class, ElectriciansWrenchPacket.STREAM_CODEC),
ENGINE_CONTROLLER_INPUT(EngineControllerInputPacket.class, EngineControllerInputPacket.STREAM_CODEC),
// ENGINE_CONTROLLER_BIND(EngineControllerBindPacket.class, EngineControllerBindPacket::new, PLAY_TO_SERVER),

View File

@@ -167,7 +167,14 @@
"tfmg.subtitle.engine_sounds": "Engine Sounds",
"tfmg.subtitle.diesel_engine_sounds": "Diesel Engine Sounds"
"tfmg.subtitle.diesel_engine_sounds": "Diesel Engine Sounds",
"create.flamethrower.fuel.spread": "%s Projectile Spread",
"create.flamethrower.fuel.speed": "%s Projectile Speed",
"create.flamethrower.fuel.amount": "%s Projectile Amount",
"create.flamethrower.fuel.cold": "Cold Flame",
"create.flamethrower.fuel.hellfire": "Scorching Flame",
"create.flamethrower.fuel.capacity": "Fuel Capacity: %s"
}