initial
This commit is contained in:
113
src/main/java/com/drmangotea/tfmg/TFMG.java
Normal file
113
src/main/java/com/drmangotea/tfmg/TFMG.java
Normal file
@@ -0,0 +1,113 @@
|
||||
package com.drmangotea.tfmg;
|
||||
|
||||
import com.drmangotea.tfmg.base.TFMGContraptions;
|
||||
import com.drmangotea.tfmg.base.TFMGCreativeTabs;
|
||||
import com.drmangotea.tfmg.base.TFMGRegistrate;
|
||||
import com.drmangotea.tfmg.content.electricity.base.ElectricNetworkManager;
|
||||
import com.drmangotea.tfmg.content.items.weapons.explosives.thermite_grenades.fire.TFMGColoredFires;
|
||||
import com.drmangotea.tfmg.datagen.TFMGDatagen;
|
||||
import com.drmangotea.tfmg.base.fluid.TFMGFluidInteractions;
|
||||
import com.drmangotea.tfmg.config.TFMGConfigs;
|
||||
import com.drmangotea.tfmg.content.decoration.pipes.TFMGPipes;
|
||||
import com.drmangotea.tfmg.registry.*;
|
||||
import com.mojang.logging.LogUtils;
|
||||
import com.simibubi.create.content.processing.burner.BlazeBurnerBlock;
|
||||
import net.minecraft.client.renderer.ItemBlockRenderTypes;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.eventbus.api.EventPriority;
|
||||
import net.minecraftforge.eventbus.api.IEventBus;
|
||||
import net.minecraftforge.fml.DistExecutor;
|
||||
import net.minecraftforge.fml.ModLoadingContext;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
|
||||
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
|
||||
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import static com.simibubi.create.content.fluids.tank.BoilerHeaters.registerHeater;
|
||||
|
||||
|
||||
@SuppressWarnings("removal")
|
||||
@Mod(TFMG.MOD_ID)
|
||||
public class TFMG {
|
||||
|
||||
public static final String MOD_ID = "tfmg";
|
||||
public static final ElectricNetworkManager NETWORK_MANAGER = new ElectricNetworkManager();
|
||||
|
||||
public static final Logger LOGGER = LogUtils.getLogger();
|
||||
|
||||
public static final TFMGRegistrate REGISTRATE = TFMGRegistrate.create();
|
||||
|
||||
|
||||
|
||||
public TFMG() {
|
||||
IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus();
|
||||
|
||||
REGISTRATE.registerEventListeners(modEventBus);
|
||||
|
||||
TFMGBlocks.init();
|
||||
TFMGBlockEntities.init();
|
||||
TFMGItems.init();
|
||||
TFMGEntityTypes.init();
|
||||
TFMGPartialModels.init();
|
||||
TFMGPipes.init();
|
||||
TFMGFluids.init();
|
||||
TFMGEncasedBlocks.init();
|
||||
TFMGPaletteBlocks.init();
|
||||
|
||||
|
||||
TFMGParticleTypes.register(modEventBus);
|
||||
TFMGCreativeTabs.register(modEventBus);
|
||||
TFMGMobEffects.register(modEventBus);
|
||||
TFMGRecipeTypes.register(modEventBus);
|
||||
TFMGColoredFires.register(modEventBus);
|
||||
|
||||
|
||||
TFMGContraptions.prepare();
|
||||
TFMGPackets.registerPackets();
|
||||
TFMGConfigs.register(ModLoadingContext.get());
|
||||
modEventBus.addListener(EventPriority.LOWEST, TFMGDatagen::gatherData);
|
||||
modEventBus.addListener(TFMG::commonSetup);
|
||||
modEventBus.addListener(this::clientSetup);
|
||||
MinecraftForge.EVENT_BUS.register(this);
|
||||
DistExecutor.safeRunWhenOn(Dist.CLIENT, () -> TFMGClient::new);
|
||||
modEventBus.addListener(TFMGCreativeTabs::addCreative);
|
||||
|
||||
}
|
||||
@SuppressWarnings("removal")
|
||||
private void clientSetup(final FMLClientSetupEvent event) {
|
||||
ItemBlockRenderTypes.setRenderLayer(TFMGColoredFires.GREEN_FIRE.get(), RenderType.cutout());
|
||||
ItemBlockRenderTypes.setRenderLayer(TFMGColoredFires.BLUE_FIRE.get(), RenderType.cutout());
|
||||
}
|
||||
|
||||
/**
|
||||
* fluid interaction & firebox heating
|
||||
*/
|
||||
public static void commonSetup(final FMLCommonSetupEvent event) {
|
||||
TFMGFluidInteractions.registerFluidInteractions();
|
||||
|
||||
event.enqueueWork(() -> {
|
||||
|
||||
registerHeater(TFMGBlocks.FIREBOX.get(), (level, pos, state) -> {
|
||||
BlazeBurnerBlock.HeatLevel value = state.getValue(BlazeBurnerBlock.HEAT_LEVEL);
|
||||
if (value == BlazeBurnerBlock.HeatLevel.NONE) {
|
||||
return -1;
|
||||
}
|
||||
if (value.isAtLeast(BlazeBurnerBlock.HeatLevel.FADING)) {
|
||||
return 1;
|
||||
}
|
||||
return -1;
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static ResourceLocation asResource(String path) {
|
||||
return new ResourceLocation(MOD_ID, path);
|
||||
}
|
||||
}
|
||||
42
src/main/java/com/drmangotea/tfmg/TFMGClient.java
Normal file
42
src/main/java/com/drmangotea/tfmg/TFMGClient.java
Normal file
@@ -0,0 +1,42 @@
|
||||
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.registry.TFMGParticleTypes;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.eventbus.api.IEventBus;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
|
||||
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
|
||||
|
||||
public class TFMGClient {
|
||||
|
||||
/**
|
||||
* does not work, too bad!
|
||||
*/
|
||||
public static final QuadPotatoCannonRenderHandler QUAD_POTATO_CANNON_RENDER_HANDLER = new QuadPotatoCannonRenderHandler();
|
||||
public static final AdvancedPotatoCannonRenderHandler ADVANCED_POTATO_CANNON_RENDER_HANDLER = new AdvancedPotatoCannonRenderHandler();
|
||||
|
||||
public static final FlamethrowerRenderHandler FLAMETHROWER_RENDER_HANDLER = new FlamethrowerRenderHandler();
|
||||
|
||||
|
||||
public TFMGClient() {
|
||||
IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus();
|
||||
IEventBus forgeEventBus = MinecraftForge.EVENT_BUS;
|
||||
modEventBus.addListener(TFMGParticleTypes::registerFactories);
|
||||
modEventBus.register(this);
|
||||
|
||||
|
||||
ADVANCED_POTATO_CANNON_RENDER_HANDLER.registerListeners(forgeEventBus);
|
||||
QUAD_POTATO_CANNON_RENDER_HANDLER.registerListeners(forgeEventBus);
|
||||
FLAMETHROWER_RENDER_HANDLER.registerListeners(forgeEventBus);
|
||||
}
|
||||
|
||||
|
||||
@SubscribeEvent
|
||||
public void setup(final FMLClientSetupEvent event) {
|
||||
// TFMGPonderIndex.register();
|
||||
// TFMGPonderIndex.registerTags();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.drmangotea.tfmg.base;
|
||||
|
||||
|
||||
import com.simibubi.create.AllPartialModels;
|
||||
import com.simibubi.create.content.kinetics.base.DirectionalKineticBlock;
|
||||
import com.simibubi.create.content.kinetics.base.KineticBlockEntity;
|
||||
import com.simibubi.create.content.kinetics.base.KineticBlockEntityRenderer;
|
||||
import com.simibubi.create.foundation.render.CachedBufferer;
|
||||
import com.simibubi.create.foundation.render.SuperByteBuffer;
|
||||
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
|
||||
public class HalfShaftRenderer<T extends KineticBlockEntity> extends KineticBlockEntityRenderer<T> {
|
||||
|
||||
public HalfShaftRenderer(BlockEntityRendererProvider.Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SuperByteBuffer getRotatedModel(T be, BlockState state) {
|
||||
return CachedBufferer.partialFacing(AllPartialModels.SHAFT_HALF, state, state
|
||||
.getValue(DirectionalKineticBlock.FACING));
|
||||
}
|
||||
}
|
||||
21
src/main/java/com/drmangotea/tfmg/base/HellFireEffect.java
Normal file
21
src/main/java/com/drmangotea/tfmg/base/HellFireEffect.java
Normal file
@@ -0,0 +1,21 @@
|
||||
package com.drmangotea.tfmg.base;
|
||||
|
||||
import net.minecraft.world.effect.MobEffect;
|
||||
import net.minecraft.world.effect.MobEffectCategory;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
|
||||
public class HellFireEffect extends MobEffect {
|
||||
public HellFireEffect(MobEffectCategory pCategory, int pColor) {
|
||||
super(pCategory, pColor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyEffectTick(LivingEntity pLivingEntity, int pAmplifier) {
|
||||
pLivingEntity.setSecondsOnFire(1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDurationEffectTick(int pDuration, int pAmplifier) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
14
src/main/java/com/drmangotea/tfmg/base/MaterialSet.java
Normal file
14
src/main/java/com/drmangotea/tfmg/base/MaterialSet.java
Normal file
@@ -0,0 +1,14 @@
|
||||
package com.drmangotea.tfmg.base;
|
||||
|
||||
import com.tterrag.registrate.util.entry.BlockEntry;
|
||||
|
||||
public class MaterialSet {
|
||||
|
||||
|
||||
public BlockEntry<?> block;
|
||||
public BlockEntry<?> slab;
|
||||
public BlockEntry<?> stairs;
|
||||
public BlockEntry<?> wall;
|
||||
|
||||
public MaterialSet(){}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
package com.drmangotea.tfmg.base;
|
||||
|
||||
import com.drmangotea.tfmg.TFMG;
|
||||
import com.drmangotea.tfmg.registry.TFMGItems;
|
||||
import com.google.common.base.Suppliers;
|
||||
import net.minecraft.sounds.SoundEvent;
|
||||
import net.minecraft.sounds.SoundEvents;
|
||||
import net.minecraft.world.item.ArmorItem;
|
||||
import net.minecraft.world.item.ArmorMaterial;
|
||||
import net.minecraft.world.item.crafting.Ingredient;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public enum TFMGArmorMaterials implements ArmorMaterial {
|
||||
|
||||
STEEL(TFMG.asResource("steel").toString(), 30, new int[]{3, 6, 8, 3}, 18, () -> SoundEvents.ARMOR_EQUIP_NETHERITE, 2.0F, 0.1F,
|
||||
() -> Ingredient.of(TFMGItems.STEEL_INGOT.get()))
|
||||
;
|
||||
private static final int[] MAX_DAMAGE_ARRAY = new int[] { 13, 15, 16, 11 };
|
||||
private final String name;
|
||||
private final int maxDamageFactor;
|
||||
private final int[] damageReductionAmountArray;
|
||||
private final int enchantability;
|
||||
private final Supplier<SoundEvent> soundEvent;
|
||||
private final float toughness;
|
||||
private final float knockbackResistance;
|
||||
private final Supplier<Ingredient> repairMaterial;
|
||||
|
||||
private TFMGArmorMaterials(String name, int maxDamageFactor, int[] damageReductionAmountArray, int enchantability,
|
||||
Supplier<SoundEvent> soundEvent, float toughness, float knockbackResistance, Supplier<Ingredient> repairMaterial) {
|
||||
this.name = name;
|
||||
this.maxDamageFactor = maxDamageFactor;
|
||||
this.damageReductionAmountArray = damageReductionAmountArray;
|
||||
this.enchantability = enchantability;
|
||||
this.soundEvent = soundEvent;
|
||||
this.toughness = toughness;
|
||||
this.knockbackResistance = knockbackResistance;
|
||||
this.repairMaterial = Suppliers.memoize(repairMaterial::get);
|
||||
}
|
||||
@Override
|
||||
public int getDurabilityForType(ArmorItem.Type type) {
|
||||
return switch (type){
|
||||
case HELMET -> MAX_DAMAGE_ARRAY[3] * this.maxDamageFactor;
|
||||
case CHESTPLATE -> MAX_DAMAGE_ARRAY[2] * this.maxDamageFactor;
|
||||
case LEGGINGS -> MAX_DAMAGE_ARRAY[1] * this.maxDamageFactor;
|
||||
case BOOTS -> MAX_DAMAGE_ARRAY[0] * this.maxDamageFactor;
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDefenseForType(ArmorItem.Type type) {
|
||||
return switch (type){
|
||||
case HELMET -> damageReductionAmountArray[3];
|
||||
case CHESTPLATE -> damageReductionAmountArray[2];
|
||||
case LEGGINGS -> damageReductionAmountArray[1];
|
||||
case BOOTS -> damageReductionAmountArray[0];
|
||||
};
|
||||
}
|
||||
@Override
|
||||
public int getEnchantmentValue() {
|
||||
return this.enchantability;
|
||||
}
|
||||
@Override
|
||||
public SoundEvent getEquipSound() {
|
||||
return this.soundEvent.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Ingredient getRepairIngredient() {
|
||||
return this.repairMaterial.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getToughness() {
|
||||
return this.toughness;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getKnockbackResistance() {
|
||||
return this.knockbackResistance;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,405 @@
|
||||
package com.drmangotea.tfmg.base;
|
||||
|
||||
|
||||
import com.drmangotea.tfmg.TFMG;
|
||||
import com.drmangotea.tfmg.content.decoration.FrameBlock;
|
||||
import com.drmangotea.tfmg.content.decoration.TrussBlock;
|
||||
import com.drmangotea.tfmg.content.decoration.doors.TFMGSlidingDoorBlock;
|
||||
import com.drmangotea.tfmg.content.decoration.encased.TFMGEncasedCogwheelBlock;
|
||||
import com.drmangotea.tfmg.content.decoration.encased.TFMGEncasedShaftBlock;
|
||||
import com.drmangotea.tfmg.content.decoration.flywheels.TFMGFlywheelBlock;
|
||||
import com.drmangotea.tfmg.registry.TFMGBlocks;
|
||||
import com.simibubi.create.AllBlocks;
|
||||
import com.simibubi.create.AllTags;
|
||||
import com.simibubi.create.content.contraptions.behaviour.DoorMovingInteraction;
|
||||
import com.simibubi.create.content.decoration.encasing.EncasedCTBehaviour;
|
||||
import com.simibubi.create.content.decoration.slidingDoor.SlidingDoorMovementBehaviour;
|
||||
import com.simibubi.create.content.kinetics.BlockStressDefaults;
|
||||
import com.simibubi.create.content.kinetics.base.RotatedPillarKineticBlock;
|
||||
import com.simibubi.create.content.kinetics.simpleRelays.encased.EncasedCogCTBehaviour;
|
||||
import com.simibubi.create.foundation.block.connected.CTSpriteShiftEntry;
|
||||
import com.simibubi.create.foundation.data.*;
|
||||
import com.tterrag.registrate.builders.BlockBuilder;
|
||||
import com.tterrag.registrate.util.DataIngredient;
|
||||
import com.tterrag.registrate.util.entry.BlockEntry;
|
||||
import com.tterrag.registrate.util.nullness.NonNullUnaryOperator;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.data.recipes.RecipeCategory;
|
||||
import net.minecraft.tags.BlockTags;
|
||||
import net.minecraft.tags.ItemTags;
|
||||
import net.minecraft.world.level.ItemLike;
|
||||
import net.minecraft.world.level.block.*;
|
||||
import net.minecraft.world.level.block.state.BlockBehaviour;
|
||||
import net.minecraftforge.client.model.generators.ModelFile;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import static com.drmangotea.tfmg.TFMG.REGISTRATE;
|
||||
import static com.simibubi.create.AllInteractionBehaviours.interactionBehaviour;
|
||||
import static com.simibubi.create.AllMovementBehaviours.movementBehaviour;
|
||||
import static com.simibubi.create.foundation.data.BlockStateGen.axisBlock;
|
||||
import static com.simibubi.create.foundation.data.BlockStateGen.simpleCubeAll;
|
||||
import static com.simibubi.create.foundation.data.ModelGen.customItemModel;
|
||||
import static com.simibubi.create.foundation.data.TagGen.*;
|
||||
|
||||
@SuppressWarnings("removal")
|
||||
public class TFMGBuilderTransformers {
|
||||
|
||||
public static <B extends TFMGSlidingDoorBlock, P> NonNullUnaryOperator<BlockBuilder<B, P>> slidingDoor(String type) {
|
||||
return b -> b.initialProperties(() -> Blocks.IRON_DOOR)
|
||||
.properties(p -> p.requiresCorrectToolForDrops()
|
||||
.strength(3.0F, 6.0F))
|
||||
.blockstate((c, p) -> {
|
||||
ModelFile bottom = AssetLookup.partialBaseModel(c, p, "bottom");
|
||||
ModelFile top = AssetLookup.partialBaseModel(c, p, "top");
|
||||
p.doorBlock(c.get(), bottom, bottom, bottom, bottom, top, top, top, top);
|
||||
})
|
||||
.addLayer(() -> RenderType::cutoutMipped)
|
||||
.transform(pickaxeOnly())
|
||||
.onRegister(interactionBehaviour(new DoorMovingInteraction()))
|
||||
.onRegister(movementBehaviour(new SlidingDoorMovementBehaviour()))
|
||||
.tag(BlockTags.DOORS)
|
||||
.tag(BlockTags.WOODEN_DOORS) // for villager AI
|
||||
.tag(AllTags.AllBlockTags.NON_DOUBLE_DOOR.tag)
|
||||
.loot((lr, block) -> lr.add(block, lr.createDoorTable(block)))
|
||||
.item()
|
||||
.tag(ItemTags.DOORS)
|
||||
.tag(AllTags.AllItemTags.CONTRAPTION_CONTROLLED.tag)
|
||||
.model((c, p) -> p.blockSprite(c, p.modLoc("item/" + type + "_door")))
|
||||
.build();
|
||||
}
|
||||
|
||||
public static <B extends Block, P> NonNullUnaryOperator<BlockBuilder<B, P>> surfaceScanner() {
|
||||
return b -> b.initialProperties(SharedProperties::softMetal)
|
||||
.blockstate((c, p) -> p.horizontalBlock(c.get(), p.models()
|
||||
.getExistingFile(p.modLoc("block/surface_scanner/block"))))
|
||||
.addLayer(() -> RenderType::cutoutMipped)
|
||||
.item()
|
||||
.transform(ModelGen.customItemModel("surface_scanner", "item"));
|
||||
}
|
||||
|
||||
public static <B extends TFMGEncasedShaftBlock, P> NonNullUnaryOperator<BlockBuilder<B, P>> encasedShaft(String casing,
|
||||
Supplier<CTSpriteShiftEntry> casingShift) {
|
||||
return builder -> encasedBase(builder, AllBlocks.SHAFT::get)
|
||||
.onRegister(CreateRegistrate.connectedTextures(() -> new EncasedCTBehaviour(casingShift.get())))
|
||||
.onRegister(CreateRegistrate.casingConnectivity((block, cc) -> cc.make(block, casingShift.get(),
|
||||
(s, f) -> f.getAxis() != s.getValue(TFMGEncasedShaftBlock.AXIS))))
|
||||
.blockstate((c, p) -> axisBlock(c, p, blockState -> p.models()
|
||||
.getExistingFile(p.modLoc("block/encased_shaft/block_" + casing)), true))
|
||||
.item()
|
||||
.model(AssetLookup.customBlockItemModel("encased_shaft", "item_" + casing))
|
||||
.build();
|
||||
}
|
||||
|
||||
public static <B extends TFMGEncasedCogwheelBlock, P> NonNullUnaryOperator<BlockBuilder<B, P>> encasedCogwheel(
|
||||
String casing, Supplier<CTSpriteShiftEntry> casingShift) {
|
||||
return b -> encasedCogwheelBase(b, casing, casingShift, AllBlocks.COGWHEEL::get, false);
|
||||
}
|
||||
|
||||
public static <B extends TFMGEncasedCogwheelBlock, P> NonNullUnaryOperator<BlockBuilder<B, P>> encasedLargeCogwheel(
|
||||
String casing, Supplier<CTSpriteShiftEntry> casingShift) {
|
||||
return b -> encasedCogwheelBase(b, casing, casingShift, AllBlocks.LARGE_COGWHEEL::get, true)
|
||||
.onRegister(CreateRegistrate.connectedTextures(() -> new EncasedCogCTBehaviour(casingShift.get())));
|
||||
}
|
||||
|
||||
private static <B extends TFMGEncasedCogwheelBlock, P> BlockBuilder<B, P> encasedCogwheelBase(BlockBuilder<B, P> b,
|
||||
String casing, Supplier<CTSpriteShiftEntry> casingShift, Supplier<ItemLike> drop, boolean large) {
|
||||
String encasedSuffix;
|
||||
if (!large) {
|
||||
encasedSuffix = "_encased_cogwheel_side" + (large ? "_connected" : "");
|
||||
} else encasedSuffix = "_encased_cogwheel_side_large";
|
||||
String blockFolder = large ? "encased_large_cogwheel" : "encased_cogwheel";
|
||||
String wood = casing.equals("steel") ? "steel_casing" : "heavy_machinery_casing";
|
||||
String gearbox = casing.equals("steel") ? "steel_gearbox" : "heavy_gearbox";
|
||||
|
||||
String casing1 = casing.equals("heavy_casing") ? "heavy_machinery" : casing;
|
||||
return encasedBase(b, drop).addLayer(() -> RenderType::cutoutMipped)
|
||||
.onRegister(CreateRegistrate.casingConnectivity((block, cc) -> cc.make(block, casingShift.get(),
|
||||
(s, f) -> f.getAxis() == s.getValue(TFMGEncasedCogwheelBlock.AXIS)
|
||||
&& !s.getValue(f.getAxisDirection() == Direction.AxisDirection.POSITIVE ? TFMGEncasedCogwheelBlock.TOP_SHAFT
|
||||
: TFMGEncasedCogwheelBlock.BOTTOM_SHAFT))))
|
||||
.blockstate((c, p) -> axisBlock(c, p, blockState -> {
|
||||
String suffix = (blockState.getValue(TFMGEncasedCogwheelBlock.TOP_SHAFT) ? "_top" : "")
|
||||
+ (blockState.getValue(TFMGEncasedCogwheelBlock.BOTTOM_SHAFT) ? "_bottom" : "");
|
||||
String modelName = c.getName() + suffix;
|
||||
return p.models()
|
||||
.withExistingParent(modelName, p.modLoc("block/" + blockFolder + "/block" + suffix))
|
||||
.texture("casing", TFMG.asResource("block/" + casing1 + "_casing"))
|
||||
.texture("particle", TFMG.asResource("block/" + casing1 + "_casing"))
|
||||
.texture("4", TFMG.asResource("block/" + gearbox))
|
||||
.texture("1", TFMG.asResource("block/" + wood))
|
||||
.texture("side", TFMG.asResource("block/" + casing1 + encasedSuffix));
|
||||
}, false))
|
||||
.item()
|
||||
.model((c, p) -> p.withExistingParent(c.getName(), p.modLoc("block/" + blockFolder + "/item"))
|
||||
.texture("casing", TFMG.asResource("block/" + casing1 + "_casing"))
|
||||
.texture("particle", TFMG.asResource("block/" + casing1 + "_casing"))
|
||||
.texture("1", TFMG.asResource("block/" + wood))
|
||||
.texture("side", TFMG.asResource("block/" + casing1 + encasedSuffix)))
|
||||
.build();
|
||||
}
|
||||
|
||||
private static <B extends RotatedPillarKineticBlock, P> BlockBuilder<B, P> encasedBase(BlockBuilder<B, P> b,
|
||||
Supplier<ItemLike> drop) {
|
||||
return b.initialProperties(SharedProperties::stone)
|
||||
.properties(BlockBehaviour.Properties::noOcclusion)
|
||||
.transform(BlockStressDefaults.setNoImpact())
|
||||
.loot((p, lb) -> p.dropOther(lb, drop.get()));
|
||||
}
|
||||
//public static <B extends CopycatCableBlock, P> NonNullUnaryOperator<BlockBuilder<B, P>> copycatCable() {
|
||||
// return b -> b.initialProperties(SharedProperties::softMetal)
|
||||
// .blockstate((c, p) -> p.simpleBlock(c.get(), p.models()
|
||||
// .getExistingFile(p.mcLoc("air"))))
|
||||
// .initialProperties(SharedProperties::softMetal)
|
||||
// .properties(BlockBehaviour.Properties::noOcclusion)
|
||||
// .addLayer(() -> RenderType::solid)
|
||||
// .addLayer(() -> RenderType::cutout)
|
||||
// .addLayer(() -> RenderType::cutoutMipped)
|
||||
// // .addLayer(() -> RenderType::translucent)
|
||||
// .color(() -> CopycatCableBlock::wrappedColor)
|
||||
// .transform(TagGen.axeOrPickaxe());
|
||||
//}
|
||||
|
||||
///////////////
|
||||
public static BlockEntry<TFMGFlywheelBlock> flywheel(String name) {
|
||||
return REGISTRATE.block(name + "_flywheel", TFMGFlywheelBlock::new)
|
||||
.initialProperties(SharedProperties::softMetal)
|
||||
.properties(BlockBehaviour.Properties::noOcclusion)
|
||||
.transform(axeOrPickaxe())
|
||||
.transform(BlockStressDefaults.setNoImpact())
|
||||
.blockstate(BlockStateGen.axisBlockProvider(true))
|
||||
.item()
|
||||
.transform(customItemModel())
|
||||
.register();
|
||||
}
|
||||
|
||||
public static BlockEntry<TrussBlock> truss(String name) {
|
||||
return REGISTRATE.block(name+"_truss", TrussBlock::new)
|
||||
.initialProperties(() -> Blocks.IRON_BLOCK)
|
||||
.properties(p -> p.noOcclusion())
|
||||
.properties(p -> p.sound(SoundType.NETHERITE_BLOCK))
|
||||
.transform(pickaxeOnly())
|
||||
.addLayer(() -> RenderType::cutoutMipped)
|
||||
.blockstate(BlockStateGen.axisBlockProvider(false))
|
||||
.item()
|
||||
.build()
|
||||
.register();
|
||||
}
|
||||
public static BlockEntry<FrameBlock> frame(String name) {
|
||||
return REGISTRATE.block(name+"_frame", FrameBlock::new)
|
||||
.initialProperties(() -> Blocks.IRON_BLOCK)
|
||||
.properties(p -> p.sound(SoundType.NETHERITE_BLOCK))
|
||||
.properties(p -> p.strength(3))
|
||||
.transform(pickaxeOnly())
|
||||
.addLayer(() -> RenderType::cutoutMipped)
|
||||
.properties(BlockBehaviour.Properties::noOcclusion)
|
||||
.blockstate((ctx, prov) -> prov.simpleBlock(ctx.getEntry(), AssetLookup.partialBaseModel(ctx, prov)))
|
||||
.simpleItem()
|
||||
.register();
|
||||
}
|
||||
public static final String[] COLORS = {"white", "blue", "light_blue", "red", "green", "lime", "pink", "magenta", "yellow", "gray", "light_gray", "brown", "cyan", "purple", "orange"};
|
||||
public static void generateCautionBlocks() {
|
||||
|
||||
|
||||
|
||||
for (String color : COLORS) {
|
||||
String firstLetter = color.substring(0, 1).toUpperCase();
|
||||
String colorWithoutC = color.substring(1);
|
||||
|
||||
String upperCaseColor = firstLetter + colorWithoutC;
|
||||
String light = "Light";
|
||||
if (upperCaseColor.contains(light)) {
|
||||
String nameWithoutLight = upperCaseColor.substring(6);
|
||||
|
||||
String firstLetter2 = nameWithoutLight.substring(0, 1).toUpperCase();
|
||||
String colorWithoutC2 = nameWithoutLight.substring(1);
|
||||
|
||||
upperCaseColor = light + " " + firstLetter2 + colorWithoutC2;
|
||||
|
||||
|
||||
}
|
||||
|
||||
REGISTRATE.block(color + "_caution_block", TFMGHorizontalDirectionalBlock::new)
|
||||
.initialProperties(() -> Blocks.COPPER_BLOCK)
|
||||
|
||||
.properties(p -> p.requiresCorrectToolForDrops())
|
||||
.properties(p -> p.sound(SoundType.NETHERITE_BLOCK))
|
||||
.transform(pickaxeOnly())
|
||||
.blockstate((c, p) -> p.horizontalBlock(c.get(), p.models()
|
||||
.withExistingParent(c.getName(), p.modLoc("block/caution_block"))
|
||||
.texture("0", p.modLoc("block/caution_block/" + color))
|
||||
.texture("particle", p.modLoc("block/caution_block/" + color))
|
||||
))
|
||||
.tag(BlockTags.NEEDS_STONE_TOOL)
|
||||
.item()
|
||||
.build()
|
||||
.lang(upperCaseColor + " Caution Block")
|
||||
.register();
|
||||
}
|
||||
}
|
||||
public static MaterialSet generateConcrete(boolean rebar) {
|
||||
|
||||
String name = rebar ? "rebar_concrete" : "concrete";
|
||||
|
||||
MaterialSet concrete = new MaterialSet();
|
||||
|
||||
generateColoredConcrete(rebar);
|
||||
|
||||
concrete.wall = REGISTRATE.block(name+"_wall", WallBlock::new)
|
||||
.initialProperties(() -> Blocks.STONE)
|
||||
.properties(p -> p.requiresCorrectToolForDrops())
|
||||
.properties(p ->p.strength(rebar ? 12f : 3.5f,rebar ? 1200f : 3.5f))
|
||||
.transform(pickaxeOnly())
|
||||
.blockstate((c, p) -> TFMGVanillaBlockStates.generateWallBlockState(c, p, "concrete"))
|
||||
.tag(BlockTags.NEEDS_STONE_TOOL)
|
||||
.tag(BlockTags.WALLS)
|
||||
.recipe((c, p) -> p.stonecutting(DataIngredient.items(concrete.block.get()), RecipeCategory.BUILDING_BLOCKS, c::get, 1))
|
||||
.item()
|
||||
.transform(b -> TFMGVanillaBlockStates.transformWallItem(b, "concrete"))
|
||||
.build()
|
||||
.register();
|
||||
|
||||
concrete.stairs = REGISTRATE.block(name+"_stairs", p -> new StairBlock(() -> concrete.block.get().defaultBlockState(), p))
|
||||
.initialProperties(() -> Blocks.STONE)
|
||||
.properties(p -> p.requiresCorrectToolForDrops())
|
||||
.properties(p ->p.strength(rebar ? 12f : 3.5f,rebar ? 1200f : 3.5f))
|
||||
.transform(pickaxeOnly())
|
||||
.blockstate((c, p) -> TFMGVanillaBlockStates.generateStairBlockState(c, p, "concrete"))
|
||||
.tag(BlockTags.NEEDS_STONE_TOOL)
|
||||
.tag(BlockTags.STAIRS)
|
||||
.recipe((c, p) -> p.stonecutting(DataIngredient.items(concrete.block.get()),RecipeCategory.BUILDING_BLOCKS, c::get, 1))
|
||||
.item()
|
||||
//.transform(b -> TFMGVanillaBlockStates.transformStairItem(b, "concrete"))
|
||||
.transform(customItemModel("concrete_stairs"))
|
||||
.register();
|
||||
|
||||
|
||||
concrete.block = REGISTRATE.block(name, Block::new)
|
||||
.initialProperties(() -> Blocks.STONE)
|
||||
.properties(p ->p.strength(rebar ? 12f : 3.5f,rebar ? 1200f : 3.5f))
|
||||
.properties(p -> p.requiresCorrectToolForDrops())
|
||||
.transform(pickaxeOnly())
|
||||
.blockstate(simpleCubeAll("concrete"))
|
||||
.tag(BlockTags.NEEDS_STONE_TOOL)
|
||||
.transform(tagBlockAndItem("concrete"))
|
||||
.build()
|
||||
.register();
|
||||
|
||||
concrete.slab = REGISTRATE.block(name+"_slab", SlabBlock::new)
|
||||
.initialProperties(() -> Blocks.STONE)
|
||||
.properties(p ->p.strength(rebar ? 12f : 3.5f,rebar ? 1200f : 3.5f))
|
||||
.properties(p -> p.requiresCorrectToolForDrops())
|
||||
.transform(pickaxeOnly())
|
||||
.blockstate((c, p) -> TFMGVanillaBlockStates.generateSlabBlockState(c, p, "concrete"))
|
||||
.tag(BlockTags.NEEDS_STONE_TOOL)
|
||||
.tag(BlockTags.SLABS)
|
||||
.recipe((c, p) -> p.stonecutting(DataIngredient.items(concrete.block.get()),RecipeCategory.BUILDING_BLOCKS, c::get, 2))
|
||||
.item()
|
||||
.transform(customItemModel("concrete_bottom"))
|
||||
.register();
|
||||
|
||||
return concrete;
|
||||
}
|
||||
public static void generateColoredConcrete(boolean rebar) {
|
||||
|
||||
String name = rebar ? "_rebar_concrete" : "_concrete";
|
||||
|
||||
for (String color : COLORS) {
|
||||
REGISTRATE.block(color +name, Block::new)
|
||||
.initialProperties(() -> Blocks.STONE)
|
||||
.properties(p ->p.strength(rebar ? 12f : 3.5f,rebar ? 1200f : 3.5f))
|
||||
.properties(p -> p.requiresCorrectToolForDrops())
|
||||
.transform(pickaxeOnly())
|
||||
.blockstate(simpleCubeAll(color + "_concrete"))
|
||||
.tag(BlockTags.NEEDS_STONE_TOOL)
|
||||
.item()
|
||||
.build()
|
||||
.register();
|
||||
|
||||
|
||||
REGISTRATE.block(color + name+"_wall", WallBlock::new)
|
||||
.initialProperties(() -> Blocks.STONE)
|
||||
.properties(p ->p.strength(rebar ? 12f : 3.5f,rebar ? 1200f : 3.5f))
|
||||
.properties(p -> p.requiresCorrectToolForDrops())
|
||||
.transform(pickaxeOnly())
|
||||
.blockstate((c, p) -> TFMGVanillaBlockStates.generateWallBlockState(c, p, color + "_concrete"))
|
||||
.tag(BlockTags.NEEDS_STONE_TOOL)
|
||||
.tag(BlockTags.WALLS)
|
||||
.item()
|
||||
.transform(b -> TFMGVanillaBlockStates.transformWallItem(b, color + "_concrete"))
|
||||
.build()
|
||||
.register();
|
||||
|
||||
REGISTRATE.block(color + name+"_stairs", p -> new StairBlock(() -> TFMGBlocks.CONCRETE.block.get().defaultBlockState(), p))
|
||||
.initialProperties(() -> Blocks.STONE)
|
||||
.properties(p ->p.strength(rebar ? 12f : 3.5f,rebar ? 1200f : 3.5f))
|
||||
.properties(p -> p.requiresCorrectToolForDrops())
|
||||
.transform(pickaxeOnly())
|
||||
.blockstate((c, p) -> TFMGVanillaBlockStates.generateStairBlockState(c, p, color + "_concrete"))
|
||||
.tag(BlockTags.NEEDS_STONE_TOOL)
|
||||
.tag(BlockTags.STAIRS)
|
||||
.item()
|
||||
// .transform(b -> TFMGVanillaBlockStates.transformStairItem(b, color + "_concrete"))
|
||||
.transform(customItemModel(color+"_concrete_stairs"))
|
||||
.register();
|
||||
|
||||
|
||||
REGISTRATE.block(color + name+"_slab", SlabBlock::new)
|
||||
.initialProperties(() -> Blocks.STONE)
|
||||
.properties(p ->p.strength(rebar ? 12f : 3.5f,rebar ? 1200f : 3.5f))
|
||||
.properties(p -> p.requiresCorrectToolForDrops())
|
||||
.transform(pickaxeOnly())
|
||||
.blockstate((c, p) -> TFMGVanillaBlockStates.generateSlabBlockState(c, p, color + "_concrete"))
|
||||
.tag(BlockTags.NEEDS_STONE_TOOL)
|
||||
.tag(BlockTags.SLABS)
|
||||
.item()
|
||||
.transform(customItemModel(color + "_concrete_bottom"))
|
||||
.register();
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
public static MaterialSet makeVariants(BlockEntry<?> blockEntry){
|
||||
MaterialSet materialSet = new MaterialSet();
|
||||
|
||||
materialSet.block = blockEntry;
|
||||
|
||||
String name = blockEntry.getId().toString().replace("tfmg:","");
|
||||
|
||||
|
||||
|
||||
REGISTRATE.block(name+"_wall", WallBlock::new)
|
||||
.initialProperties(() -> blockEntry.get())
|
||||
.transform(pickaxeOnly())
|
||||
.blockstate((c, p) -> TFMGVanillaBlockStates.generateWallBlockState(c, p, name))
|
||||
.tag(BlockTags.NEEDS_STONE_TOOL)
|
||||
.tag(BlockTags.WALLS)
|
||||
.item()
|
||||
.transform(b -> TFMGVanillaBlockStates.transformWallItem(b, name))
|
||||
.build()
|
||||
.register();
|
||||
|
||||
REGISTRATE.block(name+"_slab", SlabBlock::new)
|
||||
.initialProperties(() -> blockEntry.get())
|
||||
.properties(p -> p.requiresCorrectToolForDrops())
|
||||
.transform(pickaxeOnly())
|
||||
.blockstate((c, p) -> TFMGVanillaBlockStates.generateSlabBlockState(c, p, name))
|
||||
.tag(BlockTags.NEEDS_STONE_TOOL)
|
||||
.tag(BlockTags.SLABS)
|
||||
.item()
|
||||
.transform(customItemModel(name + "_bottom"))
|
||||
.register();
|
||||
REGISTRATE.block(name+"_stairs", p -> new StairBlock(() -> TFMGBlocks.CONCRETE.block.get().defaultBlockState(), p))
|
||||
.initialProperties(() -> Blocks.STONE)
|
||||
.transform(pickaxeOnly())
|
||||
.blockstate((c, p) -> TFMGVanillaBlockStates.generateStairBlockState(c, p, name))
|
||||
.tag(BlockTags.NEEDS_STONE_TOOL)
|
||||
.tag(BlockTags.STAIRS)
|
||||
.item()
|
||||
.transform(customItemModel(name+"_stairs"))
|
||||
.register();
|
||||
|
||||
return materialSet;
|
||||
}
|
||||
}
|
||||
23
src/main/java/com/drmangotea/tfmg/base/TFMGCommonEvents.java
Normal file
23
src/main/java/com/drmangotea/tfmg/base/TFMGCommonEvents.java
Normal file
@@ -0,0 +1,23 @@
|
||||
package com.drmangotea.tfmg.base;
|
||||
|
||||
import com.drmangotea.tfmg.TFMG;
|
||||
import com.simibubi.create.Create;
|
||||
import com.simibubi.create.foundation.utility.WorldAttached;
|
||||
import net.minecraft.world.level.LevelAccessor;
|
||||
import net.minecraftforge.event.level.LevelEvent;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
|
||||
@Mod.EventBusSubscriber
|
||||
public class TFMGCommonEvents {
|
||||
@SubscribeEvent
|
||||
public static void onLoadWorld(LevelEvent.Load event) {
|
||||
LevelAccessor world = event.getLevel();
|
||||
TFMG.NETWORK_MANAGER.onLoadWorld(world);
|
||||
}
|
||||
@SubscribeEvent
|
||||
public static void onUnloadWorld(LevelEvent.Unload event) {
|
||||
LevelAccessor world = event.getLevel();
|
||||
TFMG.NETWORK_MANAGER.onUnloadWorld(world);
|
||||
}
|
||||
}
|
||||
15
src/main/java/com/drmangotea/tfmg/base/TFMGContraptions.java
Normal file
15
src/main/java/com/drmangotea/tfmg/base/TFMGContraptions.java
Normal file
@@ -0,0 +1,15 @@
|
||||
package com.drmangotea.tfmg.base;
|
||||
|
||||
|
||||
|
||||
import com.drmangotea.tfmg.TFMG;
|
||||
import com.drmangotea.tfmg.content.machinery.oil_processing.pumpjack.pumpjack.hammer.PumpjackContraption;
|
||||
import com.simibubi.create.content.contraptions.ContraptionType;
|
||||
|
||||
public class TFMGContraptions {
|
||||
|
||||
public static final ContraptionType
|
||||
PUMPJACK_CONTRAPTION = ContraptionType.register(TFMG.asResource("pumpjack").toString(), PumpjackContraption::new);
|
||||
|
||||
public static void prepare() {}
|
||||
}
|
||||
87
src/main/java/com/drmangotea/tfmg/base/TFMGCreativeTabs.java
Normal file
87
src/main/java/com/drmangotea/tfmg/base/TFMGCreativeTabs.java
Normal file
@@ -0,0 +1,87 @@
|
||||
package com.drmangotea.tfmg.base;
|
||||
|
||||
import com.drmangotea.tfmg.content.machinery.misc.winding_machine.SpoolItem;
|
||||
import com.drmangotea.tfmg.registry.TFMGBlocks;
|
||||
import com.drmangotea.tfmg.registry.TFMGItems;
|
||||
import com.drmangotea.tfmg.registry.TFMGPaletteStoneTypes;
|
||||
import com.simibubi.create.AllCreativeModeTabs;
|
||||
import com.simibubi.create.content.processing.sequenced.SequencedAssemblyItem;
|
||||
import com.simibubi.create.foundation.data.CreateRegistrate;
|
||||
import com.tterrag.registrate.util.entry.RegistryEntry;
|
||||
import net.minecraft.core.registries.Registries;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.world.item.CreativeModeTab;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraftforge.event.BuildCreativeModeTabContentsEvent;
|
||||
import net.minecraftforge.eventbus.api.IEventBus;
|
||||
import net.minecraftforge.registries.DeferredRegister;
|
||||
import net.minecraftforge.registries.RegistryObject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static com.drmangotea.tfmg.TFMG.MOD_ID;
|
||||
import static com.drmangotea.tfmg.TFMG.REGISTRATE;
|
||||
|
||||
public class TFMGCreativeTabs {
|
||||
|
||||
|
||||
public static final DeferredRegister<CreativeModeTab> CREATIVE_MODE_TABS = DeferredRegister.create(Registries.CREATIVE_MODE_TAB, MOD_ID);
|
||||
public static final RegistryObject<CreativeModeTab> TFMG_MAIN = CREATIVE_MODE_TABS.register("tfmg_main", () -> CreativeModeTab.builder()
|
||||
.withTabsBefore(AllCreativeModeTabs.BASE_CREATIVE_TAB.getId())
|
||||
.title(Component.translatable("creative_tab.tfmg_main"))
|
||||
.icon(()-> TFMGItems.STEEL_INGOT.get().asItem().getDefaultInstance())
|
||||
.build());
|
||||
|
||||
public static final RegistryObject<CreativeModeTab> TFMG_DECORATION = CREATIVE_MODE_TABS.register("tfmg_decoration", () -> CreativeModeTab.builder()
|
||||
.withTabsBefore(TFMG_MAIN.getId())
|
||||
.title(Component.translatable("creative_tab.tfmg_decoration"))
|
||||
.icon(()-> TFMGBlocks.CONCRETE.block.get().asItem().getDefaultInstance())
|
||||
.build());
|
||||
public static void addCreative(BuildCreativeModeTabContentsEvent event) {
|
||||
if (event.getTab() == TFMG_MAIN.get()){
|
||||
for(RegistryEntry<Item> item : REGISTRATE.getAll(Registries.ITEM)){
|
||||
|
||||
if(!CreateRegistrate.isInCreativeTab(item,TFMG_MAIN))
|
||||
continue;
|
||||
if(blacklist().contains(item))
|
||||
continue;
|
||||
if(item.get() instanceof SequencedAssemblyItem)
|
||||
continue;
|
||||
if(item.get() instanceof SpoolItem&&!item.is(TFMGItems.EMPTY_SPOOL.get())){
|
||||
|
||||
ItemStack spool = item.get().getDefaultInstance();
|
||||
spool.getOrCreateTag().putInt("Amount", 1000);
|
||||
event.accept(spool);
|
||||
continue;
|
||||
}
|
||||
event.accept(item);
|
||||
}
|
||||
}
|
||||
|
||||
if (event.getTab() == TFMG_DECORATION.get()){
|
||||
for(RegistryEntry<Item> item : REGISTRATE.getAll(Registries.ITEM)){
|
||||
if(!CreateRegistrate.isInCreativeTab(item, TFMG_DECORATION))
|
||||
continue;
|
||||
if(blacklist().contains(item))
|
||||
continue;
|
||||
if(item.get() instanceof SequencedAssemblyItem)
|
||||
continue;
|
||||
|
||||
event.accept(item);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
public static void register(IEventBus modEventBus){
|
||||
CREATIVE_MODE_TABS.register(modEventBus);
|
||||
}
|
||||
|
||||
public static List<RegistryEntry<Item>> blacklist(){
|
||||
List<RegistryEntry<Item>> list = new ArrayList<>();
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.drmangotea.tfmg.base;
|
||||
|
||||
import net.minecraft.world.item.context.BlockPlaceContext;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.DirectionalBlock;
|
||||
import net.minecraft.world.level.block.HorizontalDirectionalBlock;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.StateDefinition;
|
||||
|
||||
public class TFMGDirectionalBlock extends DirectionalBlock {
|
||||
|
||||
public TFMGDirectionalBlock(Properties p_54120_) {
|
||||
super(p_54120_);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
|
||||
builder.add(FACING);
|
||||
super.createBlockStateDefinition(builder);
|
||||
}
|
||||
public BlockState getStateForPlacement(BlockPlaceContext pContext) {
|
||||
return this.defaultBlockState().setValue(FACING, pContext.getNearestLookingDirection().getOpposite());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.drmangotea.tfmg.base;
|
||||
|
||||
import net.minecraft.world.item.context.BlockPlaceContext;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.HorizontalDirectionalBlock;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.StateDefinition;
|
||||
|
||||
public class TFMGHorizontalDirectionalBlock extends HorizontalDirectionalBlock {
|
||||
|
||||
public TFMGHorizontalDirectionalBlock(Properties p_54120_) {
|
||||
super(p_54120_);
|
||||
}
|
||||
@Override
|
||||
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
|
||||
builder.add(FACING);
|
||||
super.createBlockStateDefinition(builder);
|
||||
}
|
||||
public BlockState getStateForPlacement(BlockPlaceContext pContext) {
|
||||
return this.defaultBlockState().setValue(FACING, pContext.getHorizontalDirection().getOpposite());
|
||||
}
|
||||
}
|
||||
143
src/main/java/com/drmangotea/tfmg/base/TFMGMetalBarsGen.java
Normal file
143
src/main/java/com/drmangotea/tfmg/base/TFMGMetalBarsGen.java
Normal file
@@ -0,0 +1,143 @@
|
||||
package com.drmangotea.tfmg.base;
|
||||
|
||||
import com.drmangotea.tfmg.TFMG;
|
||||
import com.simibubi.create.AllTags.AllBlockTags;
|
||||
import com.simibubi.create.foundation.data.TagGen;
|
||||
import com.tterrag.registrate.providers.DataGenContext;
|
||||
import com.tterrag.registrate.providers.RegistrateBlockstateProvider;
|
||||
import com.tterrag.registrate.util.DataIngredient;
|
||||
import com.tterrag.registrate.util.entry.BlockEntry;
|
||||
import com.tterrag.registrate.util.nullness.NonNullBiConsumer;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.data.recipes.RecipeCategory;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.IronBarsBlock;
|
||||
import net.minecraft.world.level.block.SoundType;
|
||||
import net.minecraft.world.level.material.MapColor;
|
||||
import net.minecraftforge.client.model.generators.ModelFile;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import static net.minecraft.world.level.block.state.properties.BlockStateProperties.*;
|
||||
|
||||
public class TFMGMetalBarsGen {
|
||||
|
||||
public static <P extends IronBarsBlock> NonNullBiConsumer<DataGenContext<Block, P>, RegistrateBlockstateProvider> barsBlockState(
|
||||
String name, boolean specialEdge) {
|
||||
return (c, p) -> {
|
||||
ModelFile post_ends = barsSubModel(p, name, "post_ends", specialEdge);
|
||||
ModelFile post = barsSubModel(p, name, "post", specialEdge);
|
||||
ModelFile cap = barsSubModel(p, name, "cap", specialEdge);
|
||||
ModelFile cap_alt = barsSubModel(p, name, "cap_alt", specialEdge);
|
||||
ModelFile side = barsSubModel(p, name, "side", specialEdge);
|
||||
ModelFile side_alt = barsSubModel(p, name, "side_alt", specialEdge);
|
||||
|
||||
p.getMultipartBuilder(c.get())
|
||||
.part()
|
||||
.modelFile(post_ends)
|
||||
.addModel()
|
||||
.end()
|
||||
.part()
|
||||
.modelFile(post)
|
||||
.addModel()
|
||||
.condition(NORTH, false)
|
||||
.condition(EAST, false)
|
||||
.condition(SOUTH, false)
|
||||
.condition(WEST, false)
|
||||
.end()
|
||||
.part()
|
||||
.modelFile(cap)
|
||||
.addModel()
|
||||
.condition(NORTH, true)
|
||||
.condition(EAST, false)
|
||||
.condition(SOUTH, false)
|
||||
.condition(WEST, false)
|
||||
.end()
|
||||
.part()
|
||||
.modelFile(cap)
|
||||
.rotationY(90)
|
||||
.addModel()
|
||||
.condition(NORTH, false)
|
||||
.condition(EAST, true)
|
||||
.condition(SOUTH, false)
|
||||
.condition(WEST, false)
|
||||
.end()
|
||||
.part()
|
||||
.modelFile(cap_alt)
|
||||
.addModel()
|
||||
.condition(NORTH, false)
|
||||
.condition(EAST, false)
|
||||
.condition(SOUTH, true)
|
||||
.condition(WEST, false)
|
||||
.end()
|
||||
.part()
|
||||
.modelFile(cap_alt)
|
||||
.rotationY(90)
|
||||
.addModel()
|
||||
.condition(NORTH, false)
|
||||
.condition(EAST, false)
|
||||
.condition(SOUTH, false)
|
||||
.condition(WEST, true)
|
||||
.end()
|
||||
.part()
|
||||
.modelFile(side)
|
||||
.addModel()
|
||||
.condition(NORTH, true)
|
||||
.end()
|
||||
.part()
|
||||
.modelFile(side)
|
||||
.rotationY(90)
|
||||
.addModel()
|
||||
.condition(EAST, true)
|
||||
.end()
|
||||
.part()
|
||||
.modelFile(side_alt)
|
||||
.addModel()
|
||||
.condition(SOUTH, true)
|
||||
.end()
|
||||
.part()
|
||||
.modelFile(side_alt)
|
||||
.rotationY(90)
|
||||
.addModel()
|
||||
.condition(WEST, true)
|
||||
.end();
|
||||
};
|
||||
}
|
||||
|
||||
private static ModelFile barsSubModel(RegistrateBlockstateProvider p, String name, String suffix,
|
||||
boolean specialEdge) {
|
||||
ResourceLocation barsTexture = p.modLoc("block/bars/" + name + "_bars");
|
||||
ResourceLocation edgeTexture = specialEdge ? p.modLoc("block/bars/" + name + "_bars_edge") : barsTexture;
|
||||
return p.models()
|
||||
.withExistingParent(name + "_" + suffix, p.modLoc("block/bars/" + suffix))
|
||||
.texture("bars", barsTexture)
|
||||
.texture("particle", barsTexture)
|
||||
.texture("edge", edgeTexture);
|
||||
}
|
||||
@SuppressWarnings("removal")
|
||||
public static BlockEntry<IronBarsBlock> createBars(String name, boolean specialEdge,
|
||||
Supplier<DataIngredient> ingredient, MapColor color) {
|
||||
return TFMG.REGISTRATE.block(name + "_bars", IronBarsBlock::new)
|
||||
.addLayer(() -> RenderType::cutoutMipped)
|
||||
.initialProperties(() -> Blocks.IRON_BARS)
|
||||
.properties(p -> p.sound(SoundType.COPPER)
|
||||
.mapColor(color))
|
||||
.tag(AllBlockTags.WRENCH_PICKUP.tag)
|
||||
.tag(AllBlockTags.FAN_TRANSPARENT.tag)
|
||||
.transform(TagGen.pickaxeOnly())
|
||||
.blockstate(barsBlockState(name, specialEdge))
|
||||
.item()
|
||||
.model((c, p) -> {
|
||||
ResourceLocation barsTexture = p.modLoc("block/bars/" + name + "_bars");
|
||||
p.withExistingParent(c.getName(), TFMG.asResource("item/bars"))
|
||||
.texture("bars", barsTexture)
|
||||
.texture("edge", specialEdge ? p.modLoc("block/bars/" + name + "_bars_edge") : barsTexture);
|
||||
})
|
||||
.recipe((c, p) -> p.stonecutting(ingredient.get(), RecipeCategory.DECORATIONS, c::get, 4))
|
||||
.build()
|
||||
.register();
|
||||
}
|
||||
|
||||
}
|
||||
52
src/main/java/com/drmangotea/tfmg/base/TFMGRegistrate.java
Normal file
52
src/main/java/com/drmangotea/tfmg/base/TFMGRegistrate.java
Normal file
@@ -0,0 +1,52 @@
|
||||
package com.drmangotea.tfmg.base;
|
||||
|
||||
import com.drmangotea.tfmg.TFMG;
|
||||
import com.drmangotea.tfmg.registry.TFMGBlocks;
|
||||
import com.simibubi.create.foundation.data.CreateRegistrate;
|
||||
import com.tterrag.registrate.util.DataIngredient;
|
||||
import com.tterrag.registrate.util.entry.BlockEntry;
|
||||
import net.minecraft.data.recipes.RecipeCategory;
|
||||
import net.minecraft.tags.BlockTags;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.level.block.*;
|
||||
import net.minecraft.world.level.block.state.BlockBehaviour;
|
||||
import net.minecraftforge.registries.ForgeRegistries;
|
||||
|
||||
import static com.simibubi.create.foundation.data.BlockStateGen.simpleCubeAll;
|
||||
import static com.simibubi.create.foundation.data.ModelGen.customItemModel;
|
||||
import static com.simibubi.create.foundation.data.TagGen.pickaxeOnly;
|
||||
|
||||
public class TFMGRegistrate extends CreateRegistrate {
|
||||
public static String autoLang(String id) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
boolean b = true;
|
||||
for (char c: id.toCharArray()) {
|
||||
if(c == '_') {
|
||||
builder.append(' ');
|
||||
b = true;
|
||||
} else {
|
||||
builder.append(b ? String.valueOf(c).toUpperCase() : c);
|
||||
b = false;
|
||||
}
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
protected TFMGRegistrate() {
|
||||
super(TFMG.MOD_ID);
|
||||
}
|
||||
|
||||
public static TFMGRegistrate create() {
|
||||
return new TFMGRegistrate();
|
||||
}
|
||||
|
||||
public static Block getBlock(String name) {
|
||||
return TFMG.REGISTRATE.get(name, ForgeRegistries.BLOCKS.getRegistryKey()).get();
|
||||
}
|
||||
public static Item getItem(String name) {
|
||||
return TFMG.REGISTRATE.get(name, ForgeRegistries.ITEMS.getRegistryKey()).get();
|
||||
}
|
||||
public static Item getBucket(String name) {
|
||||
return TFMG.REGISTRATE.get(name+"_bucket", ForgeRegistries.ITEMS.getRegistryKey()).get();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package com.drmangotea.tfmg.base;
|
||||
|
||||
import com.drmangotea.tfmg.TFMG;
|
||||
import com.drmangotea.tfmg.registry.TFMGTags;
|
||||
import com.simibubi.create.AllItems;
|
||||
import com.simibubi.create.AllTags;
|
||||
import com.simibubi.create.foundation.data.TagGen;
|
||||
import com.simibubi.create.foundation.data.recipe.Mods;
|
||||
import com.tterrag.registrate.providers.ProviderType;
|
||||
import com.tterrag.registrate.providers.RegistrateTagsProvider;
|
||||
import net.minecraft.tags.BlockTags;
|
||||
import net.minecraft.tags.ItemTags;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.Items;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraftforge.common.Tags;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class TFMGRegistrateTags {
|
||||
public static void addGenerators() {
|
||||
TFMG.REGISTRATE.addDataGenerator(ProviderType.BLOCK_TAGS, TFMGRegistrateTags::genBlockTags);
|
||||
TFMG.REGISTRATE.addDataGenerator(ProviderType.ITEM_TAGS, TFMGRegistrateTags::genItemTags);
|
||||
// TFMG.REGISTRATE.addDataGenerator(ProviderType.FLUID_TAGS, TFMGRegistrateTags::genFluidTags);
|
||||
// TFMG.REGISTRATE.addDataGenerator(ProviderType.ENTITY_TAGS, TFMGRegistrateTags::genEntityTags);
|
||||
}
|
||||
private static void genItemTags(RegistrateTagsProvider<Item> provIn) {
|
||||
TagGen.CreateTagsProvider<Item> prov = new TagGen.CreateTagsProvider<>(provIn, Item::builtInRegistryHolder);
|
||||
|
||||
prov.tag(TFMGTags.TFMGItemTags.RODS.tag)
|
||||
.add(Items.STICK);
|
||||
|
||||
for (TFMGTags.TFMGItemTags tag : TFMGTags.TFMGItemTags.values()) {
|
||||
if (tag.alwaysDatagen) {
|
||||
prov.getOrCreateRawBuilder(tag.tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
private static void genBlockTags(RegistrateTagsProvider<Block> provIn) {
|
||||
TagGen.CreateTagsProvider<Block> prov = new TagGen.CreateTagsProvider<>(provIn, Block::builtInRegistryHolder);
|
||||
|
||||
|
||||
prov.tag(TFMGTags.TFMGBlockTags.PUMPJACK_HEAD.tag)
|
||||
.add(Blocks.IRON_BLOCK);
|
||||
prov.tag(TFMGTags.TFMGBlockTags.PUMPJACK_PART.tag)
|
||||
.addTag(TFMGTags.TFMGBlockTags.PUMPJACK_SMALL_PART.tag);
|
||||
|
||||
for (TFMGTags.TFMGBlockTags tag : TFMGTags.TFMGBlockTags.values()) {
|
||||
if (tag.alwaysDatagen) {
|
||||
prov.getOrCreateRawBuilder(tag.tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
174
src/main/java/com/drmangotea/tfmg/base/TFMGShapes.java
Normal file
174
src/main/java/com/drmangotea/tfmg/base/TFMGShapes.java
Normal file
@@ -0,0 +1,174 @@
|
||||
package com.drmangotea.tfmg.base;
|
||||
|
||||
|
||||
import com.simibubi.create.foundation.utility.VoxelShaper;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.core.Direction.Axis;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.phys.shapes.BooleanOp;
|
||||
import net.minecraft.world.phys.shapes.Shapes;
|
||||
import net.minecraft.world.phys.shapes.VoxelShape;
|
||||
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
import static net.minecraft.core.Direction.*;
|
||||
|
||||
public class TFMGShapes {
|
||||
public static final VoxelShaper
|
||||
ENGINE_BACK = shape(3, 0, 3, 13, 16, 16)
|
||||
.forDirectional(),
|
||||
ENGINE_BACK_VERTICAL = shape(3, 0, 3, 16, 16, 13)
|
||||
.forDirectional(),
|
||||
ENGINE_VERTICAL = shape(3, 0, 3, 13, 14, 16)
|
||||
.forDirectional(),
|
||||
ENGINE = shape(3, 0, 3, 13, 14, 16)
|
||||
.forDirectional(),
|
||||
PUMPJACK_HAMMER_PART = shape(0, 2, 0, 16, 14, 16)
|
||||
.forDirectional(),
|
||||
RADIAL_ENGINE = shape(1, 4, 1, 15, 12, 15)
|
||||
.forDirectional(),
|
||||
LARGE_RADIAL_ENGINE = shape(-3, 4, -3, 19, 12, 19)
|
||||
.forDirectional(),
|
||||
PUMPJACK_HEAD = shape(1, 0, -4, 15, 14, 24)
|
||||
.forDirectional(),
|
||||
COMPACT_ENGINE_VERTICAL = shape(3, 0, 3, 13, 14, 14)
|
||||
.forDirectional(),
|
||||
COMPACT_ENGINE = shape(3, 0, 3, 13, 14, 14)
|
||||
.forDirectional(),
|
||||
CABLE_CONNECTOR = shape(6, 0, 6, 10, 9, 10)
|
||||
.forDirectional(),
|
||||
CABLE_CONNECTOR_MIDDLE = shape(6, 0, 6, 10, 16, 10)
|
||||
.forDirectional(),
|
||||
GALVANIC_CELL = shape(5, 10, 5, 11, 16, 16).add(1, 4, 6, 15, 10, 16)
|
||||
.forDirectional(),
|
||||
GENERATOR = shape(3, 0, 3, 13, 14, 13).add(0, 4, 0, 16, 10, 16)
|
||||
.forDirectional(),
|
||||
LIGHT_BULB = shape(5, 0, 5, 11, 9, 11)
|
||||
.forDirectional(),
|
||||
MODERN_LIGHT = shape(0, 0, 0, 16, 3, 16)
|
||||
.forDirectional(),
|
||||
CIRCULAR_LIGHT = shape(3, 0, 3, 13, 10, 13)
|
||||
.forDirectional(),
|
||||
ALUMINUM_LAMP = shape(3, 0, 3, 13, 2, 13).add(4, 2, 4, 12, 3, 12)
|
||||
.forDirectional(),
|
||||
RESISTOR = shape(3, 0, 3, 13, 16, 13).add(1, 1, 13, 15, 15, 16)
|
||||
.forDirectional(),
|
||||
RESISTOR_VERTICAL = shape(3, 0, 3, 13, 16, 13)
|
||||
.forDirectional(),
|
||||
BLAST_FURNACE_REINFORCEMENT_WALL = shape(00, 0, 0, 16, 6, 16)
|
||||
.forDirectional(),
|
||||
|
||||
ROTOR = shape(3, 3, 2, 13, 13, 14)
|
||||
.forAxis(),
|
||||
VOLTMETER = shape(0, 0, 2, 16, 3, 14)
|
||||
.forDirectional(),
|
||||
DIAGONAL_CABLE_BLOCK_DOWN = shape(3, 3, 11, 13, 13, 16)
|
||||
.add(3, 11, 3, 13, 16, 13)
|
||||
.add(4, 4, 5, 12, 11, 12)
|
||||
.forDirectional(),
|
||||
DIAGONAL_CABLE_BLOCK_UP = shape(3, 3, 0, 13, 13, 5)
|
||||
.add(3, 11, 3, 13, 16, 13)
|
||||
.add(4, 4, 5, 12, 11, 12)
|
||||
.forDirectional(),
|
||||
CABLE_TUBE = shape(6, 0, 6, 10, 16, 10)
|
||||
.forDirectional(),
|
||||
REBAR_PILLAR = shape(3, 0, 3, 13, 16, 13)
|
||||
.forDirectional(),
|
||||
ELECTRICAL_SWITCH = shape(5, 0, 3, 11, 3, 13)
|
||||
.forHorizontalAxis(),
|
||||
ELECTRICAL_SWITCH_CEILING = shape(5, 13, 3, 11, 16, 13)
|
||||
.forHorizontalAxis(),
|
||||
ELECTRICAL_SWITCH_WALL = shape(5, 3, 0, 11, 13, 3)
|
||||
.forHorizontal(SOUTH),
|
||||
POLARIZER = shape(4, 8, 0, 12, 12, 2)
|
||||
.add(5, 8, 14, 11, 11, 16)
|
||||
.add(11, 8, 4, 15, 12, 11)
|
||||
.add(1, 8, 4, 5, 12, 11)
|
||||
.add(0, 0, 0, 16, 8, 16)
|
||||
.forHorizontal(NORTH)
|
||||
;
|
||||
public static final VoxelShape
|
||||
|
||||
EMPTY = shape(0, 0, 0, 0, 0, 0).build(),
|
||||
PUMPJACK_CRANK = shape(0, 0, 0, 16, 8, 16).build(),
|
||||
INDUSTRIAL_PIPE = shape(4, 0, 4, 12, 16, 12).build(),
|
||||
FLARESTACK = shape(3, 0, 3, 13, 14, 14).build(),
|
||||
PUMPJACK_BASE = shape(3, 0, 3, 13, 16, 13).build(),
|
||||
TRAFFIC_LIGHT = shape(3, 0, 3, 13, 16, 13).build(),
|
||||
CASTING_SPOUT = shape(1, 2, 1, 15, 14, 15)
|
||||
.build(),
|
||||
REBAR_FLOOR = shape(0, 4, 0, 16, 12, 16)
|
||||
.build(),
|
||||
SURFACE_SCANNER = shape(2, 0, 2, 14, 14, 14).build(),
|
||||
FULL = shape(0, 0, 0, 16, 16, 16).build(),
|
||||
ELECTRIC_POST = shape(4, 0, 4, 12, 16, 12).build(),
|
||||
SLAB = shape(0, 0, 0, 16, 8, 16).build();
|
||||
;
|
||||
|
||||
private static Builder shape(VoxelShape shape) {
|
||||
return new Builder(shape);
|
||||
}
|
||||
|
||||
private static Builder shape(double x1, double y1, double z1, double x2, double y2, double z2) {
|
||||
return shape(cuboid(x1, y1, z1, x2, y2, z2));
|
||||
}
|
||||
|
||||
private static VoxelShape cuboid(double x1, double y1, double z1, double x2, double y2, double z2) {
|
||||
return Block.box(x1, y1, z1, x2, y2, z2);
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
private VoxelShape shape;
|
||||
|
||||
public Builder(VoxelShape shape) {
|
||||
this.shape = shape;
|
||||
}
|
||||
|
||||
public Builder add(VoxelShape shape) {
|
||||
this.shape = Shapes.or(this.shape, shape);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder add(double x1, double y1, double z1, double x2, double y2, double z2) {
|
||||
return add(cuboid(x1, y1, z1, x2, y2, z2));
|
||||
}
|
||||
|
||||
public Builder erase(double x1, double y1, double z1, double x2, double y2, double z2) {
|
||||
this.shape = Shapes.join(shape, cuboid(x1, y1, z1, x2, y2, z2), BooleanOp.ONLY_FIRST);
|
||||
return this;
|
||||
}
|
||||
|
||||
public VoxelShape build() {
|
||||
return shape;
|
||||
}
|
||||
|
||||
public VoxelShaper build(BiFunction<VoxelShape, Direction, VoxelShaper> factory, Direction direction) {
|
||||
return factory.apply(shape, direction);
|
||||
}
|
||||
|
||||
public VoxelShaper build(BiFunction<VoxelShape, Axis, VoxelShaper> factory, Axis axis) {
|
||||
return factory.apply(shape, axis);
|
||||
}
|
||||
public VoxelShaper forDirectional(Direction direction) {
|
||||
return build(VoxelShaper::forDirectional, direction);
|
||||
}
|
||||
|
||||
public VoxelShaper forAxis() {
|
||||
return build(VoxelShaper::forAxis, Axis.Y);
|
||||
}
|
||||
|
||||
public VoxelShaper forHorizontalAxis() {
|
||||
return build(VoxelShaper::forHorizontalAxis, Axis.Z);
|
||||
}
|
||||
|
||||
public VoxelShaper forHorizontal(Direction direction) {
|
||||
return build(VoxelShaper::forHorizontal, direction);
|
||||
}
|
||||
|
||||
public VoxelShaper forDirectional() {
|
||||
return forDirectional(UP);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.drmangotea.tfmg.base;
|
||||
|
||||
|
||||
|
||||
public class TFMGSharedProperties {}
|
||||
63
src/main/java/com/drmangotea/tfmg/base/TFMGSpriteShifts.java
Normal file
63
src/main/java/com/drmangotea/tfmg/base/TFMGSpriteShifts.java
Normal file
@@ -0,0 +1,63 @@
|
||||
package com.drmangotea.tfmg.base;
|
||||
|
||||
import com.drmangotea.tfmg.TFMG;
|
||||
import com.simibubi.create.Create;
|
||||
import com.simibubi.create.foundation.block.connected.AllCTTypes;
|
||||
import com.simibubi.create.foundation.block.connected.CTSpriteShiftEntry;
|
||||
import com.simibubi.create.foundation.block.connected.CTSpriteShifter;
|
||||
import com.simibubi.create.foundation.block.connected.CTType;
|
||||
import com.simibubi.create.foundation.block.render.SpriteShiftEntry;
|
||||
import com.simibubi.create.foundation.block.render.SpriteShifter;
|
||||
|
||||
public class TFMGSpriteShifts {
|
||||
|
||||
public static final CTSpriteShiftEntry CAST_IRON_BLOCK = omni("cast_iron_block"), LEAD_BLOCK = omni("lead_block"), STEEL_BLOCK = omni("steel_block");
|
||||
public static final CTSpriteShiftEntry STEEL_FLUID_TANK = getCT(AllCTTypes.RECTANGLE, "steel_fluid_tank"), STEEL_FLUID_TANK_TOP = getCT(AllCTTypes.RECTANGLE, "steel_fluid_tank_top"), STEEL_FLUID_TANK_INNER = getCT(AllCTTypes.RECTANGLE, "steel_fluid_tank_inner");
|
||||
public static final CTSpriteShiftEntry HEAVY_MACHINERY_CASING = omni("heavy_machinery_casing"), ELECTRIC_CASING = omni("electric_casing"), STEEL_CASING = omni("steel_casing"), INDUSTRIAL_ALUMINUM_CASING = omni("industrial_aluminum_casing");
|
||||
public static final CTSpriteShiftEntry CAPACITOR = getCT(AllCTTypes.RECTANGLE, "capacitor_side"), ACCUMULATOR = getCT(AllCTTypes.RECTANGLE, "accumulator_side");
|
||||
public static final CTSpriteShiftEntry STEEL_SCAFFOLD = horizontal("scaffold/steel_scaffold"), ALUMINUM_SCAFFOLD = horizontal("scaffold/aluminum_scaffold");
|
||||
public static final CTSpriteShiftEntry ALUMINUM_SCAFFOLD_TOP = omni("aluminum_casing");
|
||||
public static final CTSpriteShiftEntry STEEL_SCAFFOLD_INSIDE = horizontal("scaffold/steel_scaffold_inside"), ALUMINUM_SCAFFOLD_INSIDE = horizontal("scaffold/aluminum_scaffold_inside");
|
||||
public static final CTSpriteShiftEntry STEEL_ENCASED_COGWHEEL_SIDE = vertical("steel_encased_cogwheel_side"), STEEL_ENCASED_COGWHEEL_OTHERSIDE = horizontal("steel_encased_cogwheel_side"), HEAVY_CASING_ENCASED_COGWHEEL_SIDE = vertical("heavy_machinery_encased_cogwheel_side"), HEAVY_CASING_ENCASED_COGWHEEL_OTHERSIDE = horizontal("heavy_machinery_encased_cogwheel_side");
|
||||
public static final CTSpriteShiftEntry COKE_OVEN_TOP = getCT(AllCTTypes.RECTANGLE, "coke_oven/top"), COKE_OVEN_BOTTOM = getCT(AllCTTypes.RECTANGLE, "coke_oven/bottom"), COKE_OVEN_BACK = getCT(AllCTTypes.RECTANGLE, "coke_oven/side"), COKE_OVEN_SIDE = getCT(AllCTTypes.RECTANGLE, "coke_oven/side");
|
||||
|
||||
public static final CTSpriteShiftEntry BLAST_FURNACE_REINFORCEMENT = vertical("blast_furnace_reinforcement");
|
||||
public static final CTSpriteShiftEntry RUSTED_BLAST_FURNACE_REINFORCEMENT = vertical("rusted_blast_furnace_reinforcement");
|
||||
public static final CTSpriteShiftEntry SEGMENTED_DISPLAY_SCREEN = horizontal("segmented_display_screen");
|
||||
|
||||
public static final CTSpriteShiftEntry BLAST_STOVE_SIDE = getCT(AllCTTypes.RECTANGLE, "blast_stove_side"), BLAST_STOVE_TOP = getCT(AllCTTypes.RECTANGLE, "blast_stove_top");
|
||||
public static final CTSpriteShiftEntry
|
||||
REGULAR_ENGINE_TOP = vertical("engines/engine_top"),
|
||||
REGULAR_ENGINE_BOTTOM = vertical("engines/engine_bottom"),
|
||||
REGULAR_ENGINE_SIDE = horizontal("engines/engine_side");
|
||||
public static final SpriteShiftEntry WINDING_MACHINE_COPPER_WIRE = get("block/winding_machine_copper_wire", "block/winding_machine_copper_wire_scroll");
|
||||
|
||||
|
||||
///////////////////////
|
||||
public static CTSpriteShiftEntry omni(String name) {
|
||||
return getCT(AllCTTypes.OMNIDIRECTIONAL, name);
|
||||
}
|
||||
|
||||
public static CTSpriteShiftEntry horizontal(String name) {
|
||||
return getCT(AllCTTypes.HORIZONTAL_KRYPPERS, name);
|
||||
}
|
||||
|
||||
private static CTSpriteShiftEntry vertical(String name) {
|
||||
return getCT(AllCTTypes.VERTICAL, name);
|
||||
}
|
||||
|
||||
/////
|
||||
|
||||
private static CTSpriteShiftEntry getCT(CTType type, String blockTextureName, String connectedTextureName) {
|
||||
return CTSpriteShifter.getCT(type, TFMG.asResource("block/" + blockTextureName), TFMG.asResource("block/" + connectedTextureName + "_connected"));
|
||||
}
|
||||
|
||||
private static CTSpriteShiftEntry getCT(CTType type, String blockTextureName) {
|
||||
return getCT(type, blockTextureName, blockTextureName);
|
||||
}
|
||||
|
||||
private static SpriteShiftEntry get(String originalLocation, String targetLocation) {
|
||||
return SpriteShifter.get(TFMG.asResource(originalLocation), TFMG.asResource(targetLocation));
|
||||
}
|
||||
|
||||
}
|
||||
62
src/main/java/com/drmangotea/tfmg/base/TFMGTiers.java
Normal file
62
src/main/java/com/drmangotea/tfmg/base/TFMGTiers.java
Normal file
@@ -0,0 +1,62 @@
|
||||
package com.drmangotea.tfmg.base;
|
||||
|
||||
import com.drmangotea.tfmg.registry.TFMGItems;
|
||||
import net.minecraft.util.LazyLoadedValue;
|
||||
import net.minecraft.world.item.Tier;
|
||||
import net.minecraft.world.item.crafting.Ingredient;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public enum TFMGTiers implements Tier {
|
||||
|
||||
|
||||
STEEL(3, 1000, 7.5f, 3f, 12, () -> {
|
||||
return Ingredient.of(TFMGItems.STEEL_INGOT.get());
|
||||
}),
|
||||
|
||||
ALUMINUM(2, 220, 6, 2f, 22, () -> {
|
||||
return Ingredient.of(TFMGItems.ALUMINUM_INGOT.get());
|
||||
}),
|
||||
LEAD(1, 32, 2, 0.5f, 5, () -> {
|
||||
return Ingredient.of(TFMGItems.LEAD_INGOT.get());
|
||||
});
|
||||
private final int level;
|
||||
private final int uses;
|
||||
private final float speed;
|
||||
private final float damage;
|
||||
private final int enchantmentValue;
|
||||
private final LazyLoadedValue<Ingredient> repairIngredient;
|
||||
|
||||
private TFMGTiers(int pLevel, int pUses, float pSpeed, float pDamage, int pEnchantmentValue, Supplier<Ingredient> pRepairIngredient) {
|
||||
this.level = pLevel;
|
||||
this.uses = pUses;
|
||||
this.speed = pSpeed;
|
||||
this.damage = pDamage;
|
||||
this.enchantmentValue = pEnchantmentValue;
|
||||
this.repairIngredient = new LazyLoadedValue<>(pRepairIngredient);
|
||||
}
|
||||
|
||||
public int getUses() {
|
||||
return this.uses;
|
||||
}
|
||||
|
||||
public float getSpeed() {
|
||||
return this.speed;
|
||||
}
|
||||
|
||||
public float getAttackDamageBonus() {
|
||||
return this.damage;
|
||||
}
|
||||
|
||||
public int getLevel() {
|
||||
return this.level;
|
||||
}
|
||||
|
||||
public int getEnchantmentValue() {
|
||||
return this.enchantmentValue;
|
||||
}
|
||||
|
||||
public Ingredient getRepairIngredient() {
|
||||
return this.repairIngredient.get();
|
||||
}
|
||||
}
|
||||
257
src/main/java/com/drmangotea/tfmg/base/TFMGUtils.java
Normal file
257
src/main/java/com/drmangotea/tfmg/base/TFMGUtils.java
Normal file
@@ -0,0 +1,257 @@
|
||||
package com.drmangotea.tfmg.base;
|
||||
|
||||
|
||||
import com.drmangotea.tfmg.base.spark.ElectricSparkParticle;
|
||||
import com.drmangotea.tfmg.base.spark.Spark;
|
||||
import com.drmangotea.tfmg.registry.TFMGEntityTypes;
|
||||
import com.simibubi.create.Create;
|
||||
import com.simibubi.create.content.fluids.tank.FluidTankBlockEntity;
|
||||
import com.simibubi.create.foundation.fluid.SmartFluidTank;
|
||||
import com.simibubi.create.foundation.utility.Lang;
|
||||
import com.simibubi.create.foundation.utility.LangBuilder;
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.material.Fluid;
|
||||
import net.minecraft.world.phys.AABB;
|
||||
import net.minecraftforge.common.capabilities.ForgeCapabilities;
|
||||
import net.minecraftforge.common.util.LazyOptional;
|
||||
import net.minecraftforge.fluids.FluidStack;
|
||||
import net.minecraftforge.fluids.capability.IFluidHandler;
|
||||
import net.minecraftforge.items.IItemHandler;
|
||||
import net.minecraftforge.items.IItemHandlerModifiable;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class TFMGUtils {
|
||||
|
||||
|
||||
public static void createFireExplosion(Level level, Entity entity, BlockPos pos, int sparkAmount, float radius) {
|
||||
|
||||
if (level.isClientSide && entity != null) level.broadcastEntityEvent(entity, (byte) 3);
|
||||
|
||||
for (int i = 0; i < sparkAmount; i++) {
|
||||
float x = Create.RANDOM.nextFloat(360);
|
||||
float y = Create.RANDOM.nextFloat(360);
|
||||
float z = Create.RANDOM.nextFloat(360);
|
||||
Spark spark = TFMGEntityTypes.SPARK.create(level);
|
||||
spark.moveTo(pos.getX(), pos.getY() + 1, pos.getZ());
|
||||
|
||||
float f = -Mth.sin(y * ((float) Math.PI / 180F)) * Mth.cos(x * ((float) Math.PI / 180F));
|
||||
float f1 = -Mth.sin((x + z) * ((float) Math.PI / 180F));
|
||||
float f2 = Mth.cos(y * ((float) Math.PI / 180F)) * Mth.cos(x * ((float) Math.PI / 180F));
|
||||
spark.shoot(f, f1, f2, 0.3f, 1);
|
||||
level.addFreshEntity(spark);
|
||||
}
|
||||
level.explode(null, pos.getX(), pos.getY(), pos.getZ(), radius, Level.ExplosionInteraction.BLOCK);
|
||||
}
|
||||
public static void blowUpTank(FluidTankBlockEntity tank, int power) {
|
||||
|
||||
if (tank == null || tank.getControllerBE() == null) return;
|
||||
FluidTankBlockEntity be = tank.getControllerBE();
|
||||
|
||||
for (int xOffset = 0; xOffset < be.getWidth(); xOffset++) {
|
||||
for (int zOffset = 0; zOffset < be.getWidth(); zOffset++) {
|
||||
for (int yOffset = 0; yOffset < be.getHeight(); yOffset++) {
|
||||
|
||||
BlockPos pos = be.getBlockPos().offset(xOffset, yOffset, zOffset);
|
||||
|
||||
be.getLevel().destroyBlock(pos, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
createFireExplosion(be.getLevel(), null, new BlockPos(be.getBlockPos().getX() + (be.getWidth() / 2), be.getBlockPos().getY() + (be.getHeight() / 2), be.getBlockPos().getZ() + (be.getWidth() / 2)), power * 15, (float) power);
|
||||
}
|
||||
|
||||
public static String fromId(String key) {
|
||||
String s = key.replaceAll("_", " ");
|
||||
s = Arrays.stream(StringUtils.splitByCharacterTypeCamelCase(s)).map(StringUtils::capitalize).collect(Collectors.joining(" "));
|
||||
s = StringUtils.normalizeSpace(s);
|
||||
return s;
|
||||
}
|
||||
|
||||
public static String toHumanReadable(String key) {
|
||||
String s = key.replaceAll("_", " ");
|
||||
s = Arrays.stream(StringUtils.splitByCharacterTypeCamelCase(s)).map(StringUtils::capitalize).collect(Collectors.joining(" "));
|
||||
s = StringUtils.normalizeSpace(s);
|
||||
return s;
|
||||
}
|
||||
|
||||
public static void spawnElectricParticles(Level level, BlockPos pos) {
|
||||
if (level == null) return;
|
||||
|
||||
|
||||
RandomSource r = level.getRandom();
|
||||
|
||||
|
||||
for (int i = 0; i < r.nextInt(40); i++) {
|
||||
float x = Create.RANDOM.nextFloat(2) - 1;
|
||||
float y = Create.RANDOM.nextFloat(2) - 1;
|
||||
float z = Create.RANDOM.nextFloat(2) - 1;
|
||||
|
||||
level.addParticle(new ElectricSparkParticle.Data(), pos.getX() + 0.5f + x, pos.getY() + 0.5f + y, pos.getZ() + 0.5f + z, x, y, z);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
public static float getDistance(BlockPos pos1, BlockPos pos2, boolean _2D) {
|
||||
|
||||
|
||||
float x = Math.abs(pos1.getX() - pos2.getX());
|
||||
float y = Math.abs(pos1.getY() - pos2.getY());
|
||||
float z = Math.abs(pos1.getZ() - pos2.getZ());
|
||||
|
||||
|
||||
float distance2D = (float) Math.sqrt(x * x + z * z);
|
||||
|
||||
if (_2D) return distance2D;
|
||||
|
||||
|
||||
return (float) Math.sqrt(distance2D * distance2D + y * y);
|
||||
}
|
||||
|
||||
public static void createStorageTooltip(BlockEntity be, List<Component> tooltip) {
|
||||
createFluidTooltip(be, tooltip);
|
||||
createItemTooltip(be, tooltip);
|
||||
}
|
||||
public static boolean createFluidTooltip(BlockEntity be, List<Component> tooltip) {
|
||||
LangBuilder mb = Lang.translate("generic.unit.millibuckets");
|
||||
|
||||
/////////
|
||||
LazyOptional<IFluidHandler> handler = be.getCapability(ForgeCapabilities.FLUID_HANDLER);
|
||||
Optional<IFluidHandler> resolve = handler.resolve();
|
||||
if (!resolve.isPresent()) return false;
|
||||
|
||||
IFluidHandler tank = resolve.get();
|
||||
if (tank.getTanks() == 0) return false;
|
||||
|
||||
Lang.translate("goggles.fluid_storage").style(ChatFormatting.GRAY).forGoggles(tooltip);
|
||||
|
||||
|
||||
boolean isEmpty = true;
|
||||
for (int i = 0; i < tank.getTanks(); i++) {
|
||||
FluidStack fluidStack = tank.getFluidInTank(i);
|
||||
if (fluidStack.isEmpty()) continue;
|
||||
Lang.fluidName(fluidStack).style(ChatFormatting.GRAY).forGoggles(tooltip, 1);
|
||||
Lang.builder().add(Lang.number(fluidStack.getAmount()).add(mb).style(ChatFormatting.DARK_GREEN)).text(ChatFormatting.GRAY, " / ").add(Lang.number(tank.getTankCapacity(i)).add(mb).style(ChatFormatting.DARK_GRAY)).forGoggles(tooltip, 1);
|
||||
isEmpty = false;
|
||||
}
|
||||
if (tank.getTanks() > 1) {
|
||||
if (isEmpty) tooltip.remove(tooltip.size() - 1);
|
||||
return true;
|
||||
}
|
||||
if (!isEmpty) return true;
|
||||
|
||||
Lang.translate("gui.goggles.fluid_container.capacity").add(Lang.number(tank.getTankCapacity(0)).add(mb).style(ChatFormatting.DARK_GREEN)).style(ChatFormatting.DARK_GRAY).forGoggles(tooltip, 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public static boolean createItemTooltip(BlockEntity be, List<Component> tooltip) {
|
||||
|
||||
@NotNull LazyOptional<IItemHandler> handler = be.getCapability(ForgeCapabilities.ITEM_HANDLER);
|
||||
Optional<IItemHandler> resolve = handler.resolve();
|
||||
if (!resolve.isPresent()) return false;
|
||||
IItemHandlerModifiable inventory = (IItemHandlerModifiable) resolve.get();
|
||||
if (inventory.getSlots() == 0) return false;
|
||||
Lang.translate("goggles.item_storage").style(ChatFormatting.GRAY).forGoggles(tooltip);
|
||||
boolean isEmpty = true;
|
||||
for (int i = 0; i < inventory.getSlots(); i++) {
|
||||
ItemStack itemStack = inventory.getStackInSlot(i);
|
||||
|
||||
if (itemStack.isEmpty()) continue;
|
||||
Lang.itemName(itemStack).style(ChatFormatting.DARK_GREEN).add(Component.literal(" x " + itemStack.getCount())).style(ChatFormatting.DARK_GREEN).forGoggles(tooltip, 1);
|
||||
isEmpty = false;
|
||||
}
|
||||
if (inventory.getSlots() > 1) {
|
||||
if (isEmpty) tooltip.remove(tooltip.size() - 1);
|
||||
return true;
|
||||
}
|
||||
if (!isEmpty) return true;
|
||||
|
||||
Lang.translate("gui.goggles.item_storage_empty").style(ChatFormatting.DARK_GRAY).forGoggles(tooltip, 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
public static String formatUnits(double n, String unit) {
|
||||
if(n == 0)
|
||||
return Math.round(n) + unit;
|
||||
double var10000;
|
||||
if (n >= 1000000000) {
|
||||
var10000 = (double) Math.round((double) n / 1.0E8);
|
||||
return var10000 / 10.0 + "G" + unit;
|
||||
} else if (n >= 1000000) {
|
||||
var10000 = (double) Math.round((double) n / 100000.0);
|
||||
return var10000 / 10.0 + "M" + unit;
|
||||
} else if (n >= 1000) {
|
||||
var10000 = (double) Math.round((double) n / 100.0);
|
||||
return var10000 / 10.0 + "k" + unit;
|
||||
}
|
||||
// else if (n < 0.001) {
|
||||
// var10000 = (double) Math.round((double) n * 10000000.0);
|
||||
// return var10000 / 10.0 + "μ" + unit;
|
||||
// }
|
||||
else if (n < 1) {
|
||||
var10000 = (double) Math.round((double) n * 10000.0);
|
||||
return var10000 / 10.0 + "m" + unit;
|
||||
}
|
||||
else {
|
||||
return Math.round(n) + unit;
|
||||
}
|
||||
}
|
||||
public static void drainFilteredTank(SmartFluidTank tank, int amount){
|
||||
tank.setFluid(new FluidStack(tank.getFluid(),Math.max(tank.getFluidAmount()-amount,0)));
|
||||
}
|
||||
public static void fillFilteredTank(SmartFluidTank tank, FluidStack resource){
|
||||
if(tank.getFluid().getFluid().isSame(resource.getFluid())||tank.isEmpty())
|
||||
tank.setFluid(new FluidStack(resource.getFluid(),Math.min(tank.getFluidAmount()+resource.getAmount(),tank.getCapacity())));
|
||||
}
|
||||
public static Iterable<BlockPos> AABBtoBlockPos(AABB aabb) {
|
||||
return BlockPos.betweenClosed(new BlockPos((int) aabb.minX, (int) aabb.minY, (int) aabb.minZ), new BlockPos((int) aabb.maxX, (int) aabb.maxY, (int) aabb.maxZ));
|
||||
}
|
||||
public static SmartFluidTank createTank(int capacity, boolean extractionAllowed, Consumer<FluidStack> updateCallback) {
|
||||
return createTank(capacity, extractionAllowed, true, updateCallback, null);
|
||||
}
|
||||
public static SmartFluidTank createTank(int capacity, boolean extractionAllowed, boolean insertionAllowed, Consumer<FluidStack> updateCallback) {
|
||||
return createTank(capacity, extractionAllowed, insertionAllowed, updateCallback, null);
|
||||
}
|
||||
public static SmartFluidTank createTank(int capacity, boolean extractionAllowed, boolean insertionAllowed, Consumer<FluidStack> updateCallback, Fluid validFluid) {
|
||||
return new SmartFluidTank(capacity, updateCallback) {
|
||||
@Override
|
||||
public boolean isFluidValid(FluidStack stack) {
|
||||
|
||||
if (validFluid == null) return true;
|
||||
|
||||
return stack.getFluid().isSame(validFluid);
|
||||
}
|
||||
@Override
|
||||
public FluidStack drain(FluidStack resource, FluidAction action) {
|
||||
if (!extractionAllowed) return FluidStack.EMPTY;
|
||||
return super.drain(resource, action);
|
||||
}
|
||||
@Override
|
||||
public FluidStack drain(int maxDrain, FluidAction action) {
|
||||
if (!extractionAllowed) return FluidStack.EMPTY;
|
||||
return super.drain(maxDrain, action);
|
||||
}
|
||||
@Override
|
||||
public int fill(FluidStack resource, FluidAction action) {
|
||||
if (!insertionAllowed) return 0;
|
||||
return super.fill(resource, action);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package com.drmangotea.tfmg.base;
|
||||
|
||||
import com.drmangotea.tfmg.TFMG;
|
||||
import com.drmangotea.tfmg.content.decoration.concrete.RebarStairsBlock;
|
||||
import com.simibubi.create.foundation.data.CreateRegistrate;
|
||||
import com.tterrag.registrate.builders.BlockBuilder;
|
||||
import com.tterrag.registrate.builders.ItemBuilder;
|
||||
import com.tterrag.registrate.providers.DataGenContext;
|
||||
import com.tterrag.registrate.providers.RegistrateBlockstateProvider;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.BlockItem;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.SlabBlock;
|
||||
import net.minecraft.world.level.block.StairBlock;
|
||||
import net.minecraft.world.level.block.WallBlock;
|
||||
import net.minecraftforge.client.model.generators.ModelFile;
|
||||
|
||||
public class TFMGVanillaBlockStates {
|
||||
|
||||
|
||||
//WALL
|
||||
public static void generateWallBlockState(DataGenContext<Block, WallBlock> ctx, RegistrateBlockstateProvider prov,
|
||||
String name) {
|
||||
prov.wallBlock(ctx.get(), name, TFMG.asResource("block/" + name));
|
||||
}
|
||||
|
||||
public static ItemBuilder<BlockItem, BlockBuilder<WallBlock, CreateRegistrate>> transformWallItem(
|
||||
ItemBuilder<BlockItem, BlockBuilder<WallBlock, CreateRegistrate>> builder, String name) {
|
||||
builder.model((c, p) -> p.wallInventory(c.getName(), TFMG.asResource("block/" + name)));
|
||||
return builder;
|
||||
}
|
||||
|
||||
//STAIR
|
||||
public static void generateStairBlockState(DataGenContext<Block, StairBlock> ctx, RegistrateBlockstateProvider prov,
|
||||
String name) {
|
||||
prov.stairsBlock(ctx.get(), name, TFMG.asResource("block/" + name));
|
||||
}
|
||||
|
||||
public static ItemBuilder<BlockItem, BlockBuilder<StairBlock, CreateRegistrate>> transformStairItem(
|
||||
ItemBuilder<BlockItem, BlockBuilder<StairBlock, CreateRegistrate>> builder, String variantName) {
|
||||
return builder;
|
||||
}
|
||||
|
||||
//SLAB
|
||||
|
||||
public static void generateSlabBlockState(DataGenContext<Block, SlabBlock> ctx, RegistrateBlockstateProvider prov,
|
||||
String variantName) {
|
||||
String name = variantName;
|
||||
ResourceLocation texture = TFMG.asResource("block/" + name);
|
||||
|
||||
ModelFile bottom = prov.models()
|
||||
.slab(name + "_bottom", texture, texture, texture);
|
||||
ModelFile top = prov.models()
|
||||
.slabTop(name + "_top", texture, texture, texture);
|
||||
ModelFile doubleSlab = prov.models()
|
||||
.getExistingFile(prov.modLoc("block/" + name));
|
||||
|
||||
prov.slabBlock(ctx.get(), bottom, top, doubleSlab);
|
||||
}
|
||||
|
||||
public static ItemBuilder<BlockItem, BlockBuilder<SlabBlock, CreateRegistrate>> transformSlabItem(
|
||||
ItemBuilder<BlockItem, BlockBuilder<SlabBlock, CreateRegistrate>> builder, String variantName) {
|
||||
return builder;
|
||||
}
|
||||
}
|
||||
43
src/main/java/com/drmangotea/tfmg/base/WallMountBlock.java
Normal file
43
src/main/java/com/drmangotea/tfmg/base/WallMountBlock.java
Normal file
@@ -0,0 +1,43 @@
|
||||
package com.drmangotea.tfmg.base;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.world.item.context.BlockPlaceContext;
|
||||
import net.minecraft.world.level.LevelReader;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.StateDefinition;
|
||||
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
|
||||
import net.minecraft.world.level.block.state.properties.DirectionProperty;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class WallMountBlock extends Block {
|
||||
|
||||
public static final DirectionProperty FACING = BlockStateProperties.FACING;
|
||||
|
||||
public WallMountBlock(Properties p_49795_) {
|
||||
super(p_49795_);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
|
||||
super.createBlockStateDefinition(builder.add(FACING));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public BlockState getStateForPlacement(BlockPlaceContext p_58126_) {
|
||||
BlockState blockstate = this.defaultBlockState();
|
||||
LevelReader levelreader = p_58126_.getLevel();
|
||||
BlockPos blockpos = p_58126_.getClickedPos();
|
||||
Direction[] adirection = p_58126_.getNearestLookingDirections();
|
||||
for (Direction direction : adirection) {
|
||||
Direction direction1 = direction.getOpposite();
|
||||
blockstate = blockstate.setValue(FACING, direction1);
|
||||
if (blockstate.canSurvive(levelreader, blockpos)) {
|
||||
return blockstate;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package com.drmangotea.tfmg.base.fluid;
|
||||
|
||||
|
||||
import com.simibubi.create.AllFluids;
|
||||
import com.simibubi.create.Create;
|
||||
import com.simibubi.create.foundation.utility.Color;
|
||||
import com.tterrag.registrate.builders.FluidBuilder;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.damagesource.DamageSource;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.level.BlockAndTintGetter;
|
||||
import net.minecraft.world.level.material.FluidState;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraftforge.fluids.FluidStack;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class AcidFluidType extends AllFluids.TintedFluidType {
|
||||
|
||||
// public static DamageSource damageSourceAcid = new DamageSource("tfmg.acid");
|
||||
public AcidFluidType(Properties properties, ResourceLocation stillTexture, ResourceLocation flowingTexture) {
|
||||
super(properties, stillTexture, flowingTexture);
|
||||
}
|
||||
private Vector3f fogColor;
|
||||
private Supplier<Float> fogDistance;
|
||||
|
||||
public static FluidBuilder.FluidTypeFactory create(int fogColor, Supplier<Float> fogDistance) {
|
||||
return (p, s, f) -> {
|
||||
AcidFluidType fluidType = new AcidFluidType(p, s, f);
|
||||
fluidType.fogColor = new Color(fogColor, false).asVectorF();
|
||||
fluidType.fogDistance = fogDistance;
|
||||
return fluidType;
|
||||
};
|
||||
}
|
||||
@Override
|
||||
protected Vector3f getCustomFogColor() {
|
||||
return fogColor;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float getFogDistanceModifier() {
|
||||
return fogDistance.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getTintColor(FluidStack stack) {
|
||||
return NO_TINT;
|
||||
}
|
||||
@Override
|
||||
public int getTintColor(FluidState state, BlockAndTintGetter world, BlockPos pos) {
|
||||
return 0x00ffffff;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean move(FluidState state, LivingEntity entity, Vec3 movementVector, double gravity)
|
||||
{
|
||||
|
||||
|
||||
|
||||
// if(Create.RANDOM.nextInt(2)==0)
|
||||
// entity.hurt(damageSourceAcid,2);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
package com.drmangotea.tfmg.base.fluid;
|
||||
|
||||
import com.drmangotea.tfmg.registry.TFMGBlocks;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.state.StateDefinition;
|
||||
import net.minecraft.world.level.material.Fluid;
|
||||
import net.minecraft.world.level.material.FluidState;
|
||||
import net.minecraftforge.fluids.ForgeFlowingFluid;
|
||||
|
||||
public class AsphaltFluid extends ForgeFlowingFluid {
|
||||
|
||||
|
||||
protected AsphaltFluid(Properties properties) {
|
||||
super(properties);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSource(FluidState p_76140_) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAmount(FluidState p_164509_) {
|
||||
return 8;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void randomTick(Level level, BlockPos pos, FluidState p_230574_, RandomSource randomSource) {
|
||||
int random = randomSource.nextInt(7) ;
|
||||
|
||||
if(random==2) {
|
||||
level.setBlock(pos, TFMGBlocks.ASPHALT.get().defaultBlockState(), 3);
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean isRandomlyTicking() {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
public static class Flowing extends AsphaltFluid {
|
||||
public Flowing(Properties properties) {
|
||||
super(properties);
|
||||
}
|
||||
|
||||
protected void createFluidStateDefinition(StateDefinition.Builder<Fluid, FluidState> p_76260_) {
|
||||
super.createFluidStateDefinition(p_76260_);
|
||||
p_76260_.add(LEVEL);
|
||||
}
|
||||
|
||||
public int getAmount(FluidState p_76264_) {
|
||||
return p_76264_.getValue(LEVEL);
|
||||
}
|
||||
|
||||
public boolean isSource(FluidState p_76262_) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Source extends AsphaltFluid {
|
||||
public Source(Properties properties) {
|
||||
super(properties);
|
||||
}
|
||||
|
||||
public int getAmount(FluidState p_76269_) {
|
||||
return 8;
|
||||
}
|
||||
|
||||
public boolean isSource(FluidState p_76267_) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
package com.drmangotea.tfmg.base.fluid;
|
||||
|
||||
import com.drmangotea.tfmg.registry.TFMGBlocks;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.LiquidBlock;
|
||||
import net.minecraft.world.level.block.state.StateDefinition;
|
||||
import net.minecraft.world.level.material.Fluid;
|
||||
import net.minecraft.world.level.material.FluidState;
|
||||
import net.minecraftforge.fluids.ForgeFlowingFluid;
|
||||
|
||||
import static com.drmangotea.tfmg.content.decoration.concrete.ConcreteloggedBlock.CONCRETELOGGED;
|
||||
|
||||
public class ConcreteFluid extends ForgeFlowingFluid {
|
||||
protected ConcreteFluid(Properties properties) {
|
||||
super(properties);
|
||||
}
|
||||
@Override
|
||||
public boolean isSource(FluidState p_76140_) {
|
||||
return true;
|
||||
}
|
||||
@Override
|
||||
public int getAmount(FluidState p_164509_) {
|
||||
return 8;
|
||||
}
|
||||
@Override
|
||||
public void randomTick(Level level, BlockPos pos, FluidState p_230574_, RandomSource randomSource) {
|
||||
|
||||
if(!(level.getBlockState(pos).getBlock() instanceof LiquidBlock))
|
||||
return;
|
||||
|
||||
int random = randomSource.nextInt(7) ;
|
||||
if(random==2) {
|
||||
|
||||
level.setBlock(pos, TFMGBlocks.CONCRETE.block.get().defaultBlockState(), 3);
|
||||
}
|
||||
}
|
||||
protected boolean isRandomlyTicking() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public static class Flowing extends ConcreteFluid {
|
||||
public Flowing(Properties properties) {
|
||||
super(properties);
|
||||
}
|
||||
|
||||
protected void createFluidStateDefinition(StateDefinition.Builder<Fluid, FluidState> p_76260_) {
|
||||
super.createFluidStateDefinition(p_76260_);
|
||||
p_76260_.add(LEVEL);
|
||||
}
|
||||
|
||||
public int getAmount(FluidState p_76264_) {
|
||||
return p_76264_.getValue(LEVEL);
|
||||
}
|
||||
|
||||
public boolean isSource(FluidState p_76262_) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Source extends ConcreteFluid {
|
||||
public Source(Properties properties) {
|
||||
super(properties);
|
||||
}
|
||||
|
||||
public int getAmount(FluidState p_76269_) {
|
||||
return 8;
|
||||
}
|
||||
|
||||
public boolean isSource(FluidState p_76267_) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
package com.drmangotea.tfmg.base.fluid;
|
||||
|
||||
import com.drmangotea.tfmg.registry.TFMGFluids;
|
||||
import com.simibubi.create.AllFluids;
|
||||
import com.simibubi.create.Create;
|
||||
import com.simibubi.create.foundation.utility.Color;
|
||||
import com.tterrag.registrate.builders.FluidBuilder;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.damagesource.DamageSource;
|
||||
import net.minecraft.world.damagesource.DamageSources;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.level.BlockAndTintGetter;
|
||||
import net.minecraft.world.level.material.FluidState;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraftforge.fluids.FluidStack;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class HotFluidType extends TFMGFluids.SolidRenderedPlaceableFluidType {
|
||||
public HotFluidType(Properties properties, ResourceLocation stillTexture, ResourceLocation flowingTexture) {
|
||||
super(properties, stillTexture, flowingTexture);
|
||||
}
|
||||
private Vector3f fogColor;
|
||||
private Supplier<Float> fogDistance;
|
||||
|
||||
public static FluidBuilder.FluidTypeFactory create(int fogColor, Supplier<Float> fogDistance) {
|
||||
return (p, s, f) -> {
|
||||
HotFluidType fluidType = new HotFluidType(p, s, f);
|
||||
fluidType.fogColor = new Color(fogColor, false).asVectorF();
|
||||
fluidType.fogDistance = fogDistance;
|
||||
return fluidType;
|
||||
};
|
||||
}
|
||||
@Override
|
||||
protected Vector3f getCustomFogColor() {
|
||||
return fogColor;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float getFogDistanceModifier() {
|
||||
return fogDistance.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getTintColor(FluidStack stack) {
|
||||
return NO_TINT;
|
||||
}
|
||||
@Override
|
||||
public int getTintColor(FluidState state, BlockAndTintGetter world, BlockPos pos) {
|
||||
return 0x00ffffff;
|
||||
}
|
||||
@Override
|
||||
public int getLightLevel() {
|
||||
return 15;
|
||||
}
|
||||
@Override
|
||||
public int getTemperature()
|
||||
{
|
||||
return 1270;
|
||||
}
|
||||
@Override
|
||||
public int getViscosity()
|
||||
{
|
||||
return 50;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean move(FluidState state, LivingEntity entity, Vec3 movementVector, double gravity)
|
||||
{
|
||||
entity.setDeltaMovement(entity.getDeltaMovement().scale(0.6d));
|
||||
|
||||
entity.setSecondsOnFire(10);
|
||||
|
||||
if(Create.RANDOM.nextInt(30)==27)
|
||||
entity.lavaHurt();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean canExtinguish(Entity entity)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
package com.drmangotea.tfmg.base.fluid;
|
||||
|
||||
import com.drmangotea.tfmg.TFMG;
|
||||
import com.drmangotea.tfmg.registry.TFMGBlocks;
|
||||
import com.simibubi.create.content.decoration.palettes.AllPaletteBlocks;
|
||||
import com.simibubi.create.content.decoration.palettes.AllPaletteStoneTypes;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraftforge.common.ForgeMod;
|
||||
import net.minecraftforge.fluids.FluidInteractionRegistry;
|
||||
import net.minecraftforge.registries.ForgeRegistries;
|
||||
|
||||
import static com.drmangotea.tfmg.registry.TFMGFluids.*;
|
||||
|
||||
public class TFMGFluidInteractions {
|
||||
public static void registerFluidInteractions() {
|
||||
FluidInteractionRegistry.addInteraction(ForgeMod.LAVA_TYPE.get(), new FluidInteractionRegistry.InteractionInformation(
|
||||
CRUDE_OIL.get().getFluidType(),
|
||||
fluidState -> {
|
||||
if (fluidState.isSource()) {
|
||||
return TFMGBlocks.FOSSILSTONE.get().defaultBlockState();
|
||||
} else {
|
||||
return Blocks.SMOOTH_BASALT.defaultBlockState();
|
||||
}
|
||||
}
|
||||
));
|
||||
FluidInteractionRegistry.addInteraction(ForgeMod.LAVA_TYPE.get(), new FluidInteractionRegistry.InteractionInformation(
|
||||
HEAVY_OIL.get().getFluidType(),
|
||||
fluidState -> {
|
||||
if (fluidState.isSource()) {
|
||||
return TFMGBlocks.FOSSILSTONE.get().defaultBlockState();
|
||||
} else {
|
||||
return Blocks.SMOOTH_BASALT.defaultBlockState();
|
||||
}
|
||||
}
|
||||
));
|
||||
//
|
||||
FluidInteractionRegistry.addInteraction(ForgeMod.LAVA_TYPE.get(), new FluidInteractionRegistry.InteractionInformation(
|
||||
GASOLINE.get().getFluidType(),
|
||||
fluidState -> {
|
||||
if (fluidState.isSource()) {
|
||||
return TFMGBlocks.FOSSILSTONE.get().defaultBlockState();
|
||||
} else {
|
||||
return Blocks.SMOOTH_BASALT.defaultBlockState();
|
||||
}
|
||||
}
|
||||
));
|
||||
FluidInteractionRegistry.addInteraction(ForgeMod.LAVA_TYPE.get(), new FluidInteractionRegistry.InteractionInformation(
|
||||
DIESEL.get().getFluidType(),
|
||||
fluidState -> {
|
||||
if (fluidState.isSource()) {
|
||||
return TFMGBlocks.FOSSILSTONE.get().defaultBlockState();
|
||||
} else {
|
||||
return Blocks.SMOOTH_BASALT.defaultBlockState();
|
||||
}
|
||||
}
|
||||
));
|
||||
FluidInteractionRegistry.addInteraction(ForgeMod.LAVA_TYPE.get(), new FluidInteractionRegistry.InteractionInformation(
|
||||
NAPHTHA.get().getFluidType(),
|
||||
fluidState -> {
|
||||
if (fluidState.isSource()) {
|
||||
return TFMGBlocks.FOSSILSTONE.get().defaultBlockState();
|
||||
} else {
|
||||
return Blocks.SMOOTH_BASALT.defaultBlockState();
|
||||
}
|
||||
}
|
||||
));
|
||||
FluidInteractionRegistry.addInteraction(ForgeMod.LAVA_TYPE.get(), new FluidInteractionRegistry.InteractionInformation(
|
||||
KEROSENE.get().getFluidType(),
|
||||
fluidState -> {
|
||||
if (fluidState.isSource()) {
|
||||
return TFMGBlocks.FOSSILSTONE.get().defaultBlockState();
|
||||
} else {
|
||||
return Blocks.SMOOTH_BASALT.defaultBlockState();
|
||||
}
|
||||
}
|
||||
));
|
||||
FluidInteractionRegistry.addInteraction(ForgeMod.LAVA_TYPE.get(), new FluidInteractionRegistry.InteractionInformation(
|
||||
LUBRICATION_OIL.get().getFluidType(),
|
||||
fluidState -> {
|
||||
if (fluidState.isSource()) {
|
||||
return TFMGBlocks.FOSSILSTONE.get().defaultBlockState();
|
||||
} else {
|
||||
return Blocks.SMOOTH_BASALT.defaultBlockState();
|
||||
}
|
||||
}
|
||||
));
|
||||
FluidInteractionRegistry.addInteraction(ForgeMod.LAVA_TYPE.get(), new FluidInteractionRegistry.InteractionInformation(
|
||||
COOLING_FLUID.get().getFluidType(),
|
||||
fluidState -> {
|
||||
if (fluidState.isSource()) {
|
||||
return Blocks.BASALT.defaultBlockState();
|
||||
} else {
|
||||
return Blocks.SMOOTH_BASALT.defaultBlockState();
|
||||
}
|
||||
}
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,262 @@
|
||||
package com.drmangotea.tfmg.base.palettes;
|
||||
|
||||
|
||||
import com.drmangotea.tfmg.base.TFMGCreativeTabs;
|
||||
import com.drmangotea.tfmg.registry.TFMGPaletteStoneTypes;
|
||||
import com.simibubi.create.Create;
|
||||
import com.simibubi.create.foundation.data.CreateRegistrate;
|
||||
import com.simibubi.create.foundation.utility.Lang;
|
||||
import com.tterrag.registrate.builders.BlockBuilder;
|
||||
import com.tterrag.registrate.builders.ItemBuilder;
|
||||
import com.tterrag.registrate.providers.DataGenContext;
|
||||
import com.tterrag.registrate.providers.RegistrateBlockstateProvider;
|
||||
import com.tterrag.registrate.providers.RegistrateRecipeProvider;
|
||||
import com.tterrag.registrate.util.DataIngredient;
|
||||
import com.tterrag.registrate.util.entry.BlockEntry;
|
||||
import com.tterrag.registrate.util.nullness.NonnullType;
|
||||
import net.minecraft.data.recipes.RecipeCategory;
|
||||
import net.minecraft.data.recipes.ShapedRecipeBuilder;
|
||||
import net.minecraft.data.recipes.ShapelessRecipeBuilder;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.tags.BlockTags;
|
||||
import net.minecraft.tags.ItemTags;
|
||||
import net.minecraft.tags.TagKey;
|
||||
import net.minecraft.world.item.BlockItem;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.SlabBlock;
|
||||
import net.minecraft.world.level.block.StairBlock;
|
||||
import net.minecraft.world.level.block.WallBlock;
|
||||
import net.minecraft.world.level.block.state.BlockBehaviour.Properties;
|
||||
import net.minecraftforge.client.model.generators.ModelFile;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
|
||||
import static com.drmangotea.tfmg.TFMG.REGISTRATE;
|
||||
import static com.simibubi.create.foundation.data.TagGen.pickaxeOnly;
|
||||
|
||||
public abstract class TFMGPaletteBlockPartial<B extends Block> {
|
||||
|
||||
public static final TFMGPaletteBlockPartial<StairBlock> STAIR = new Stairs();
|
||||
public static final TFMGPaletteBlockPartial<SlabBlock> SLAB = new Slab(false);
|
||||
public static final TFMGPaletteBlockPartial<SlabBlock> UNIQUE_SLAB = new Slab(true);
|
||||
public static final TFMGPaletteBlockPartial<WallBlock> WALL = new Wall();
|
||||
public static final TFMGPaletteBlockPartial<?>[] ALL_PARTIALS = { STAIR, SLAB, WALL };
|
||||
public static final TFMGPaletteBlockPartial<?>[] FOR_POLISHED = { STAIR, UNIQUE_SLAB, WALL };
|
||||
private String name;
|
||||
|
||||
protected TFMGPaletteBlockPartial(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
static {
|
||||
REGISTRATE.setCreativeTab(TFMGCreativeTabs.TFMG_DECORATION);
|
||||
}
|
||||
|
||||
public @NonnullType BlockBuilder<B, CreateRegistrate> create(String variantName, TFMGPaletteBlockPattern pattern,
|
||||
BlockEntry<? extends Block> block, TFMGPaletteStoneTypes variant) {
|
||||
String patternName = Lang.nonPluralId(pattern.createName(variantName));
|
||||
String blockName = patternName + "_" + this.name;
|
||||
|
||||
BlockBuilder<B, CreateRegistrate> blockBuilder = REGISTRATE
|
||||
.block(blockName, p -> createBlock(block))
|
||||
.blockstate((c, p) -> generateBlockState(c, p, variantName, pattern, block))
|
||||
.recipe((c, p) -> createRecipes(variant, block, c, p))
|
||||
.transform(b -> transformBlock(b, variantName, pattern));
|
||||
|
||||
ItemBuilder<BlockItem, BlockBuilder<B, CreateRegistrate>> itemBuilder = blockBuilder.item()
|
||||
.transform(b -> transformItem(b, variantName, pattern));
|
||||
|
||||
if (canRecycle())
|
||||
itemBuilder.tag(variant.materialTag);
|
||||
|
||||
return itemBuilder.build();
|
||||
}
|
||||
|
||||
protected ResourceLocation getTexture(String variantName, TFMGPaletteBlockPattern pattern, int index) {
|
||||
return TFMGPaletteBlockPattern.toLocation(variantName, pattern.getTexture(index));
|
||||
}
|
||||
protected BlockBuilder<B, CreateRegistrate> transformBlock(BlockBuilder<B, CreateRegistrate> builder,
|
||||
String variantName, TFMGPaletteBlockPattern pattern) {
|
||||
getBlockTags().forEach(builder::tag);
|
||||
return builder.transform(pickaxeOnly());
|
||||
}
|
||||
protected ItemBuilder<BlockItem, BlockBuilder<B, CreateRegistrate>> transformItem(
|
||||
ItemBuilder<BlockItem, BlockBuilder<B, CreateRegistrate>> builder, String variantName,
|
||||
TFMGPaletteBlockPattern pattern) {
|
||||
getItemTags().forEach(builder::tag);
|
||||
return builder;
|
||||
}
|
||||
protected boolean canRecycle() {
|
||||
return true;
|
||||
}
|
||||
protected abstract Iterable<TagKey<Block>> getBlockTags();
|
||||
protected abstract Iterable<TagKey<Item>> getItemTags();
|
||||
protected abstract B createBlock(Supplier<? extends Block> block);
|
||||
protected abstract void createRecipes(TFMGPaletteStoneTypes type, BlockEntry<? extends Block> patternBlock,
|
||||
DataGenContext<Block, ? extends Block> c, RegistrateRecipeProvider p);
|
||||
protected abstract void generateBlockState(DataGenContext<Block, B> ctx, RegistrateBlockstateProvider prov, String variantName, TFMGPaletteBlockPattern pattern, Supplier<? extends Block> block);
|
||||
private static class Stairs extends TFMGPaletteBlockPartial<StairBlock> {
|
||||
public Stairs() {
|
||||
super("stairs");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected StairBlock createBlock(Supplier<? extends Block> block) {
|
||||
return new StairBlock(() -> block.get()
|
||||
.defaultBlockState(), Properties.copy(block.get()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void generateBlockState(DataGenContext<Block, StairBlock> ctx, RegistrateBlockstateProvider prov,
|
||||
String variantName, TFMGPaletteBlockPattern pattern, Supplier<? extends Block> block) {
|
||||
prov.stairsBlock(ctx.get(), getTexture(variantName, pattern, 0));
|
||||
}
|
||||
@Override
|
||||
protected Iterable<TagKey<Block>> getBlockTags() {
|
||||
return Arrays.asList(BlockTags.STAIRS);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Iterable<TagKey<Item>> getItemTags() {
|
||||
return Arrays.asList(ItemTags.STAIRS);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createRecipes(TFMGPaletteStoneTypes type, BlockEntry<? extends Block> patternBlock,
|
||||
DataGenContext<Block, ? extends Block> c, RegistrateRecipeProvider p) {
|
||||
RecipeCategory category = RecipeCategory.BUILDING_BLOCKS;
|
||||
p.stairs(DataIngredient.items(patternBlock.get()), category, c::get, c.getName(), false);
|
||||
p.stonecutting(DataIngredient.tag(type.materialTag), category, c::get, 1);
|
||||
}
|
||||
}
|
||||
private static class Slab extends TFMGPaletteBlockPartial<SlabBlock> {
|
||||
|
||||
private boolean customSide;
|
||||
|
||||
public Slab(boolean customSide) {
|
||||
super("slab");
|
||||
this.customSide = customSide;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SlabBlock createBlock(Supplier<? extends Block> block) {
|
||||
return new SlabBlock(Properties.copy(block.get()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean canRecycle() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void generateBlockState(DataGenContext<Block, SlabBlock> ctx, RegistrateBlockstateProvider prov,
|
||||
String variantName, TFMGPaletteBlockPattern pattern, Supplier<? extends Block> block) {
|
||||
String name = ctx.getName();
|
||||
ResourceLocation mainTexture = getTexture(variantName, pattern, 0);
|
||||
ResourceLocation sideTexture = customSide ? getTexture(variantName, pattern, 1) : mainTexture;
|
||||
|
||||
ModelFile bottom = prov.models()
|
||||
.slab(name, sideTexture, mainTexture, mainTexture);
|
||||
ModelFile top = prov.models()
|
||||
.slabTop(name + "_top", sideTexture, mainTexture, mainTexture);
|
||||
ModelFile doubleSlab;
|
||||
|
||||
if (customSide) {
|
||||
doubleSlab = prov.models()
|
||||
.cubeColumn(name + "_double", sideTexture, mainTexture);
|
||||
} else {
|
||||
doubleSlab = prov.models()
|
||||
.getExistingFile(prov.modLoc(pattern.createName(variantName)));
|
||||
}
|
||||
|
||||
prov.slabBlock(ctx.get(), bottom, top, doubleSlab);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Iterable<TagKey<Block>> getBlockTags() {
|
||||
return Arrays.asList(BlockTags.SLABS);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Iterable<TagKey<Item>> getItemTags() {
|
||||
return Arrays.asList(ItemTags.SLABS);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createRecipes(TFMGPaletteStoneTypes type, BlockEntry<? extends Block> patternBlock,
|
||||
DataGenContext<Block, ? extends Block> c, RegistrateRecipeProvider p) {
|
||||
RecipeCategory category = RecipeCategory.BUILDING_BLOCKS;
|
||||
p.slab(DataIngredient.items(patternBlock.get()), category, c::get, c.getName(), false);
|
||||
p.stonecutting(DataIngredient.tag(type.materialTag), category, c::get, 2);
|
||||
DataIngredient ingredient = DataIngredient.items(c.get());
|
||||
ShapelessRecipeBuilder.shapeless(category, patternBlock.get())
|
||||
.requires(ingredient)
|
||||
.requires(ingredient)
|
||||
.unlockedBy("has_" + c.getName(), ingredient.getCritereon(p))
|
||||
.save(p, Create.ID + ":" + c.getName() + "_recycling");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BlockBuilder<SlabBlock, CreateRegistrate> transformBlock(
|
||||
BlockBuilder<SlabBlock, CreateRegistrate> builder, String variantName, TFMGPaletteBlockPattern pattern) {
|
||||
builder.loot((lt, block) -> lt.add(block, lt.createSlabItemTable(block)));
|
||||
return super.transformBlock(builder, variantName, pattern);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class Wall extends TFMGPaletteBlockPartial<WallBlock> {
|
||||
|
||||
public Wall() {
|
||||
super("wall");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected WallBlock createBlock(Supplier<? extends Block> block) {
|
||||
return new WallBlock(Properties.copy(block.get()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ItemBuilder<BlockItem, BlockBuilder<WallBlock, CreateRegistrate>> transformItem(
|
||||
ItemBuilder<BlockItem, BlockBuilder<WallBlock, CreateRegistrate>> builder, String variantName,
|
||||
TFMGPaletteBlockPattern pattern) {
|
||||
builder.model((c, p) -> p.wallInventory(c.getName(), getTexture(variantName, pattern, 0)));
|
||||
return super.transformItem(builder, variantName, pattern);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void generateBlockState(DataGenContext<Block, WallBlock> ctx, RegistrateBlockstateProvider prov,
|
||||
String variantName, TFMGPaletteBlockPattern pattern, Supplier<? extends Block> block) {
|
||||
prov.wallBlock(ctx.get(), pattern.createName(variantName), getTexture(variantName, pattern, 0));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Iterable<TagKey<Block>> getBlockTags() {
|
||||
return Arrays.asList(BlockTags.WALLS);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Iterable<TagKey<Item>> getItemTags() {
|
||||
return Arrays.asList(ItemTags.WALLS);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createRecipes(TFMGPaletteStoneTypes type, BlockEntry<? extends Block> patternBlock,
|
||||
DataGenContext<Block, ? extends Block> c, RegistrateRecipeProvider p) {
|
||||
RecipeCategory category = RecipeCategory.BUILDING_BLOCKS;
|
||||
p.stonecutting(DataIngredient.tag(type.materialTag), category, c::get, 1);
|
||||
DataIngredient ingredient = DataIngredient.items(patternBlock.get());
|
||||
ShapedRecipeBuilder.shaped(category, c.get(), 6)
|
||||
.pattern("XXX")
|
||||
.pattern("XXX")
|
||||
.define('X', ingredient)
|
||||
.unlockedBy("has_" + p.safeName(ingredient), ingredient.getCritereon(p))
|
||||
.save(p, p.safeId(c.get()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,263 @@
|
||||
package com.drmangotea.tfmg.base.palettes;
|
||||
|
||||
|
||||
import com.drmangotea.tfmg.TFMG;
|
||||
import com.simibubi.create.content.decoration.palettes.ConnectedPillarBlock;
|
||||
import com.simibubi.create.foundation.block.connected.*;
|
||||
import com.tterrag.registrate.providers.DataGenContext;
|
||||
import com.tterrag.registrate.providers.RegistrateBlockstateProvider;
|
||||
import com.tterrag.registrate.providers.RegistrateRecipeProvider;
|
||||
import com.tterrag.registrate.util.nullness.NonNullBiConsumer;
|
||||
import com.tterrag.registrate.util.nullness.NonNullFunction;
|
||||
import com.tterrag.registrate.util.nullness.NonNullSupplier;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.tags.TagKey;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.state.BlockBehaviour;
|
||||
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
import net.minecraftforge.client.model.generators.ConfiguredModel;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import static com.drmangotea.tfmg.base.palettes.TFMGPaletteBlockPartial.ALL_PARTIALS;
|
||||
import static com.drmangotea.tfmg.base.palettes.TFMGPaletteBlockPartial.FOR_POLISHED;
|
||||
import static com.drmangotea.tfmg.base.palettes.TFMGPaletteBlockPattern.PatternNameType.*;
|
||||
|
||||
|
||||
public class TFMGPaletteBlockPattern {
|
||||
|
||||
public static final TFMGPaletteBlockPattern
|
||||
|
||||
CUT =
|
||||
create("cut", PREFIX, ALL_PARTIALS),
|
||||
|
||||
BRICKS = create("cut_bricks", WRAP, ALL_PARTIALS).textures("brick"),
|
||||
SMALL_BRICKS = create("small_bricks", WRAP, ALL_PARTIALS).textures("small_brick"),
|
||||
POLISHED = create("polished_cut", PREFIX, FOR_POLISHED).textures("polished", "slab"),
|
||||
LAYERED = create("layered", PREFIX).blockStateFactory(p -> p::cubeColumn)
|
||||
.textures("layered", "cap")
|
||||
.connectedTextures(v -> new HorizontalCTBehaviour(ct(v, CTs.LAYERED), ct(v, CTs.CAP))),
|
||||
PILLAR = create("pillar", SUFFIX).blockStateFactory(p -> p::pillar)
|
||||
.block(ConnectedPillarBlock::new)
|
||||
.textures("pillar", "cap")
|
||||
.connectedTextures(v -> new RotatedPillarCTBehaviour(ct(v, CTs.PILLAR), ct(v, CTs.CAP)))
|
||||
;
|
||||
|
||||
public static final TFMGPaletteBlockPattern[] VANILLA_RANGE = { CUT, POLISHED, BRICKS, SMALL_BRICKS, LAYERED, PILLAR };
|
||||
|
||||
public static final TFMGPaletteBlockPattern[] STANDARD_RANGE = { CUT, POLISHED, BRICKS, SMALL_BRICKS, LAYERED, PILLAR };
|
||||
|
||||
static final String TEXTURE_LOCATION = "block/palettes/stone_types/%s/%s";
|
||||
|
||||
private PatternNameType nameType;
|
||||
private String[] textures;
|
||||
private String id;
|
||||
private boolean isTranslucent;
|
||||
private TagKey<Block>[] blockTags;
|
||||
private TagKey<Item>[] itemTags;
|
||||
private Optional<Function<String, ConnectedTextureBehaviour>> ctFactory;
|
||||
private IPatternBlockStateGenerator blockStateGenerator;
|
||||
private NonNullFunction<BlockBehaviour.Properties, ? extends Block> blockFactory;
|
||||
private NonNullFunction<NonNullSupplier<Block>, NonNullBiConsumer<DataGenContext<Block, ? extends Block>, RegistrateRecipeProvider>> additionalRecipes;
|
||||
private TFMGPaletteBlockPartial<? extends Block>[] partials;
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
private RenderType renderType;
|
||||
|
||||
private static TFMGPaletteBlockPattern create(String name, PatternNameType nameType,
|
||||
TFMGPaletteBlockPartial<?>... partials) {
|
||||
TFMGPaletteBlockPattern pattern = new TFMGPaletteBlockPattern();
|
||||
pattern.id = name;
|
||||
pattern.ctFactory = Optional.empty();
|
||||
pattern.nameType = nameType;
|
||||
pattern.partials = partials;
|
||||
pattern.additionalRecipes = $ -> NonNullBiConsumer.noop();
|
||||
pattern.isTranslucent = false;
|
||||
pattern.blockFactory = Block::new;
|
||||
pattern.textures = new String[] { name };
|
||||
pattern.blockStateGenerator = p -> p::cubeAll;
|
||||
return pattern;
|
||||
}
|
||||
|
||||
public IPatternBlockStateGenerator getBlockStateGenerator() {
|
||||
return blockStateGenerator;
|
||||
}
|
||||
|
||||
public boolean isTranslucent() {
|
||||
return isTranslucent;
|
||||
}
|
||||
|
||||
public TagKey<Block>[] getBlockTags() {
|
||||
return blockTags;
|
||||
}
|
||||
|
||||
public TagKey<Item>[] getItemTags() {
|
||||
return itemTags;
|
||||
}
|
||||
|
||||
public NonNullFunction<BlockBehaviour.Properties, ? extends Block> getBlockFactory() {
|
||||
return blockFactory;
|
||||
}
|
||||
|
||||
public TFMGPaletteBlockPartial<? extends Block>[] getPartials() {
|
||||
return partials;
|
||||
}
|
||||
|
||||
public String getTexture(int index) {
|
||||
return textures[index];
|
||||
}
|
||||
|
||||
public void addRecipes(NonNullSupplier<Block> baseBlock, DataGenContext<Block, ? extends Block> c,
|
||||
RegistrateRecipeProvider p) {
|
||||
additionalRecipes.apply(baseBlock)
|
||||
.accept(c, p);
|
||||
}
|
||||
|
||||
public Optional<Supplier<ConnectedTextureBehaviour>> createCTBehaviour(String variant) {
|
||||
return ctFactory.map(d -> () -> d.apply(variant));
|
||||
}
|
||||
|
||||
// Builder
|
||||
|
||||
private TFMGPaletteBlockPattern blockStateFactory(IPatternBlockStateGenerator factory) {
|
||||
blockStateGenerator = factory;
|
||||
return this;
|
||||
}
|
||||
|
||||
private TFMGPaletteBlockPattern textures(String... textures) {
|
||||
this.textures = textures;
|
||||
return this;
|
||||
}
|
||||
|
||||
private TFMGPaletteBlockPattern block(NonNullFunction<BlockBehaviour.Properties, ? extends Block> blockFactory) {
|
||||
this.blockFactory = blockFactory;
|
||||
return this;
|
||||
}
|
||||
|
||||
private TFMGPaletteBlockPattern connectedTextures(Function<String, ConnectedTextureBehaviour> factory) {
|
||||
this.ctFactory = Optional.of(factory);
|
||||
return this;
|
||||
}
|
||||
|
||||
// Model generators
|
||||
|
||||
public IBlockStateProvider cubeAll(String variant) {
|
||||
ResourceLocation all = toLocation(variant, textures[0]);
|
||||
return (ctx, prov) -> prov.simpleBlock(ctx.get(), prov.models()
|
||||
.cubeAll(createName(variant), all));
|
||||
}
|
||||
|
||||
public IBlockStateProvider cubeBottomTop(String variant) {
|
||||
ResourceLocation side = toLocation(variant, textures[0]);
|
||||
ResourceLocation bottom = toLocation(variant, textures[1]);
|
||||
ResourceLocation top = toLocation(variant, textures[2]);
|
||||
return (ctx, prov) -> prov.simpleBlock(ctx.get(), prov.models()
|
||||
.cubeBottomTop(createName(variant), side, bottom, top));
|
||||
}
|
||||
|
||||
public IBlockStateProvider pillar(String variant) {
|
||||
ResourceLocation side = toLocation(variant, textures[0]);
|
||||
ResourceLocation end = toLocation(variant, textures[1]);
|
||||
|
||||
return (ctx, prov) -> prov.getVariantBuilder(ctx.getEntry())
|
||||
.forAllStatesExcept(state -> {
|
||||
Direction.Axis axis = state.getValue(BlockStateProperties.AXIS);
|
||||
if (axis == Direction.Axis.Y)
|
||||
return ConfiguredModel.builder()
|
||||
.modelFile(prov.models()
|
||||
.cubeColumn(createName(variant), side, end))
|
||||
.uvLock(false)
|
||||
.build();
|
||||
return ConfiguredModel.builder()
|
||||
.modelFile(prov.models()
|
||||
.cubeColumnHorizontal(createName(variant) + "_horizontal", side, end))
|
||||
.uvLock(false)
|
||||
.rotationX(90)
|
||||
.rotationY(axis == Direction.Axis.X ? 90 : 0)
|
||||
.build();
|
||||
}, BlockStateProperties.WATERLOGGED, ConnectedPillarBlock.NORTH, ConnectedPillarBlock.SOUTH,
|
||||
ConnectedPillarBlock.EAST, ConnectedPillarBlock.WEST);
|
||||
}
|
||||
|
||||
public IBlockStateProvider cubeColumn(String variant) {
|
||||
ResourceLocation side = toLocation(variant, textures[0]);
|
||||
ResourceLocation end = toLocation(variant, textures[1]);
|
||||
return (ctx, prov) -> prov.simpleBlock(ctx.get(), prov.models()
|
||||
.cubeColumn(createName(variant), side, end));
|
||||
}
|
||||
|
||||
// Utility
|
||||
|
||||
public String createName(String variant) {
|
||||
if (nameType == WRAP) {
|
||||
String[] split = id.split("_");
|
||||
if (split.length == 2) {
|
||||
String formatString = "%s_%s_%s";
|
||||
return String.format(formatString, split[0], variant, split[1]);
|
||||
}
|
||||
}
|
||||
String formatString = "%s_%s";
|
||||
return nameType == SUFFIX ? String.format(formatString, variant, id) : String.format(formatString, id, variant);
|
||||
}
|
||||
|
||||
protected static ResourceLocation toLocation(String variant, String texture) {
|
||||
return TFMG.asResource(
|
||||
String.format(TEXTURE_LOCATION, texture, variant + (texture.equals("cut") ? "_" : "_cut_") + texture));
|
||||
}
|
||||
|
||||
protected static CTSpriteShiftEntry ct(String variant, CTs texture) {
|
||||
ResourceLocation resLoc = texture.srcFactory.apply(variant);
|
||||
ResourceLocation resLocTarget = texture.targetFactory.apply(variant);
|
||||
return CTSpriteShifter.getCT(texture.type, resLoc,
|
||||
new ResourceLocation(resLocTarget.getNamespace(), resLocTarget.getPath() + "_connected"));
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
static interface IPatternBlockStateGenerator
|
||||
extends Function<TFMGPaletteBlockPattern, Function<String, IBlockStateProvider>> {
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
static interface IBlockStateProvider
|
||||
extends NonNullBiConsumer<DataGenContext<Block, ? extends Block>, RegistrateBlockstateProvider> {
|
||||
}
|
||||
|
||||
enum PatternNameType {
|
||||
PREFIX, SUFFIX, WRAP
|
||||
}
|
||||
|
||||
// Textures with connectability, used by Spriteshifter
|
||||
|
||||
public enum CTs {
|
||||
|
||||
PILLAR(AllCTTypes.RECTANGLE, s -> toLocation(s, "pillar")),
|
||||
CAP(AllCTTypes.OMNIDIRECTIONAL, s -> toLocation(s, "cap")),
|
||||
LAYERED(AllCTTypes.HORIZONTAL_KRYPPERS, s -> toLocation(s, "layered"))
|
||||
|
||||
;
|
||||
|
||||
public CTType type;
|
||||
private Function<String, ResourceLocation> srcFactory;
|
||||
private Function<String, ResourceLocation> targetFactory;
|
||||
|
||||
private CTs(CTType type, Function<String, ResourceLocation> factory) {
|
||||
this(type, factory, factory);
|
||||
}
|
||||
|
||||
private CTs(CTType type, Function<String, ResourceLocation> srcFactory,
|
||||
Function<String, ResourceLocation> targetFactory) {
|
||||
this.type = type;
|
||||
this.srcFactory = srcFactory;
|
||||
this.targetFactory = targetFactory;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
package com.drmangotea.tfmg.base.palettes;
|
||||
|
||||
|
||||
import com.drmangotea.tfmg.base.TFMGCreativeTabs;
|
||||
import com.drmangotea.tfmg.registry.TFMGPaletteStoneTypes;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.simibubi.create.foundation.data.CreateRegistrate;
|
||||
import com.tterrag.registrate.builders.BlockBuilder;
|
||||
import com.tterrag.registrate.builders.ItemBuilder;
|
||||
import com.tterrag.registrate.providers.ProviderType;
|
||||
import com.tterrag.registrate.util.DataIngredient;
|
||||
import com.tterrag.registrate.util.entry.BlockEntry;
|
||||
import com.tterrag.registrate.util.nullness.NonNullSupplier;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.data.recipes.RecipeCategory;
|
||||
import net.minecraft.tags.TagKey;
|
||||
import net.minecraft.world.item.BlockItem;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
|
||||
|
||||
import static com.drmangotea.tfmg.TFMG.REGISTRATE;
|
||||
import static com.simibubi.create.foundation.data.CreateRegistrate.connectedTextures;
|
||||
import static com.simibubi.create.foundation.data.TagGen.pickaxeOnly;
|
||||
|
||||
@SuppressWarnings("'onRegister(com.tterrag.registrate.util.nullness.NonNullConsumer<? super capture<? extends net.minecraft.world.level.block.Block>>)' in 'com.tterrag.registrate.builders.Builder' cannot be applied to '(com.tterrag.registrate.util.nullness.NonNullConsumer<capture<? super capture<? extends net.minecraft.world.level.block.Block>>>)'")
|
||||
public class TFMGPalettesVariantEntry {
|
||||
|
||||
public final ImmutableList<BlockEntry<? extends Block>> registeredBlocks;
|
||||
public final ImmutableList<BlockEntry<? extends Block>> registeredPartials;
|
||||
|
||||
static {
|
||||
REGISTRATE.setCreativeTab(TFMGCreativeTabs.TFMG_DECORATION);
|
||||
}
|
||||
|
||||
@SuppressWarnings("'onRegister(com.tterrag.registrate.util.nullness.NonNullConsumer<? super capture<? extends net.minecraft.world.level.block.Block>>)' in 'com.tterrag.registrate.builders.Builder' cannot be applied to '(com.tterrag.registrate.util.nullness.NonNullConsumer<capture<? super capture<? extends net.minecraft.world.level.block.Block>>>)'")
|
||||
public TFMGPalettesVariantEntry(String name, TFMGPaletteStoneTypes paletteStoneVariants) {
|
||||
ImmutableList.Builder<BlockEntry<? extends Block>> registeredBlocks = ImmutableList.builder();
|
||||
ImmutableList.Builder<BlockEntry<? extends Block>> registeredPartials = ImmutableList.builder();
|
||||
NonNullSupplier<Block> baseBlock = paletteStoneVariants.baseBlock;
|
||||
|
||||
for (TFMGPaletteBlockPattern pattern : paletteStoneVariants.variantTypes) {
|
||||
BlockBuilder<? extends Block, CreateRegistrate> builder =
|
||||
REGISTRATE.block(pattern.createName(name), pattern.getBlockFactory())
|
||||
.initialProperties(baseBlock)
|
||||
.transform(pickaxeOnly())
|
||||
.blockstate(pattern.getBlockStateGenerator()
|
||||
.apply(pattern)
|
||||
.apply(name)::accept);
|
||||
|
||||
ItemBuilder<BlockItem, ? extends BlockBuilder<? extends Block, CreateRegistrate>> itemBuilder =
|
||||
builder.item();
|
||||
|
||||
TagKey<Block>[] blockTags = pattern.getBlockTags();
|
||||
if (blockTags != null)
|
||||
builder.tag(blockTags);
|
||||
TagKey<Item>[] itemTags = pattern.getItemTags();
|
||||
if (itemTags != null)
|
||||
itemBuilder.tag(itemTags);
|
||||
|
||||
itemBuilder.tag(paletteStoneVariants.materialTag);
|
||||
|
||||
if (pattern.isTranslucent())
|
||||
builder.addLayer(() -> RenderType::translucent);
|
||||
pattern.createCTBehaviour(name)
|
||||
.ifPresent(b -> builder.onRegister(connectedTextures(b)));
|
||||
|
||||
builder.recipe((c, p) -> {
|
||||
p.stonecutting(DataIngredient.tag(paletteStoneVariants.materialTag), RecipeCategory.BUILDING_BLOCKS, c);
|
||||
pattern.addRecipes(baseBlock, c, p);
|
||||
});
|
||||
|
||||
itemBuilder.register();
|
||||
BlockEntry<? extends Block> block = builder.register();
|
||||
registeredBlocks.add(block);
|
||||
|
||||
for (TFMGPaletteBlockPartial<? extends Block> partialBlock : pattern.getPartials())
|
||||
registeredPartials.add(partialBlock.create(name, pattern, block, paletteStoneVariants)
|
||||
.register());
|
||||
}
|
||||
|
||||
REGISTRATE.addDataGenerator(ProviderType.RECIPE,
|
||||
p -> p.stonecutting(DataIngredient.tag(paletteStoneVariants.materialTag), RecipeCategory.BUILDING_BLOCKS,
|
||||
baseBlock));
|
||||
REGISTRATE.addDataGenerator(ProviderType.ITEM_TAGS, p -> p.addTag(paletteStoneVariants.materialTag)
|
||||
.add(baseBlock.get()
|
||||
.asItem()));
|
||||
|
||||
this.registeredBlocks = registeredBlocks.build();
|
||||
this.registeredPartials = registeredPartials.build();
|
||||
}
|
||||
|
||||
}
|
||||
117
src/main/java/com/drmangotea/tfmg/base/spark/BlueSpark.java
Normal file
117
src/main/java/com/drmangotea/tfmg/base/spark/BlueSpark.java
Normal file
@@ -0,0 +1,117 @@
|
||||
package com.drmangotea.tfmg.base.spark;
|
||||
|
||||
|
||||
|
||||
|
||||
import com.drmangotea.tfmg.content.items.weapons.explosives.thermite_grenades.fire.BlueFireBlock;
|
||||
import com.drmangotea.tfmg.registry.TFMGEntityTypes;
|
||||
import com.drmangotea.tfmg.registry.TFMGItems;
|
||||
import com.simibubi.create.content.trains.CubeParticleData;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.particles.ParticleOptions;
|
||||
import net.minecraft.core.particles.ParticleTypes;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.Mob;
|
||||
import net.minecraft.world.entity.projectile.ThrowableProjectile;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.minecraft.world.phys.EntityHitResult;
|
||||
import net.minecraft.world.phys.HitResult;
|
||||
|
||||
public class BlueSpark extends ThrowableProjectile {
|
||||
public BlueSpark(EntityType<? extends BlueSpark> p_37391_, Level p_37392_) {
|
||||
super(p_37391_, p_37392_);
|
||||
|
||||
}
|
||||
public BlueSpark(Level p_37399_, LivingEntity p_37400_) {
|
||||
super(TFMGEntityTypes.SPARK.get(), p_37400_, p_37399_);
|
||||
}
|
||||
|
||||
public BlueSpark(Level p_37394_, double p_37395_, double p_37396_, double p_37397_) {
|
||||
super(TFMGEntityTypes.BLUE_SPARK.get(), p_37395_, p_37396_, p_37397_, p_37394_);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected float getGravity(){
|
||||
return 0.02f;
|
||||
}
|
||||
@Override
|
||||
protected void defineSynchedData() {}
|
||||
|
||||
public void tick(){
|
||||
super.tick();
|
||||
if (this.isInWaterOrRain()) {
|
||||
this.discard();
|
||||
}
|
||||
if(this.level().isClientSide) {
|
||||
|
||||
CubeParticleData data =
|
||||
new CubeParticleData(4.1f, 60.2f, 100.3f, .0125f + .0625f * random.nextFloat(), 30, false);
|
||||
level().addParticle(data, this.getX(), this.getY(), this.getZ(), this.random.nextGaussian() * 0.05D, -this.getDeltaMovement().y * 0.5D, this.random.nextGaussian() * 0.05D);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private ParticleOptions getParticle() {
|
||||
|
||||
return ParticleTypes.FLAME;
|
||||
}
|
||||
|
||||
public void handleEntityEvent(byte p_37402_) {
|
||||
if (p_37402_ == 3) {
|
||||
ParticleOptions particleoptions = this.getParticle();
|
||||
|
||||
for(int i = 0; i < 8; ++i) {
|
||||
this.level().addParticle(particleoptions, this.getX(), this.getY(), this.getZ(), 0.0D, 0.0D, 0.0D);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
protected void onHitBlock(BlockHitResult p_37384_) {
|
||||
super.onHitBlock(p_37384_);
|
||||
if (!this.level().isClientSide) {
|
||||
Entity entity = this.getOwner();
|
||||
if (!(entity instanceof Mob) || net.minecraftforge.event.ForgeEventFactory.getMobGriefingEvent(this.level(), this)) {
|
||||
BlockPos blockpos = p_37384_.getBlockPos().relative(p_37384_.getDirection());
|
||||
if (this.level().isEmptyBlock(blockpos)) {
|
||||
this.level().setBlockAndUpdate(blockpos, BlueFireBlock.getState(this.level(), blockpos));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
protected void onHitEntity(EntityHitResult p_37386_) {
|
||||
super.onHitEntity(p_37386_);
|
||||
if (!this.level().isClientSide) {
|
||||
Entity entity = p_37386_.getEntity();
|
||||
Entity entity1 = this.getOwner();
|
||||
int i = entity.getRemainingFireTicks();
|
||||
entity.setSecondsOnFire(10);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
protected void onHit(HitResult p_37406_) {
|
||||
super.onHit(p_37406_);
|
||||
|
||||
if (!this.level().isClientSide) {
|
||||
this.level().broadcastEntityEvent(this, (byte)3);
|
||||
|
||||
|
||||
//this.level.explode(this, this.getX(), this.getY(0.0625D), this.getZ(), 2.0F, Explosion.BlockInteraction.NONE);
|
||||
this.discard();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static EntityType.Builder<?> build(EntityType.Builder<?> builder) {
|
||||
EntityType.Builder<BlueSpark> entityBuilder = (EntityType.Builder<BlueSpark>) builder;
|
||||
return entityBuilder.sized(.25f, .25f);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package com.drmangotea.tfmg.base.spark;
|
||||
|
||||
|
||||
import com.drmangotea.tfmg.TFMG;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||
import com.mojang.math.Axis;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.client.renderer.entity.EntityRenderer;
|
||||
import net.minecraft.client.renderer.entity.EntityRendererProvider;
|
||||
import net.minecraft.client.renderer.texture.OverlayTexture;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
import org.joml.Matrix3f;
|
||||
import org.joml.Matrix4f;
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public class BlueSparkRenderer extends EntityRenderer<BlueSpark> {
|
||||
private static final ResourceLocation TEXTURE_LOCATION = TFMG.asResource("textures/entity/blue_spark.png");
|
||||
private static final RenderType RENDER_TYPE = RenderType.entityCutoutNoCull(TEXTURE_LOCATION);
|
||||
public BlueSparkRenderer(EntityRendererProvider.Context p_173962_) {
|
||||
super(p_173962_);
|
||||
}
|
||||
|
||||
protected int getBlockLightLevel(BlueSpark p_114087_, BlockPos p_114088_) {
|
||||
return 15;
|
||||
}
|
||||
|
||||
public void render(BlueSpark p_114080_, float p_114081_, float p_114082_, PoseStack p_114083_, MultiBufferSource p_114084_, int p_114085_) {
|
||||
p_114083_.pushPose();
|
||||
p_114083_.scale(0.5F, 0.5F, 0.5F);
|
||||
p_114083_.mulPose(this.entityRenderDispatcher.cameraOrientation());
|
||||
p_114083_.mulPose(Axis.YP.rotationDegrees(180.0F));
|
||||
PoseStack.Pose posestack$pose = p_114083_.last();
|
||||
Matrix4f matrix4f = posestack$pose.pose();
|
||||
Matrix3f matrix3f = posestack$pose.normal();
|
||||
VertexConsumer vertexconsumer = p_114084_.getBuffer(RENDER_TYPE);
|
||||
vertex(vertexconsumer, matrix4f, matrix3f, p_114085_, 0.0F, 0, 0, 1);
|
||||
vertex(vertexconsumer, matrix4f, matrix3f, p_114085_, 1.0F, 0, 1, 1);
|
||||
vertex(vertexconsumer, matrix4f, matrix3f, p_114085_, 1.0F, 1, 1, 0);
|
||||
vertex(vertexconsumer, matrix4f, matrix3f, p_114085_, 0.0F, 1, 0, 0);
|
||||
p_114083_.popPose();
|
||||
super.render(p_114080_, p_114081_, p_114082_, p_114083_, p_114084_, p_114085_);
|
||||
}
|
||||
|
||||
private static void vertex(VertexConsumer p_114090_, Matrix4f p_114091_, Matrix3f p_114092_, int p_114093_, float p_114094_, int p_114095_, int p_114096_, int p_114097_) {
|
||||
p_114090_.vertex(p_114091_, p_114094_ - 0.5F, (float)p_114095_ - 0.25F, 0.0F).color(255, 255, 255, 255).uv((float)p_114096_, (float)p_114097_).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(p_114093_).normal(p_114092_, 0.0F, 1.0F, 0.0F).endVertex();
|
||||
}
|
||||
|
||||
public ResourceLocation getTextureLocation(BlueSpark p_114078_) {
|
||||
return TEXTURE_LOCATION;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package com.drmangotea.tfmg.base.spark;
|
||||
|
||||
|
||||
import com.drmangotea.tfmg.registry.TFMGParticleTypes;
|
||||
import com.simibubi.create.content.equipment.bell.BasicParticleData;
|
||||
import com.simibubi.create.content.equipment.bell.CustomRotationParticle;
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.client.particle.SpriteSet;
|
||||
import net.minecraft.core.particles.ParticleOptions;
|
||||
import net.minecraft.core.particles.ParticleType;
|
||||
|
||||
public class ElectricSparkParticle extends CustomRotationParticle {
|
||||
|
||||
private final SpriteSet animatedSprite;
|
||||
protected int startTicks;
|
||||
protected int endTicks;
|
||||
protected int numLoops;
|
||||
protected int startFrames = 17;
|
||||
protected int loopFrames = 16;
|
||||
protected int endFrames = 20;
|
||||
protected int totalFrames = 53;
|
||||
|
||||
public ElectricSparkParticle(ClientLevel worldIn, double x, double y, double z, double vx, double vy, double vz,
|
||||
SpriteSet spriteSet, ParticleOptions data) {
|
||||
super(worldIn, x, y, z, spriteSet, 0);
|
||||
this.animatedSprite = spriteSet;
|
||||
this.quadSize = 0.5f;
|
||||
this.setSize(this.quadSize, this.quadSize);
|
||||
|
||||
this.loopLength = loopFrames + (int) (this.random.nextFloat() * 5f - 4f);
|
||||
this.startTicks = startFrames + (int) (this.random.nextFloat() * 5f - 4f);
|
||||
this.endTicks = endFrames + (int) (this.random.nextFloat() * 5f - 4f);
|
||||
this.numLoops = (int) (1f + this.random.nextFloat() * 2f);
|
||||
|
||||
this.setFrame(0);
|
||||
this.mirror = this.random.nextBoolean();
|
||||
}
|
||||
public void setFrame(int frame) {
|
||||
if (frame >= 0 && frame < totalFrames)
|
||||
setSprite(animatedSprite.get(frame, totalFrames));
|
||||
}
|
||||
|
||||
public static class Data extends BasicParticleData<ElectricSparkParticle> {
|
||||
@Override
|
||||
public IBasicParticleFactory<ElectricSparkParticle> getBasicFactory() {
|
||||
return (worldIn, x, y, z, vx, vy, vz, spriteSet) -> new ElectricSparkParticle(worldIn, x, y, z, vx, vy, vz,
|
||||
spriteSet, this);
|
||||
}
|
||||
@Override
|
||||
public ParticleType<?> getType() {
|
||||
return TFMGParticleTypes.ELECTRIC_SPARK.get();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
103
src/main/java/com/drmangotea/tfmg/base/spark/GreenSpark.java
Normal file
103
src/main/java/com/drmangotea/tfmg/base/spark/GreenSpark.java
Normal file
@@ -0,0 +1,103 @@
|
||||
package com.drmangotea.tfmg.base.spark;
|
||||
|
||||
|
||||
|
||||
import com.drmangotea.tfmg.content.items.weapons.explosives.thermite_grenades.fire.GreenFireBlock;
|
||||
import com.drmangotea.tfmg.registry.TFMGEntityTypes;
|
||||
import com.drmangotea.tfmg.registry.TFMGItems;
|
||||
import com.simibubi.create.content.trains.CubeParticleData;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.particles.ParticleOptions;
|
||||
import net.minecraft.core.particles.ParticleTypes;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.Mob;
|
||||
import net.minecraft.world.entity.projectile.ThrowableProjectile;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.minecraft.world.phys.EntityHitResult;
|
||||
import net.minecraft.world.phys.HitResult;
|
||||
|
||||
public class GreenSpark extends ThrowableProjectile {
|
||||
public GreenSpark(EntityType<? extends GreenSpark> p_37391_, Level p_37392_) {
|
||||
super(p_37391_, p_37392_);
|
||||
}
|
||||
public GreenSpark(Level p_37399_, LivingEntity p_37400_) {
|
||||
super(TFMGEntityTypes.SPARK.get(), p_37400_, p_37399_);
|
||||
}
|
||||
|
||||
public GreenSpark(Level level, double p_37395_, double p_37396_, double p_37397_) {
|
||||
super(TFMGEntityTypes.SPARK.get(), p_37395_, p_37396_, p_37397_, level);
|
||||
}
|
||||
@Override
|
||||
protected float getGravity(){
|
||||
return 0.02f;
|
||||
}
|
||||
@Override
|
||||
protected void defineSynchedData() {}
|
||||
|
||||
public void tick(){
|
||||
super.tick();
|
||||
if (this.isInWaterOrRain()) {
|
||||
this.discard();
|
||||
}
|
||||
if(this.level().isClientSide) {
|
||||
|
||||
CubeParticleData data =
|
||||
new CubeParticleData(0.01f, 100.25f, 20.1f, .0125f + .0625f * random.nextFloat(), 30, true);
|
||||
level().addParticle(data, this.getX(), this.getY(), this.getZ(), this.random.nextGaussian() * 0.05D, -this.getDeltaMovement().y * 0.5D, this.random.nextGaussian() * 0.05D);
|
||||
}
|
||||
}
|
||||
|
||||
private ParticleOptions getParticle() {
|
||||
|
||||
return ParticleTypes.FLAME;
|
||||
}
|
||||
public void handleEntityEvent(byte p_37402_) {
|
||||
if (p_37402_ == 3) {
|
||||
ParticleOptions particleoptions = this.getParticle();
|
||||
|
||||
for(int i = 0; i < 8; ++i) {
|
||||
this.level().addParticle(particleoptions, this.getX(), this.getY(), this.getZ(), 0.0D, 0.0D, 0.0D);
|
||||
}
|
||||
}
|
||||
}
|
||||
protected void onHitBlock(BlockHitResult p_37384_) {
|
||||
super.onHitBlock(p_37384_);
|
||||
if (!this.level().isClientSide) {
|
||||
Entity entity = this.getOwner();
|
||||
if (!(entity instanceof Mob) || net.minecraftforge.event.ForgeEventFactory.getMobGriefingEvent(this.level(), this)) {
|
||||
BlockPos blockpos = p_37384_.getBlockPos().relative(p_37384_.getDirection());
|
||||
if (this.level().isEmptyBlock(blockpos)) {
|
||||
this.level().setBlockAndUpdate(blockpos, GreenFireBlock.getState(this.level(), blockpos));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
protected void onHitEntity(EntityHitResult p_37386_) {
|
||||
super.onHitEntity(p_37386_);
|
||||
if (!this.level().isClientSide) {
|
||||
Entity entity = p_37386_.getEntity();
|
||||
entity.setSecondsOnFire(10);
|
||||
}
|
||||
}
|
||||
|
||||
protected void onHit(HitResult p_37406_) {
|
||||
super.onHit(p_37406_);
|
||||
if (!this.level().isClientSide) {
|
||||
this.level().broadcastEntityEvent(this, (byte)3);
|
||||
this.discard();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static EntityType.Builder<?> build(EntityType.Builder<?> builder) {
|
||||
EntityType.Builder<GreenSpark> entityBuilder = (EntityType.Builder<GreenSpark>) builder;
|
||||
return entityBuilder.sized(.25f, .25f);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package com.drmangotea.tfmg.base.spark;
|
||||
|
||||
|
||||
import com.drmangotea.tfmg.TFMG;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||
import com.mojang.math.Axis;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.client.renderer.entity.EntityRenderer;
|
||||
import net.minecraft.client.renderer.entity.EntityRendererProvider;
|
||||
import net.minecraft.client.renderer.texture.OverlayTexture;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
import org.joml.Matrix3f;
|
||||
import org.joml.Matrix4f;
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public class GreenSparkRenderer extends EntityRenderer<GreenSpark> {
|
||||
private static final ResourceLocation TEXTURE_LOCATION = TFMG.asResource("textures/entity/green_spark.png");
|
||||
private static final RenderType RENDER_TYPE = RenderType.entityCutoutNoCull(TEXTURE_LOCATION);
|
||||
public GreenSparkRenderer(EntityRendererProvider.Context p_173962_) {
|
||||
super(p_173962_);
|
||||
}
|
||||
|
||||
protected int getBlockLightLevel(GreenSpark p_114087_, BlockPos p_114088_) {
|
||||
return 15;
|
||||
}
|
||||
|
||||
public void render(GreenSpark p_114080_, float p_114081_, float p_114082_, PoseStack p_114083_, MultiBufferSource p_114084_, int p_114085_) {
|
||||
p_114083_.pushPose();
|
||||
p_114083_.scale(0.5F, 0.5F, 0.5F);
|
||||
p_114083_.mulPose(this.entityRenderDispatcher.cameraOrientation());
|
||||
p_114083_.mulPose(Axis.YP.rotationDegrees(180.0F));
|
||||
PoseStack.Pose posestack$pose = p_114083_.last();
|
||||
Matrix4f matrix4f = posestack$pose.pose();
|
||||
Matrix3f matrix3f = posestack$pose.normal();
|
||||
VertexConsumer vertexconsumer = p_114084_.getBuffer(RENDER_TYPE);
|
||||
vertex(vertexconsumer, matrix4f, matrix3f, p_114085_, 0.0F, 0, 0, 1);
|
||||
vertex(vertexconsumer, matrix4f, matrix3f, p_114085_, 1.0F, 0, 1, 1);
|
||||
vertex(vertexconsumer, matrix4f, matrix3f, p_114085_, 1.0F, 1, 1, 0);
|
||||
vertex(vertexconsumer, matrix4f, matrix3f, p_114085_, 0.0F, 1, 0, 0);
|
||||
p_114083_.popPose();
|
||||
super.render(p_114080_, p_114081_, p_114082_, p_114083_, p_114084_, p_114085_);
|
||||
}
|
||||
|
||||
private static void vertex(VertexConsumer p_114090_, Matrix4f p_114091_, Matrix3f p_114092_, int p_114093_, float p_114094_, int p_114095_, int p_114096_, int p_114097_) {
|
||||
p_114090_.vertex(p_114091_, p_114094_ - 0.5F, (float)p_114095_ - 0.25F, 0.0F).color(255, 255, 255, 255).uv((float)p_114096_, (float)p_114097_).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(p_114093_).normal(p_114092_, 0.0F, 1.0F, 0.0F).endVertex();
|
||||
}
|
||||
|
||||
public ResourceLocation getTextureLocation(GreenSpark p_114078_) {
|
||||
return TEXTURE_LOCATION;
|
||||
}
|
||||
}
|
||||
100
src/main/java/com/drmangotea/tfmg/base/spark/Spark.java
Normal file
100
src/main/java/com/drmangotea/tfmg/base/spark/Spark.java
Normal file
@@ -0,0 +1,100 @@
|
||||
package com.drmangotea.tfmg.base.spark;
|
||||
|
||||
|
||||
import com.drmangotea.tfmg.registry.TFMGEntityTypes;
|
||||
import com.drmangotea.tfmg.registry.TFMGItems;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.particles.ParticleOptions;
|
||||
import net.minecraft.core.particles.ParticleTypes;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.Mob;
|
||||
import net.minecraft.world.entity.projectile.ThrowableProjectile;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.BaseFireBlock;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.minecraft.world.phys.EntityHitResult;
|
||||
import net.minecraft.world.phys.HitResult;
|
||||
|
||||
public class Spark extends ThrowableProjectile {
|
||||
public Spark(EntityType<? extends Spark> p_37391_, Level p_37392_) {
|
||||
super(p_37391_, p_37392_);
|
||||
}
|
||||
public Spark(Level p_37399_, LivingEntity p_37400_) {
|
||||
super(TFMGEntityTypes.SPARK.get(), p_37400_, p_37399_);
|
||||
}
|
||||
public Spark(Level p_37394_, double p_37395_, double p_37396_, double p_37397_) {
|
||||
super(TFMGEntityTypes.SPARK.get(), p_37395_, p_37396_, p_37397_, p_37394_);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float getGravity(){
|
||||
return 0.02f;
|
||||
}
|
||||
@Override
|
||||
protected void defineSynchedData() {}
|
||||
|
||||
public void tick(){
|
||||
super.tick();
|
||||
if (this.isInWaterOrRain()) {
|
||||
this.discard();
|
||||
}
|
||||
if(this.level().isClientSide) {
|
||||
|
||||
this.level().addParticle(ParticleTypes.FLAME, this.getX(), this.getY(), this.getZ(), this.random.nextGaussian() * 0.05D, -this.getDeltaMovement().y * 0.5D, this.random.nextGaussian() * 0.05D);
|
||||
}
|
||||
}
|
||||
protected Item getDefaultItem() {
|
||||
return TFMGItems.THERMITE_GRENADE.get();
|
||||
}
|
||||
private ParticleOptions getParticle() {
|
||||
return ParticleTypes.FLAME;
|
||||
}
|
||||
|
||||
public void handleEntityEvent(byte p_37402_) {
|
||||
if (p_37402_ == 3) {
|
||||
ParticleOptions particleoptions = this.getParticle();
|
||||
|
||||
for(int i = 0; i < 8; ++i) {
|
||||
this.level().addParticle(particleoptions, this.getX(), this.getY(), this.getZ(), 0.0D, 0.0D, 0.0D);
|
||||
}
|
||||
}
|
||||
}
|
||||
protected void onHitBlock(BlockHitResult p_37384_) {
|
||||
super.onHitBlock(p_37384_);
|
||||
if (!this.level().isClientSide) {
|
||||
Entity entity = this.getOwner();
|
||||
if (!(entity instanceof Mob) || net.minecraftforge.event.ForgeEventFactory.getMobGriefingEvent(this.level(), this)) {
|
||||
BlockPos blockpos = p_37384_.getBlockPos().relative(p_37384_.getDirection());
|
||||
if (this.level().isEmptyBlock(blockpos)) {
|
||||
this.level().setBlockAndUpdate(blockpos, BaseFireBlock.getState(this.level(), blockpos));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void onHitEntity(EntityHitResult p_37386_) {
|
||||
super.onHitEntity(p_37386_);
|
||||
if (!this.level().isClientSide) {
|
||||
Entity entity = p_37386_.getEntity();
|
||||
entity.setSecondsOnFire(10);
|
||||
}
|
||||
}
|
||||
|
||||
protected void onHit(HitResult p_37406_) {
|
||||
super.onHit(p_37406_);
|
||||
|
||||
if (!this.level().isClientSide) {
|
||||
this.level().broadcastEntityEvent(this, (byte)3);
|
||||
this.discard();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static EntityType.Builder<?> build(EntityType.Builder<?> builder) {
|
||||
EntityType.Builder<Spark> entityBuilder = (EntityType.Builder<Spark>) builder;
|
||||
return entityBuilder.sized(.25f, .25f);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package com.drmangotea.tfmg.base.spark;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||
import com.mojang.math.Axis;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.client.renderer.entity.EntityRenderer;
|
||||
import net.minecraft.client.renderer.entity.EntityRendererProvider;
|
||||
import net.minecraft.client.renderer.texture.OverlayTexture;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
import org.joml.Matrix3f;
|
||||
import org.joml.Matrix4f;
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public class SparkRenderer extends EntityRenderer<Spark> {
|
||||
private static final ResourceLocation TEXTURE_LOCATION = new ResourceLocation("textures/particle/lava.png");
|
||||
private static final RenderType RENDER_TYPE = RenderType.entityCutoutNoCull(TEXTURE_LOCATION);
|
||||
public SparkRenderer(EntityRendererProvider.Context p_173962_) {
|
||||
super(p_173962_);
|
||||
}
|
||||
|
||||
protected int getBlockLightLevel(Spark p_114087_, BlockPos p_114088_) {
|
||||
return 15;
|
||||
}
|
||||
|
||||
public void render(Spark p_114080_, float p_114081_, float p_114082_, PoseStack p_114083_, MultiBufferSource p_114084_, int p_114085_) {
|
||||
p_114083_.pushPose();
|
||||
p_114083_.scale(0.5F, 0.5F, 0.5F);
|
||||
p_114083_.mulPose(this.entityRenderDispatcher.cameraOrientation());
|
||||
p_114083_.mulPose(Axis.YP.rotationDegrees(180.0F));
|
||||
PoseStack.Pose posestack$pose = p_114083_.last();
|
||||
Matrix4f matrix4f = posestack$pose.pose();
|
||||
Matrix3f matrix3f = posestack$pose.normal();
|
||||
VertexConsumer vertexconsumer = p_114084_.getBuffer(RENDER_TYPE);
|
||||
vertex(vertexconsumer, matrix4f, matrix3f, p_114085_, 0.0F, 0, 0, 1);
|
||||
vertex(vertexconsumer, matrix4f, matrix3f, p_114085_, 1.0F, 0, 1, 1);
|
||||
vertex(vertexconsumer, matrix4f, matrix3f, p_114085_, 1.0F, 1, 1, 0);
|
||||
vertex(vertexconsumer, matrix4f, matrix3f, p_114085_, 0.0F, 1, 0, 0);
|
||||
p_114083_.popPose();
|
||||
super.render(p_114080_, p_114081_, p_114082_, p_114083_, p_114084_, p_114085_);
|
||||
}
|
||||
private static void vertex(VertexConsumer p_114090_, Matrix4f p_114091_, Matrix3f p_114092_, int p_114093_, float p_114094_, int p_114095_, int p_114096_, int p_114097_) {
|
||||
p_114090_.vertex(p_114091_, p_114094_ - 0.5F, (float)p_114095_ - 0.25F, 0.0F).color(255, 255, 255, 255).uv((float)p_114096_, (float)p_114097_).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(p_114093_).normal(p_114092_, 0.0F, 1.0F, 0.0F).endVertex();
|
||||
}
|
||||
public ResourceLocation getTextureLocation(Spark p_114078_) {
|
||||
return TEXTURE_LOCATION;
|
||||
}
|
||||
}
|
||||
18
src/main/java/com/drmangotea/tfmg/config/DepositConfig.java
Normal file
18
src/main/java/com/drmangotea/tfmg/config/DepositConfig.java
Normal file
@@ -0,0 +1,18 @@
|
||||
package com.drmangotea.tfmg.config;
|
||||
|
||||
import com.simibubi.create.foundation.config.ConfigBase;
|
||||
|
||||
public class DepositConfig extends ConfigBase {
|
||||
|
||||
|
||||
public final ConfigInt depositMaxReserves = i(10000, 1000, "depositMaxReserves", Comments.depositMaxReserves);
|
||||
public final ConfigBool infiniteDeposits = b(false, "infiniteDeposits", Comments.infiniteDeposits);
|
||||
@Override
|
||||
public String getName() {
|
||||
return "deposits";
|
||||
}
|
||||
private static class Comments {
|
||||
static String depositMaxReserves = "Sets the maximum oil reserves a deposit can have.";
|
||||
static String infiniteDeposits = "Makes deposits bottomless.";
|
||||
}
|
||||
}
|
||||
59
src/main/java/com/drmangotea/tfmg/config/MachineConfig.java
Normal file
59
src/main/java/com/drmangotea/tfmg/config/MachineConfig.java
Normal file
@@ -0,0 +1,59 @@
|
||||
package com.drmangotea.tfmg.config;
|
||||
|
||||
import com.simibubi.create.foundation.config.ConfigBase;
|
||||
|
||||
public class MachineConfig extends ConfigBase {
|
||||
|
||||
public final ConfigFloat largeGeneratorFeModifier = f(4, 0, "largeGeneratorFEModifier", Comments.largeGenerator);
|
||||
public final ConfigFloat smallGeneratorFeModifier = f(0.4f, 0, "smallGeneratorFEModifier", Comments.generator);
|
||||
public final ConfigInt blastFurnaceMaxHeight = i(10, 3, "blastFurnaceMaxHeight", Comments.blastFurnaceHeight);
|
||||
public final ConfigFloat blastFurnaceHeightSpeedModifier = f(1f, 0.1f, "blastFurnaceHeightSpeedModifier", Comments.blastFurnaceHeightSpeedModifier);
|
||||
public final ConfigInt blastFurnaceFuelConsumption = i(600, 1, "blastFurnaceFuelConsumption", Comments.blastFurnaceFuelConsumption);
|
||||
public final ConfigInt electricMotorMinimumPower = i(3000, 1, "electricMotorMinimumPower", Comments.electricMotorMinimumPower);
|
||||
public final ConfigInt electricMotorMinimumVoltage = i(150, 1, "electricMotorMinimumVoltage", Comments.electricMotorMinimumVoltage);
|
||||
public final ConfigFloat electricMotorPowerUsageModifier = f(1, 0, "electricMotorPowerUsageModifier", Comments.electricMotorPowerUsageModifier);
|
||||
public final ConfigInt cokeOvenMaxSize = i(5, 1, "cokeOvenMaxSize", Comments.cokeOvenMaxSize);
|
||||
public final ConfigInt accumulatorStorage = i(100000, 1, "accumulatorStorage", Comments.accumulatorStorage);
|
||||
public final ConfigInt accumulatorVoltage = i(12, 1, "accumulatorVoltage", Comments.accumulatorVoltage);
|
||||
public final ConfigInt accumulatorMaxAmpOutput = i(20, 1, "accumulatorMaxAmpOutput", Comments.accumulatorMaxAmpOutput);
|
||||
public final ConfigInt accumulatorChargingRate = i(100, 1, "accumulatorChargingRate", Comments.accumulatorChargingRate);
|
||||
public final ConfigFloat FEtoWattTickConversionRate = f(1, 0, "FEtoWattTickConversionRate", Comments.FEtoWattTickConversionRate);
|
||||
public final ConfigBool fireboxExhaustRequirement = b(true, "fireboxExhaustRequirement", Comments.fireboxExhaustRequirement);
|
||||
public final ConfigInt fireboxFuelConsumption = i(100, 1, "fireboxFuelConsumption", Comments.fireboxFuelConsumption);
|
||||
public final ConfigInt graphiteElectrodeCurrent = i(10, 1, "graphiteElectrodeCurrent", Comments.graphiteElectrodeCurrent);
|
||||
public final ConfigInt electrolysisMinimumCurrent = i(5, 1, "electrolysisMinimumCurrent", Comments.electrolysisMinimumCurrent);
|
||||
public final ConfigInt engineMaxLength = i(5, 1, "engineMaxLength", Comments.engineMaxLength);
|
||||
public final ConfigInt surfaceScannerScanDepth = i(-64, -512, "surfaceScannerScanDepth", Comments.surfaceScannerScanDepth);
|
||||
public final ConfigInt polarizerItemChargingRate = i(1000, 1, "polarizerItemChargingRate", Comments.polarizerItemChargingRate);
|
||||
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "machines";
|
||||
}
|
||||
|
||||
|
||||
private static class Comments {
|
||||
static String largeGenerator = "Changes the FE production of large generators.";
|
||||
static String generator = "Changes the FE production of small generators.";
|
||||
static String blastFurnaceHeight = "Changes the maximum height of the blast furnace.";
|
||||
static String blastFurnaceHeightSpeedModifier = "Sets the maximum time that can be saved by increasing blast furnace height.";
|
||||
static String blastFurnaceFuelConsumption = "Determines how many ticks does it take to consume one fuel.";
|
||||
static String electricMotorMinimumPower = "Determines the minimum power an electric motor can run on.";
|
||||
static String electricMotorMinimumVoltage = "Determines the minimum voltage an electric motor can run on.";
|
||||
static String electricMotorPowerUsageModifier = "Changes the power usage of electric motors.";
|
||||
static String cokeOvenMaxSize = "Determines the maximum size of coke ovens.";
|
||||
static String accumulatorStorage = "Determines the storage space of accumulators.";
|
||||
static String accumulatorVoltage = "Determines the voltage accumulators output.";
|
||||
static String accumulatorMaxAmpOutput = "Sets the maximum amperage an accumulator can provide.";
|
||||
static String accumulatorChargingRate = "Sets the maximum charging rate of accumulators.";
|
||||
static String fireboxExhaustRequirement = "If set to true,fireboxes will require exhaust management.";
|
||||
static String fireboxFuelConsumption = "Determines the amount of fuel a firebox needs to run for 3 seconds.";
|
||||
static String graphiteElectrodeCurrent = "The minimum electric current that will make graphite electrodes superheated.";
|
||||
static String electrolysisMinimumCurrent = "The minimum electric current that will make electrolyzers operational.";
|
||||
static String engineMaxLength = "The maximum length of engines.";
|
||||
static String surfaceScannerScanDepth = "Y level surface scanner scan at.";
|
||||
static String FEtoWattTickConversionRate = "How much Forge Energy is in one watt-tick.";
|
||||
static String polarizerItemChargingRate = "How much FE can polarizer charge per tick.";
|
||||
}
|
||||
}
|
||||
110
src/main/java/com/drmangotea/tfmg/config/StressConfig.java
Normal file
110
src/main/java/com/drmangotea/tfmg/config/StressConfig.java
Normal file
@@ -0,0 +1,110 @@
|
||||
package com.drmangotea.tfmg.config;
|
||||
|
||||
|
||||
import com.drmangotea.tfmg.TFMG;
|
||||
import com.simibubi.create.content.kinetics.BlockStressDefaults;
|
||||
import com.simibubi.create.content.kinetics.BlockStressValues.IStressValueProvider;
|
||||
import com.simibubi.create.foundation.config.ConfigBase;
|
||||
import com.simibubi.create.foundation.utility.Couple;
|
||||
import com.simibubi.create.foundation.utility.RegisteredObjects;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraftforge.common.ForgeConfigSpec.Builder;
|
||||
import net.minecraftforge.common.ForgeConfigSpec.ConfigValue;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class StressConfig extends ConfigBase implements IStressValueProvider {
|
||||
|
||||
private final Map<ResourceLocation, ConfigValue<Double>> capacities = new HashMap<>();
|
||||
private final Map<ResourceLocation, ConfigValue<Double>> impacts = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public void registerAll(Builder builder) {
|
||||
builder.comment(".", Comments.su, Comments.impact)
|
||||
.push("impact");
|
||||
BlockStressDefaults.DEFAULT_IMPACTS.forEach((r, i) -> {
|
||||
if (r.getNamespace()
|
||||
.equals(TFMG.MOD_ID))
|
||||
getImpacts().put(r, builder.define(r.getPath(), i));
|
||||
});
|
||||
builder.pop();
|
||||
|
||||
builder.comment(".", Comments.su, Comments.capacity)
|
||||
.push("capacity");
|
||||
BlockStressDefaults.DEFAULT_CAPACITIES.forEach((r, i) -> {
|
||||
if (r.getNamespace()
|
||||
.equals(TFMG.MOD_ID))
|
||||
getCapacities().put(r, builder.define(r.getPath(), i));
|
||||
});
|
||||
builder.pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "stressValues";
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getImpact(Block block) {
|
||||
block = redirectValues(block);
|
||||
ResourceLocation key = RegisteredObjects.getKeyOrThrow(block);
|
||||
ConfigValue<Double> value = getImpacts().get(key);
|
||||
if (value != null) return value.get();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getCapacity(Block block) {
|
||||
block = redirectValues(block);
|
||||
ResourceLocation key = RegisteredObjects.getKeyOrThrow(block);
|
||||
ConfigValue<Double> value = getCapacities().get(key);
|
||||
if (value != null) return value.get();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasImpact(Block block) {
|
||||
block = redirectValues(block);
|
||||
ResourceLocation key = RegisteredObjects.getKeyOrThrow(block);
|
||||
return getImpacts().containsKey(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasCapacity(Block block) {
|
||||
block = redirectValues(block);
|
||||
ResourceLocation key = RegisteredObjects.getKeyOrThrow(block);
|
||||
return getCapacities().containsKey(key);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Couple<Integer> getGeneratedRPM(Block block) {
|
||||
block = redirectValues(block);
|
||||
ResourceLocation key = RegisteredObjects.getKeyOrThrow(block);
|
||||
Supplier<Couple<Integer>> supplier = BlockStressDefaults.GENERATOR_SPEEDS.get(key);
|
||||
if (supplier == null) return null;
|
||||
return supplier.get();
|
||||
}
|
||||
|
||||
protected Block redirectValues(Block block) {
|
||||
return block;
|
||||
}
|
||||
|
||||
public Map<ResourceLocation, ConfigValue<Double>> getImpacts() {
|
||||
return impacts;
|
||||
}
|
||||
|
||||
public Map<ResourceLocation, ConfigValue<Double>> getCapacities() {
|
||||
return capacities;
|
||||
}
|
||||
|
||||
private static class Comments {
|
||||
static String su = "[in Stress Units]";
|
||||
static String impact = "Configure the individual stress impact of mechanical blocks. Note that this cost is doubled for every speed increase it receives";
|
||||
static String capacity = "Configure how much stress a source can accommodate for.";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.drmangotea.tfmg.config;
|
||||
|
||||
import com.simibubi.create.foundation.config.ConfigBase;
|
||||
|
||||
public class TFMGCommonConfig extends ConfigBase {
|
||||
|
||||
public final MachineConfig machines = nested(0, MachineConfig::new, "Config options for TFMG's machinery");
|
||||
public final DepositConfig deposits = nested(1, DepositConfig::new, "Oil Deposit Config");
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "common";
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
78
src/main/java/com/drmangotea/tfmg/config/TFMGConfigs.java
Normal file
78
src/main/java/com/drmangotea/tfmg/config/TFMGConfigs.java
Normal file
@@ -0,0 +1,78 @@
|
||||
package com.drmangotea.tfmg.config;
|
||||
|
||||
import com.simibubi.create.content.kinetics.BlockStressValues;
|
||||
import com.simibubi.create.foundation.config.ConfigBase;
|
||||
import com.simibubi.create.infrastructure.config.CCommon;
|
||||
import net.minecraftforge.common.ForgeConfigSpec;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import net.minecraftforge.fml.ModLoadingContext;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.config.ModConfig;
|
||||
import net.minecraftforge.fml.event.config.ModConfigEvent;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import java.util.EnumMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
@Mod.EventBusSubscriber(bus = Mod.EventBusSubscriber.Bus.MOD)
|
||||
public class TFMGConfigs {
|
||||
|
||||
private static final Map<ModConfig.Type, ConfigBase> CONFIGS = new EnumMap<>(ModConfig.Type.class);
|
||||
|
||||
private static TFMGServerConfig server;
|
||||
private static TFMGCommonConfig common;
|
||||
|
||||
|
||||
|
||||
public static TFMGServerConfig server() {
|
||||
return server;
|
||||
}
|
||||
|
||||
public static TFMGCommonConfig common() {
|
||||
return common;
|
||||
}
|
||||
|
||||
public static ConfigBase byType(ModConfig.Type type) {
|
||||
return CONFIGS.get(type);
|
||||
}
|
||||
|
||||
private static <T extends ConfigBase> T register(Supplier<T> factory, ModConfig.Type side) {
|
||||
Pair<T, ForgeConfigSpec> specPair = new ForgeConfigSpec.Builder().configure(builder -> {
|
||||
T config = factory.get();
|
||||
config.registerAll(builder);
|
||||
return config;
|
||||
});
|
||||
|
||||
T config = specPair.getLeft();
|
||||
config.specification = specPair.getRight();
|
||||
CONFIGS.put(side, config);
|
||||
return config;
|
||||
}
|
||||
@SuppressWarnings("removal")
|
||||
public static void register(ModLoadingContext context) {
|
||||
server = register(TFMGServerConfig::new, ModConfig.Type.SERVER);
|
||||
common = register(TFMGCommonConfig::new, ModConfig.Type.COMMON);
|
||||
for (Map.Entry<ModConfig.Type, ConfigBase> pair : CONFIGS.entrySet())
|
||||
context.registerConfig(pair.getKey(), pair.getValue().specification);
|
||||
|
||||
BlockStressValues.registerProvider(context.getActiveNamespace(), server().stressValues);
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onLoad(ModConfigEvent.Loading event) {
|
||||
for (ConfigBase config : CONFIGS.values())
|
||||
if (config.specification == event.getConfig()
|
||||
.getSpec())
|
||||
config.onLoad();
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onReload(ModConfigEvent.Reloading event) {
|
||||
for (ConfigBase config : CONFIGS.values())
|
||||
if (config.specification == event.getConfig()
|
||||
.getSpec())
|
||||
config.onReload();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.drmangotea.tfmg.config;
|
||||
|
||||
import com.simibubi.create.foundation.config.ConfigBase;
|
||||
|
||||
public class TFMGServerConfig extends ConfigBase {
|
||||
|
||||
|
||||
|
||||
public final StressConfig stressValues = nested(0, StressConfig::new, "Fine tune the kinetic stats of individual components");
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "server";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package com.drmangotea.tfmg.content.decoration;
|
||||
|
||||
import com.simibubi.create.foundation.block.ProperWaterloggedBlock;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.world.item.context.BlockPlaceContext;
|
||||
import net.minecraft.world.level.LevelAccessor;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.RotatedPillarBlock;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.StateDefinition;
|
||||
import net.minecraft.world.level.material.FluidState;
|
||||
|
||||
public class FrameBlock extends Block implements ProperWaterloggedBlock {
|
||||
|
||||
|
||||
|
||||
public FrameBlock(Properties p_55926_) {
|
||||
super(p_55926_);
|
||||
this.registerDefaultState(this.defaultBlockState().setValue(WATERLOGGED, false));
|
||||
}
|
||||
|
||||
|
||||
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> p_55933_) {
|
||||
p_55933_.add(WATERLOGGED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FluidState getFluidState(BlockState pState) {
|
||||
return fluidState(pState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState updateShape(BlockState pState, Direction pDirection, BlockState pNeighborState,
|
||||
LevelAccessor pLevel, BlockPos pCurrentPos, BlockPos pNeighborPos) {
|
||||
updateWater(pLevel, pState, pCurrentPos);
|
||||
return pState;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getStateForPlacement(BlockPlaceContext pContext) {
|
||||
return withWater(super.getStateForPlacement(pContext), pContext);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
package com.drmangotea.tfmg.content.decoration;
|
||||
|
||||
import com.drmangotea.tfmg.base.WallMountBlock;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Maps;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.core.particles.ParticleTypes;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.item.context.BlockPlaceContext;
|
||||
import net.minecraft.world.level.BlockGetter;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.LevelAccessor;
|
||||
import net.minecraft.world.level.LevelReader;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.SimpleWaterloggedBlock;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.StateDefinition;
|
||||
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
|
||||
import net.minecraft.world.level.block.state.properties.BooleanProperty;
|
||||
import net.minecraft.world.level.material.FluidState;
|
||||
import net.minecraft.world.level.material.Fluids;
|
||||
import net.minecraft.world.phys.shapes.CollisionContext;
|
||||
import net.minecraft.world.phys.shapes.VoxelShape;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
public class LithiumTorchBlock extends WallMountBlock implements SimpleWaterloggedBlock {
|
||||
|
||||
public static final BooleanProperty WATERLOGGED = BlockStateProperties.WATERLOGGED;
|
||||
|
||||
private static final Map<Direction, VoxelShape> SHAPE = Maps.newEnumMap(ImmutableMap.of(Direction.NORTH, Block.box(5.5D, 3.0D, 11.0D, 10.5D, 13.0D, 16.0D), Direction.SOUTH, Block.box(5.5D, 3.0D, 0.0D, 10.5D, 13.0D, 5.0D), Direction.WEST, Block.box(11.0D, 3.0D, 5.5D, 16.0D, 13.0D, 10.5D), Direction.EAST, Block.box(0.0D, 3.0D, 5.5D, 5.0D, 13.0D, 10.5D),Direction.UP,Block.box(6.0D, 0.0D, 6.0D, 10.0D, 10.0D, 10.0D),Direction.DOWN,Block.box(6.0D, 6.0D, 6.0D, 10.0D, 16.0D, 10.0D)));
|
||||
public LithiumTorchBlock(Properties pProperties) {
|
||||
super(pProperties);
|
||||
}
|
||||
|
||||
public VoxelShape getShape(BlockState pState, BlockGetter pLevel, BlockPos pPos, CollisionContext pContext) {
|
||||
|
||||
|
||||
return SHAPE.get(pState.getValue(FACING));
|
||||
}
|
||||
|
||||
@Override
|
||||
public FluidState getFluidState(BlockState p_51475_) {
|
||||
return p_51475_.getValue(WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(p_51475_);
|
||||
}
|
||||
|
||||
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> p_55125_) {
|
||||
p_55125_.add(WATERLOGGED,FACING);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void animateTick(BlockState pState, Level pLevel, BlockPos pPos, RandomSource pRandom) {
|
||||
Direction direction = pState.getValue(FACING);
|
||||
double d0 = (double)pPos.getX() + 0.5D;
|
||||
double d1 = (double)pPos.getY() + 0.7D;
|
||||
double d2 = (double)pPos.getZ() + 0.5D;
|
||||
double d3 = 0.22D;
|
||||
double d4 = 0.27D;
|
||||
Direction direction1 = direction.getOpposite();
|
||||
double y;
|
||||
if(direction == Direction.DOWN) {
|
||||
y = d1 - 0.22D * (double) direction1.getStepY();
|
||||
}else {
|
||||
y = d1 + 0.11D;
|
||||
}
|
||||
|
||||
|
||||
pLevel.addParticle(ParticleTypes.SMOKE, d0 + 0.27D * (double)direction1.getStepX(), y, d2 + 0.27D * (double)direction1.getStepZ(), 0.0D, 0.0D, 0.0D);
|
||||
pLevel.addParticle(ParticleTypes.FLAME, d0 + 0.27D * (double)direction1.getStepX(), y, d2 + 0.27D * (double)direction1.getStepZ(), 0.0D, 0.0D, 0.0D);
|
||||
}
|
||||
public BlockState updateShape(BlockState pState, Direction pFacing, BlockState pFacingState, LevelAccessor pLevel, BlockPos pCurrentPos, BlockPos pFacingPos) {
|
||||
|
||||
if (pState.getValue(WATERLOGGED)) {
|
||||
pLevel.scheduleTick(pCurrentPos, Fluids.WATER, Fluids.WATER.getTickDelay(pLevel));
|
||||
}
|
||||
|
||||
return !this.canSurvive(pState, pLevel, pCurrentPos) ? Blocks.AIR.defaultBlockState() : pState;
|
||||
}
|
||||
|
||||
|
||||
public boolean canSurvive(BlockState pState, LevelReader pLevel, BlockPos pPos) {
|
||||
Direction direction = pState.getValue(FACING);
|
||||
BlockPos blockpos = pPos.relative(direction.getOpposite());
|
||||
BlockState blockstate = pLevel.getBlockState(blockpos);
|
||||
return blockstate.isFaceSturdy(pLevel, blockpos, direction);
|
||||
}
|
||||
|
||||
public BlockState getStateForPlacement(BlockPlaceContext pContext) {
|
||||
|
||||
FluidState fluidstate = pContext.getLevel().getFluidState(pContext.getClickedPos());
|
||||
boolean flag = fluidstate.getType() == Fluids.WATER;
|
||||
|
||||
return this.defaultBlockState().setValue(FACING, pContext.getClickedFace()).setValue(WATERLOGGED,flag);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.drmangotea.tfmg.content.decoration;
|
||||
|
||||
import com.drmangotea.tfmg.base.WallMountBlock;
|
||||
import com.simibubi.create.foundation.data.SpecialBlockStateGen;
|
||||
import com.tterrag.registrate.providers.DataGenContext;
|
||||
import com.tterrag.registrate.providers.RegistrateBlockstateProvider;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraftforge.client.model.generators.ModelFile;
|
||||
|
||||
import static com.simibubi.create.foundation.data.AssetLookup.partialBaseModel;
|
||||
|
||||
public class LithiumTorchGenerator extends SpecialBlockStateGen {
|
||||
|
||||
@Override
|
||||
protected int getXRotation(BlockState state) {
|
||||
return state.getValue(LithiumTorchBlock.FACING)== Direction.DOWN ? 180 : 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getYRotation(BlockState state) {
|
||||
return switch (state.getValue(WallMountBlock.FACING)) {
|
||||
case NORTH -> 270;
|
||||
case SOUTH -> 90;
|
||||
case WEST -> 180;
|
||||
case EAST -> 0;
|
||||
case DOWN -> 0;
|
||||
case UP -> 0;
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends Block> ModelFile getModel(DataGenContext<Block, T> ctx, RegistrateBlockstateProvider prov,
|
||||
BlockState state) {
|
||||
|
||||
|
||||
return state.getValue(WallMountBlock.FACING).getAxis().isHorizontal() ? partialBaseModel(ctx, prov, "wall")
|
||||
: partialBaseModel(ctx, prov);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package com.drmangotea.tfmg.content.decoration;
|
||||
|
||||
import com.simibubi.create.foundation.block.ProperWaterloggedBlock;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.world.item.context.BlockPlaceContext;
|
||||
import net.minecraft.world.level.LevelAccessor;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.RotatedPillarBlock;
|
||||
import net.minecraft.world.level.block.Rotation;
|
||||
import net.minecraft.world.level.block.SimpleWaterloggedBlock;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.StateDefinition;
|
||||
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
|
||||
import net.minecraft.world.level.block.state.properties.BooleanProperty;
|
||||
import net.minecraft.world.level.block.state.properties.EnumProperty;
|
||||
import net.minecraft.world.level.material.FluidState;
|
||||
import net.minecraft.world.level.material.Fluids;
|
||||
|
||||
public class TrussBlock extends RotatedPillarBlock implements ProperWaterloggedBlock {
|
||||
|
||||
|
||||
|
||||
public TrussBlock(Properties p_55926_) {
|
||||
super(p_55926_);
|
||||
this.registerDefaultState(this.defaultBlockState().setValue(AXIS, Direction.Axis.Y).setValue(WATERLOGGED, false));
|
||||
}
|
||||
|
||||
|
||||
|
||||
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> p_55933_) {
|
||||
p_55933_.add(WATERLOGGED, AXIS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FluidState getFluidState(BlockState pState) {
|
||||
return fluidState(pState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState updateShape(BlockState pState, Direction pDirection, BlockState pNeighborState,
|
||||
LevelAccessor pLevel, BlockPos pCurrentPos, BlockPos pNeighborPos) {
|
||||
updateWater(pLevel, pState, pCurrentPos);
|
||||
return pState;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getStateForPlacement(BlockPlaceContext pContext) {
|
||||
return withWater(super.getStateForPlacement(pContext), pContext);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
package com.drmangotea.tfmg.content.decoration.cogs;
|
||||
|
||||
import com.drmangotea.tfmg.registry.TFMGPartialModels;
|
||||
import com.jozufozu.flywheel.api.InstanceData;
|
||||
import com.jozufozu.flywheel.api.Instancer;
|
||||
import com.jozufozu.flywheel.api.Material;
|
||||
import com.jozufozu.flywheel.api.MaterialManager;
|
||||
import com.jozufozu.flywheel.core.PartialModel;
|
||||
import com.jozufozu.flywheel.util.transform.TransformStack;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.math.Axis;
|
||||
import com.simibubi.create.AllPartialModels;
|
||||
import com.simibubi.create.content.kinetics.base.IRotate;
|
||||
import com.simibubi.create.content.kinetics.base.KineticBlockEntity;
|
||||
import com.simibubi.create.content.kinetics.base.KineticBlockEntityInstance;
|
||||
import com.simibubi.create.content.kinetics.base.flwdata.RotatingData;
|
||||
import com.simibubi.create.content.kinetics.simpleRelays.BracketedKineticBlockEntityRenderer;
|
||||
import com.simibubi.create.foundation.render.AllMaterialSpecs;
|
||||
import com.simibubi.create.foundation.utility.Iterate;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public class EncasedAluminumCogInstance extends KineticBlockEntityInstance<KineticBlockEntity> {
|
||||
|
||||
private boolean large;
|
||||
|
||||
protected RotatingData rotatingModel;
|
||||
protected Optional<RotatingData> rotatingTopShaft;
|
||||
protected Optional<RotatingData> rotatingBottomShaft;
|
||||
|
||||
public static EncasedAluminumCogInstance small(MaterialManager modelManager, KineticBlockEntity blockEntity) {
|
||||
return new EncasedAluminumCogInstance(modelManager, blockEntity, false);
|
||||
}
|
||||
|
||||
public static EncasedAluminumCogInstance large(MaterialManager modelManager, KineticBlockEntity blockEntity) {
|
||||
return new EncasedAluminumCogInstance(modelManager, blockEntity, true);
|
||||
}
|
||||
|
||||
public EncasedAluminumCogInstance(MaterialManager modelManager, KineticBlockEntity blockEntity, boolean large) {
|
||||
super(modelManager, blockEntity);
|
||||
this.large = large;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
rotatingModel = setup(getCogModel().createInstance());
|
||||
|
||||
Block block = blockState.getBlock();
|
||||
if (!(block instanceof IRotate))
|
||||
return;
|
||||
|
||||
IRotate def = (IRotate) block;
|
||||
rotatingTopShaft = Optional.empty();
|
||||
rotatingBottomShaft = Optional.empty();
|
||||
|
||||
for (Direction d : Iterate.directionsInAxis(axis)) {
|
||||
if (!def.hasShaftTowards(blockEntity.getLevel(), blockEntity.getBlockPos(), blockState, d))
|
||||
continue;
|
||||
RotatingData data = setup(getRotatingMaterial().getModel(AllPartialModels.SHAFT_HALF, blockState, d)
|
||||
.createInstance());
|
||||
if (large)
|
||||
data.setRotationOffset(BracketedKineticBlockEntityRenderer.getShaftAngleOffset(axis, pos));
|
||||
if (d.getAxisDirection() == Direction.AxisDirection.POSITIVE)
|
||||
rotatingTopShaft = Optional.of(data);
|
||||
else
|
||||
rotatingBottomShaft = Optional.of(data);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update() {
|
||||
updateRotation(rotatingModel);
|
||||
rotatingTopShaft.ifPresent(this::updateRotation);
|
||||
rotatingBottomShaft.ifPresent(this::updateRotation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateLight() {
|
||||
relight(pos, rotatingModel);
|
||||
rotatingTopShaft.ifPresent(d -> relight(pos, d));
|
||||
rotatingBottomShaft.ifPresent(d -> relight(pos, d));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
rotatingModel.delete();
|
||||
rotatingTopShaft.ifPresent(InstanceData::delete);
|
||||
rotatingBottomShaft.ifPresent(InstanceData::delete);
|
||||
}
|
||||
|
||||
protected Instancer<RotatingData> getCogModel() {
|
||||
BlockState referenceState = blockEntity.getBlockState();
|
||||
Direction facing =
|
||||
Direction.fromAxisAndDirection(referenceState.getValue(BlockStateProperties.AXIS), Direction.AxisDirection.POSITIVE);
|
||||
PartialModel partial = large ? TFMGPartialModels.LARGE_ALUMINUM_COGHWEEL : TFMGPartialModels.ALUMINUM_COGHWEEL;
|
||||
|
||||
return getCutoutRotatingMaterial().getModel(partial, referenceState, facing, () -> {
|
||||
PoseStack poseStack = new PoseStack();
|
||||
TransformStack.cast(poseStack)
|
||||
.centre()
|
||||
.rotateToFace(facing)
|
||||
.multiply(Axis.XN.rotationDegrees(90))
|
||||
.unCentre();
|
||||
return poseStack;
|
||||
});
|
||||
}
|
||||
|
||||
protected Material<RotatingData> getCutoutRotatingMaterial() {
|
||||
return materialManager.defaultCutout()
|
||||
.material(AllMaterialSpecs.ROTATING);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package com.drmangotea.tfmg.content.decoration.cogs;
|
||||
|
||||
import com.drmangotea.tfmg.registry.TFMGPartialModels;
|
||||
import com.jozufozu.flywheel.backend.Backend;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.simibubi.create.AllPartialModels;
|
||||
import com.simibubi.create.content.kinetics.base.IRotate;
|
||||
import com.simibubi.create.content.kinetics.base.KineticBlockEntityRenderer;
|
||||
import com.simibubi.create.content.kinetics.simpleRelays.BracketedKineticBlockEntityRenderer;
|
||||
import com.simibubi.create.content.kinetics.simpleRelays.SimpleKineticBlockEntity;
|
||||
import com.simibubi.create.content.kinetics.simpleRelays.encased.EncasedCogwheelBlock;
|
||||
import com.simibubi.create.foundation.render.CachedBufferer;
|
||||
import com.simibubi.create.foundation.render.SuperByteBuffer;
|
||||
import com.simibubi.create.foundation.utility.Iterate;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
|
||||
public class EncasedAluminumCogRenderer extends KineticBlockEntityRenderer<SimpleKineticBlockEntity> {
|
||||
|
||||
private boolean large;
|
||||
|
||||
public static EncasedAluminumCogRenderer small(BlockEntityRendererProvider.Context context) {
|
||||
return new EncasedAluminumCogRenderer(context, false);
|
||||
}
|
||||
|
||||
public static EncasedAluminumCogRenderer large(BlockEntityRendererProvider.Context context) {
|
||||
return new EncasedAluminumCogRenderer(context, true);
|
||||
}
|
||||
|
||||
public EncasedAluminumCogRenderer(BlockEntityRendererProvider.Context context, boolean large) {
|
||||
super(context);
|
||||
this.large = large;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderSafe(SimpleKineticBlockEntity be, float partialTicks, PoseStack ms, MultiBufferSource buffer,
|
||||
int light, int overlay) {
|
||||
super.renderSafe(be, partialTicks, ms, buffer, light, overlay);
|
||||
if (Backend.canUseInstancing(be.getLevel()))
|
||||
return;
|
||||
|
||||
BlockState blockState = be.getBlockState();
|
||||
Block block = blockState.getBlock();
|
||||
if (!(block instanceof IRotate))
|
||||
return;
|
||||
IRotate def = (IRotate) block;
|
||||
|
||||
Direction.Axis axis = getRotationAxisOf(be);
|
||||
BlockPos pos = be.getBlockPos();
|
||||
float angle = large ? BracketedKineticBlockEntityRenderer.getAngleForLargeCogShaft(be, axis)
|
||||
: getAngleForTe(be, pos, axis);
|
||||
|
||||
for (Direction d : Iterate.directionsInAxis(getRotationAxisOf(be))) {
|
||||
if (!def.hasShaftTowards(be.getLevel(), be.getBlockPos(), blockState, d))
|
||||
continue;
|
||||
SuperByteBuffer shaft = CachedBufferer.partialFacing(AllPartialModels.SHAFT_HALF, be.getBlockState(), d);
|
||||
kineticRotationTransform(shaft, be, axis, angle, light);
|
||||
shaft.renderInto(ms, buffer.getBuffer(RenderType.cutoutMipped()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SuperByteBuffer getRotatedModel(SimpleKineticBlockEntity be, BlockState state) {
|
||||
return CachedBufferer.partialFacingVertical(
|
||||
large ? TFMGPartialModels.LARGE_ALUMINUM_COGHWEEL : TFMGPartialModels.ALUMINUM_COGHWEEL, state,
|
||||
Direction.fromAxisAndDirection(state.getValue(EncasedCogwheelBlock.AXIS), Direction.AxisDirection.POSITIVE));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
package com.drmangotea.tfmg.content.decoration.cogs;
|
||||
|
||||
import com.drmangotea.tfmg.registry.TFMGPartialModels;
|
||||
import com.jozufozu.flywheel.api.InstanceData;
|
||||
import com.jozufozu.flywheel.api.Instancer;
|
||||
import com.jozufozu.flywheel.api.MaterialManager;
|
||||
import com.jozufozu.flywheel.core.PartialModel;
|
||||
import com.jozufozu.flywheel.util.transform.TransformStack;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.math.Axis;
|
||||
import com.simibubi.create.AllPartialModels;
|
||||
import com.simibubi.create.content.kinetics.base.IRotate;
|
||||
import com.simibubi.create.content.kinetics.base.KineticBlockEntity;
|
||||
import com.simibubi.create.content.kinetics.base.KineticBlockEntityInstance;
|
||||
import com.simibubi.create.content.kinetics.base.flwdata.RotatingData;
|
||||
import com.simibubi.create.content.kinetics.simpleRelays.BracketedKineticBlockEntityRenderer;
|
||||
import com.simibubi.create.foundation.utility.Iterate;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public class EncasedSteelCogInstance extends KineticBlockEntityInstance<KineticBlockEntity> {
|
||||
|
||||
private boolean large;
|
||||
|
||||
protected RotatingData rotatingModel;
|
||||
protected Optional<RotatingData> rotatingTopShaft;
|
||||
protected Optional<RotatingData> rotatingBottomShaft;
|
||||
|
||||
public static EncasedSteelCogInstance small(MaterialManager modelManager, KineticBlockEntity blockEntity) {
|
||||
return new EncasedSteelCogInstance(modelManager, blockEntity, false);
|
||||
}
|
||||
|
||||
public static EncasedSteelCogInstance large(MaterialManager modelManager, KineticBlockEntity blockEntity) {
|
||||
return new EncasedSteelCogInstance(modelManager, blockEntity, true);
|
||||
}
|
||||
|
||||
public EncasedSteelCogInstance(MaterialManager modelManager, KineticBlockEntity blockEntity, boolean large) {
|
||||
super(modelManager, blockEntity);
|
||||
this.large = large;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
rotatingModel = setup(getCogModel().createInstance());
|
||||
|
||||
Block block = blockState.getBlock();
|
||||
if (!(block instanceof IRotate))
|
||||
return;
|
||||
|
||||
IRotate def = (IRotate) block;
|
||||
rotatingTopShaft = Optional.empty();
|
||||
rotatingBottomShaft = Optional.empty();
|
||||
|
||||
for (Direction d : Iterate.directionsInAxis(axis)) {
|
||||
if (!def.hasShaftTowards(blockEntity.getLevel(), blockEntity.getBlockPos(), blockState, d))
|
||||
continue;
|
||||
RotatingData data = setup(getRotatingMaterial().getModel(AllPartialModels.SHAFT_HALF, blockState, d)
|
||||
.createInstance());
|
||||
if (large)
|
||||
data.setRotationOffset(BracketedKineticBlockEntityRenderer.getShaftAngleOffset(axis, pos));
|
||||
if (d.getAxisDirection() == Direction.AxisDirection.POSITIVE)
|
||||
rotatingTopShaft = Optional.of(data);
|
||||
else
|
||||
rotatingBottomShaft = Optional.of(data);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update() {
|
||||
updateRotation(rotatingModel);
|
||||
rotatingTopShaft.ifPresent(this::updateRotation);
|
||||
rotatingBottomShaft.ifPresent(this::updateRotation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateLight() {
|
||||
relight(pos, rotatingModel);
|
||||
rotatingTopShaft.ifPresent(d -> relight(pos, d));
|
||||
rotatingBottomShaft.ifPresent(d -> relight(pos, d));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
rotatingModel.delete();
|
||||
rotatingTopShaft.ifPresent(InstanceData::delete);
|
||||
rotatingBottomShaft.ifPresent(InstanceData::delete);
|
||||
}
|
||||
|
||||
protected Instancer<RotatingData> getCogModel() {
|
||||
BlockState referenceState = blockEntity.getBlockState();
|
||||
Direction facing =
|
||||
Direction.fromAxisAndDirection(referenceState.getValue(BlockStateProperties.AXIS), Direction.AxisDirection.POSITIVE);
|
||||
PartialModel partial = large ? TFMGPartialModels.LARGE_STEEL_COGHWEEL : TFMGPartialModels.STEEL_COGHWEEL;
|
||||
|
||||
return getRotatingMaterial().getModel(partial, referenceState, facing, () -> {
|
||||
PoseStack poseStack = new PoseStack();
|
||||
TransformStack.cast(poseStack)
|
||||
.centre()
|
||||
.rotateToFace(facing)
|
||||
.multiply(Axis.XN.rotationDegrees(90))
|
||||
.unCentre();
|
||||
return poseStack;
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package com.drmangotea.tfmg.content.decoration.cogs;
|
||||
|
||||
import com.drmangotea.tfmg.registry.TFMGPartialModels;
|
||||
import com.jozufozu.flywheel.backend.Backend;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.simibubi.create.AllPartialModels;
|
||||
import com.simibubi.create.content.kinetics.base.IRotate;
|
||||
import com.simibubi.create.content.kinetics.base.KineticBlockEntityRenderer;
|
||||
import com.simibubi.create.content.kinetics.simpleRelays.BracketedKineticBlockEntityRenderer;
|
||||
import com.simibubi.create.content.kinetics.simpleRelays.SimpleKineticBlockEntity;
|
||||
import com.simibubi.create.content.kinetics.simpleRelays.encased.EncasedCogwheelBlock;
|
||||
import com.simibubi.create.foundation.render.CachedBufferer;
|
||||
import com.simibubi.create.foundation.render.SuperByteBuffer;
|
||||
import com.simibubi.create.foundation.utility.Iterate;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
|
||||
public class EncasedSteelCogRenderer extends KineticBlockEntityRenderer<SimpleKineticBlockEntity> {
|
||||
|
||||
private boolean large;
|
||||
|
||||
public static EncasedSteelCogRenderer small(BlockEntityRendererProvider.Context context) {
|
||||
return new EncasedSteelCogRenderer(context, false);
|
||||
}
|
||||
|
||||
public static EncasedSteelCogRenderer large(BlockEntityRendererProvider.Context context) {
|
||||
return new EncasedSteelCogRenderer(context, true);
|
||||
}
|
||||
|
||||
public EncasedSteelCogRenderer(BlockEntityRendererProvider.Context context, boolean large) {
|
||||
super(context);
|
||||
this.large = large;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderSafe(SimpleKineticBlockEntity be, float partialTicks, PoseStack ms, MultiBufferSource buffer,
|
||||
int light, int overlay) {
|
||||
super.renderSafe(be, partialTicks, ms, buffer, light, overlay);
|
||||
if (Backend.canUseInstancing(be.getLevel()))
|
||||
return;
|
||||
|
||||
BlockState blockState = be.getBlockState();
|
||||
Block block = blockState.getBlock();
|
||||
if (!(block instanceof IRotate))
|
||||
return;
|
||||
IRotate def = (IRotate) block;
|
||||
|
||||
Direction.Axis axis = getRotationAxisOf(be);
|
||||
BlockPos pos = be.getBlockPos();
|
||||
float angle = large ? BracketedKineticBlockEntityRenderer.getAngleForLargeCogShaft(be, axis)
|
||||
: getAngleForTe(be, pos, axis);
|
||||
for (Direction d : Iterate.directionsInAxis(getRotationAxisOf(be))) {
|
||||
if (!def.hasShaftTowards(be.getLevel(), be.getBlockPos(), blockState, d))
|
||||
continue;
|
||||
SuperByteBuffer shaft = CachedBufferer.partialFacing(AllPartialModels.SHAFT_HALF, be.getBlockState(), d);
|
||||
kineticRotationTransform(shaft, be, axis, angle, light);
|
||||
shaft.renderInto(ms, buffer.getBuffer(RenderType.cutoutMipped()));
|
||||
}
|
||||
}
|
||||
@Override
|
||||
protected SuperByteBuffer getRotatedModel(SimpleKineticBlockEntity be, BlockState state) {
|
||||
return CachedBufferer.partialFacingVertical(
|
||||
large ? TFMGPartialModels.LARGE_STEEL_COGHWEEL : TFMGPartialModels.STEEL_COGHWEEL, state,
|
||||
Direction.fromAxisAndDirection(state.getValue(EncasedCogwheelBlock.AXIS), Direction.AxisDirection.POSITIVE));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,208 @@
|
||||
package com.drmangotea.tfmg.content.decoration.cogs;
|
||||
|
||||
import com.drmangotea.tfmg.registry.TFMGBlockEntities;
|
||||
import com.simibubi.create.AllBlocks;
|
||||
import com.simibubi.create.AllShapes;
|
||||
import com.simibubi.create.content.decoration.encasing.EncasableBlock;
|
||||
import com.simibubi.create.content.kinetics.base.IRotate;
|
||||
import com.simibubi.create.content.kinetics.base.KineticBlockEntity;
|
||||
import com.simibubi.create.content.kinetics.simpleRelays.AbstractSimpleShaftBlock;
|
||||
import com.simibubi.create.content.kinetics.simpleRelays.ICogWheel;
|
||||
import com.simibubi.create.content.kinetics.speedController.SpeedControllerBlock;
|
||||
import com.simibubi.create.foundation.advancement.AllAdvancements;
|
||||
import com.simibubi.create.foundation.utility.Iterate;
|
||||
import net.minecraft.MethodsReturnNonnullByDefault;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.InteractionResult;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.context.BlockPlaceContext;
|
||||
import net.minecraft.world.level.BlockGetter;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.LevelReader;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
|
||||
import net.minecraft.world.level.material.Fluids;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.minecraft.world.phys.shapes.CollisionContext;
|
||||
import net.minecraft.world.phys.shapes.VoxelShape;
|
||||
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
|
||||
import static net.minecraft.core.Direction.Axis;
|
||||
|
||||
@ParametersAreNonnullByDefault
|
||||
@MethodsReturnNonnullByDefault
|
||||
public class TFMGCogWheelBlock extends AbstractSimpleShaftBlock implements ICogWheel, EncasableBlock {
|
||||
|
||||
boolean isLarge;
|
||||
|
||||
protected TFMGCogWheelBlock(boolean large, Properties properties) {
|
||||
super(properties);
|
||||
isLarge = large;
|
||||
}
|
||||
|
||||
public static TFMGCogWheelBlock small(Properties properties) {
|
||||
return new TFMGCogWheelBlock(false, properties);
|
||||
}
|
||||
|
||||
public static TFMGCogWheelBlock large(Properties properties) {
|
||||
return new TFMGCogWheelBlock(true, properties);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLargeCog() {
|
||||
return isLarge;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSmallCog() {
|
||||
return !isLarge;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VoxelShape getShape(BlockState state, BlockGetter worldIn, BlockPos pos, CollisionContext context) {
|
||||
return (isLarge ? AllShapes.LARGE_GEAR : AllShapes.SMALL_GEAR).get(state.getValue(AXIS));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canSurvive(BlockState state, LevelReader worldIn, BlockPos pos) {
|
||||
return isValidCogwheelPosition(ICogWheel.isLargeCog(state), worldIn, pos, state.getValue(AXIS));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlacedBy(Level worldIn, BlockPos pos, BlockState state, LivingEntity placer, ItemStack stack) {
|
||||
super.setPlacedBy(worldIn, pos, state, placer, stack);
|
||||
if (placer instanceof Player player)
|
||||
triggerShiftingGearsAdvancement(worldIn, pos, state, player);
|
||||
}
|
||||
|
||||
protected void triggerShiftingGearsAdvancement(Level world, BlockPos pos, BlockState state, Player player) {
|
||||
if (world.isClientSide || player == null)
|
||||
return;
|
||||
|
||||
Axis axis = state.getValue(TFMGCogWheelBlock.AXIS);
|
||||
for (Axis perpendicular1 : Iterate.axes) {
|
||||
if (perpendicular1 == axis)
|
||||
continue;
|
||||
|
||||
Direction d1 = Direction.get(Direction.AxisDirection.POSITIVE, perpendicular1);
|
||||
for (Axis perpendicular2 : Iterate.axes) {
|
||||
if (perpendicular1 == perpendicular2)
|
||||
continue;
|
||||
if (axis == perpendicular2)
|
||||
continue;
|
||||
|
||||
Direction d2 = Direction.get(Direction.AxisDirection.POSITIVE, perpendicular2);
|
||||
for (int offset1 : Iterate.positiveAndNegative) {
|
||||
for (int offset2 : Iterate.positiveAndNegative) {
|
||||
BlockPos connectedPos = pos.relative(d1, offset1)
|
||||
.relative(d2, offset2);
|
||||
BlockState blockState = world.getBlockState(connectedPos);
|
||||
if (!(blockState.getBlock() instanceof TFMGCogWheelBlock))
|
||||
continue;
|
||||
if (blockState.getValue(TFMGCogWheelBlock.AXIS) != axis)
|
||||
continue;
|
||||
if (ICogWheel.isLargeCog(blockState) == isLarge)
|
||||
continue;
|
||||
|
||||
AllAdvancements.COGS.awardTo(player);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand,
|
||||
BlockHitResult ray) {
|
||||
if (player.isShiftKeyDown() || !player.mayBuild())
|
||||
return InteractionResult.PASS;
|
||||
|
||||
ItemStack heldItem = player.getItemInHand(hand);
|
||||
InteractionResult result = tryEncase(state, world, pos, heldItem, player, hand, ray);
|
||||
if (result.consumesAction())
|
||||
return result;
|
||||
|
||||
return InteractionResult.PASS;
|
||||
}
|
||||
|
||||
public static boolean isValidCogwheelPosition(boolean large, LevelReader worldIn, BlockPos pos, Axis cogAxis) {
|
||||
for (Direction facing : Iterate.directions) {
|
||||
if (facing.getAxis() == cogAxis)
|
||||
continue;
|
||||
|
||||
BlockPos offsetPos = pos.relative(facing);
|
||||
BlockState blockState = worldIn.getBlockState(offsetPos);
|
||||
if (blockState.hasProperty(AXIS) && facing.getAxis() == blockState.getValue(AXIS))
|
||||
continue;
|
||||
|
||||
if (ICogWheel.isLargeCog(blockState) || large && ICogWheel.isSmallCog(blockState))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
protected Axis getAxisForPlacement(BlockPlaceContext context) {
|
||||
if (context.getPlayer() != null && context.getPlayer()
|
||||
.isShiftKeyDown())
|
||||
return context.getClickedFace()
|
||||
.getAxis();
|
||||
|
||||
Level world = context.getLevel();
|
||||
BlockState stateBelow = world.getBlockState(context.getClickedPos()
|
||||
.below());
|
||||
|
||||
if (AllBlocks.ROTATION_SPEED_CONTROLLER.has(stateBelow) && isLargeCog())
|
||||
return stateBelow.getValue(SpeedControllerBlock.HORIZONTAL_AXIS) == Axis.X ? Axis.Z : Axis.X;
|
||||
|
||||
BlockPos placedOnPos = context.getClickedPos()
|
||||
.relative(context.getClickedFace()
|
||||
.getOpposite());
|
||||
BlockState placedAgainst = world.getBlockState(placedOnPos);
|
||||
|
||||
Block block = placedAgainst.getBlock();
|
||||
if (ICogWheel.isSmallCog(placedAgainst))
|
||||
return ((IRotate) block).getRotationAxis(placedAgainst);
|
||||
|
||||
Axis preferredAxis = getPreferredAxis(context);
|
||||
return preferredAxis != null ? preferredAxis
|
||||
: context.getClickedFace()
|
||||
.getAxis();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getStateForPlacement(BlockPlaceContext context) {
|
||||
boolean shouldWaterlog = context.getLevel()
|
||||
.getFluidState(context.getClickedPos())
|
||||
.getType() == Fluids.WATER;
|
||||
return this.defaultBlockState()
|
||||
.setValue(AXIS, getAxisForPlacement(context))
|
||||
.setValue(BlockStateProperties.WATERLOGGED, shouldWaterlog);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getParticleTargetRadius() {
|
||||
return isLargeCog() ? 1.125f : .65f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getParticleInitialRadius() {
|
||||
return isLargeCog() ? 1f : .75f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDedicatedCogWheel() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockEntityType<? extends KineticBlockEntity> getBlockEntityType() {
|
||||
return TFMGBlockEntities.TFMG_COGWHEEL.get();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,305 @@
|
||||
package com.drmangotea.tfmg.content.decoration.cogs;
|
||||
|
||||
import com.simibubi.create.AllShapes;
|
||||
import com.simibubi.create.content.kinetics.base.DirectionalKineticBlock;
|
||||
import com.simibubi.create.content.kinetics.base.HorizontalKineticBlock;
|
||||
import com.simibubi.create.content.kinetics.base.IRotate;
|
||||
import com.simibubi.create.content.kinetics.base.RotatedPillarKineticBlock;
|
||||
import com.simibubi.create.content.kinetics.simpleRelays.ICogWheel;
|
||||
import com.simibubi.create.foundation.placement.IPlacementHelper;
|
||||
import com.simibubi.create.foundation.placement.PlacementHelpers;
|
||||
import com.simibubi.create.foundation.placement.PlacementOffset;
|
||||
import com.simibubi.create.foundation.utility.Iterate;
|
||||
import net.minecraft.MethodsReturnNonnullByDefault;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.core.Direction.Axis;
|
||||
import net.minecraft.world.InteractionResult;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.BlockItem;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.context.UseOnContext;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import static com.simibubi.create.content.kinetics.base.RotatedPillarKineticBlock.AXIS;
|
||||
|
||||
public class TFMGCogwheelBlockItem extends BlockItem {
|
||||
|
||||
boolean large;
|
||||
|
||||
private final int placementHelperId;
|
||||
private final int integratedCogHelperId;
|
||||
|
||||
public TFMGCogwheelBlockItem(TFMGCogWheelBlock block, Properties builder) {
|
||||
super(block, builder);
|
||||
large = block.isLarge;
|
||||
|
||||
placementHelperId = PlacementHelpers.register(large ? new LargeCogHelper() : new SmallCogHelper());
|
||||
integratedCogHelperId =
|
||||
PlacementHelpers.register(large ? new IntegratedLargeCogHelper() : new IntegratedSmallCogHelper());
|
||||
}
|
||||
|
||||
@Override
|
||||
public InteractionResult onItemUseFirst(ItemStack stack, UseOnContext context) {
|
||||
Level world = context.getLevel();
|
||||
BlockPos pos = context.getClickedPos();
|
||||
BlockState state = world.getBlockState(pos);
|
||||
|
||||
IPlacementHelper helper = PlacementHelpers.get(placementHelperId);
|
||||
Player player = context.getPlayer();
|
||||
BlockHitResult ray = new BlockHitResult(context.getClickLocation(), context.getClickedFace(), pos, true);
|
||||
if (helper.matchesState(state) && player != null && !player.isShiftKeyDown()) {
|
||||
return helper.getOffset(player, world, state, pos, ray)
|
||||
.placeInWorld(world, this, player, context.getHand(), ray);
|
||||
}
|
||||
|
||||
if (integratedCogHelperId != -1) {
|
||||
helper = PlacementHelpers.get(integratedCogHelperId);
|
||||
|
||||
if (helper.matchesState(state) && player != null && !player.isShiftKeyDown()) {
|
||||
return helper.getOffset(player, world, state, pos, ray)
|
||||
.placeInWorld(world, this, player, context.getHand(), ray);
|
||||
}
|
||||
}
|
||||
|
||||
return super.onItemUseFirst(stack, context);
|
||||
}
|
||||
|
||||
@MethodsReturnNonnullByDefault
|
||||
private static class SmallCogHelper extends DiagonalCogHelper {
|
||||
|
||||
@Override
|
||||
public Predicate<ItemStack> getItemPredicate() {
|
||||
return ((Predicate<ItemStack>) ICogWheel::isSmallCogItem).and(ICogWheel::isDedicatedCogItem);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlacementOffset getOffset(Player player, Level world, BlockState state, BlockPos pos,
|
||||
BlockHitResult ray) {
|
||||
if (hitOnShaft(state, ray))
|
||||
return PlacementOffset.fail();
|
||||
|
||||
if (!ICogWheel.isLargeCog(state)) {
|
||||
Axis axis = ((IRotate) state.getBlock()).getRotationAxis(state);
|
||||
List<Direction> directions = IPlacementHelper.orderedByDistanceExceptAxis(pos, ray.getLocation(), axis);
|
||||
|
||||
for (Direction dir : directions) {
|
||||
BlockPos newPos = pos.relative(dir);
|
||||
|
||||
if (!TFMGCogWheelBlock.isValidCogwheelPosition(false, world, newPos, axis))
|
||||
continue;
|
||||
|
||||
if (!world.getBlockState(newPos)
|
||||
.canBeReplaced())
|
||||
continue;
|
||||
|
||||
return PlacementOffset.success(newPos, s -> s.setValue(AXIS, axis));
|
||||
|
||||
}
|
||||
|
||||
return PlacementOffset.fail();
|
||||
}
|
||||
|
||||
return super.getOffset(player, world, state, pos, ray);
|
||||
}
|
||||
}
|
||||
|
||||
@MethodsReturnNonnullByDefault
|
||||
private static class LargeCogHelper extends DiagonalCogHelper {
|
||||
|
||||
@Override
|
||||
public Predicate<ItemStack> getItemPredicate() {
|
||||
return ((Predicate<ItemStack>) ICogWheel::isLargeCogItem).and(ICogWheel::isDedicatedCogItem);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlacementOffset getOffset(Player player, Level world, BlockState state, BlockPos pos,
|
||||
BlockHitResult ray) {
|
||||
if (hitOnShaft(state, ray))
|
||||
return PlacementOffset.fail();
|
||||
|
||||
if (ICogWheel.isLargeCog(state)) {
|
||||
Axis axis = ((IRotate) state.getBlock()).getRotationAxis(state);
|
||||
Direction side = IPlacementHelper.orderedByDistanceOnlyAxis(pos, ray.getLocation(), axis)
|
||||
.get(0);
|
||||
List<Direction> directions = IPlacementHelper.orderedByDistanceExceptAxis(pos, ray.getLocation(), axis);
|
||||
for (Direction dir : directions) {
|
||||
BlockPos newPos = pos.relative(dir)
|
||||
.relative(side);
|
||||
|
||||
if (!TFMGCogWheelBlock.isValidCogwheelPosition(true, world, newPos, dir.getAxis()))
|
||||
continue;
|
||||
|
||||
if (!world.getBlockState(newPos)
|
||||
.canBeReplaced())
|
||||
continue;
|
||||
|
||||
return PlacementOffset.success(newPos, s -> s.setValue(AXIS, dir.getAxis()));
|
||||
}
|
||||
|
||||
return PlacementOffset.fail();
|
||||
}
|
||||
|
||||
return super.getOffset(player, world, state, pos, ray);
|
||||
}
|
||||
}
|
||||
|
||||
@MethodsReturnNonnullByDefault
|
||||
public abstract static class DiagonalCogHelper implements IPlacementHelper {
|
||||
|
||||
@Override
|
||||
public Predicate<BlockState> getStatePredicate() {
|
||||
return s -> ICogWheel.isSmallCog(s) || ICogWheel.isLargeCog(s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlacementOffset getOffset(Player player, Level world, BlockState state, BlockPos pos,
|
||||
BlockHitResult ray) {
|
||||
// diagonal gears of different size
|
||||
Axis axis = ((IRotate) state.getBlock()).getRotationAxis(state);
|
||||
Direction closest = IPlacementHelper.orderedByDistanceExceptAxis(pos, ray.getLocation(), axis)
|
||||
.get(0);
|
||||
List<Direction> directions = IPlacementHelper.orderedByDistanceExceptAxis(pos, ray.getLocation(), axis,
|
||||
d -> d.getAxis() != closest.getAxis());
|
||||
|
||||
for (Direction dir : directions) {
|
||||
BlockPos newPos = pos.relative(dir)
|
||||
.relative(closest);
|
||||
if (!world.getBlockState(newPos)
|
||||
.canBeReplaced())
|
||||
continue;
|
||||
|
||||
if (!TFMGCogWheelBlock.isValidCogwheelPosition(ICogWheel.isLargeCog(state), world, newPos, axis))
|
||||
continue;
|
||||
|
||||
return PlacementOffset.success(newPos, s -> s.setValue(AXIS, axis));
|
||||
}
|
||||
|
||||
return PlacementOffset.fail();
|
||||
}
|
||||
|
||||
protected boolean hitOnShaft(BlockState state, BlockHitResult ray) {
|
||||
return AllShapes.SIX_VOXEL_POLE.get(((IRotate) state.getBlock()).getRotationAxis(state))
|
||||
.bounds()
|
||||
.inflate(0.001)
|
||||
.contains(ray.getLocation()
|
||||
.subtract(ray.getLocation()
|
||||
.align(Iterate.axisSet)));
|
||||
}
|
||||
}
|
||||
|
||||
@MethodsReturnNonnullByDefault
|
||||
public static class IntegratedLargeCogHelper implements IPlacementHelper {
|
||||
|
||||
@Override
|
||||
public Predicate<ItemStack> getItemPredicate() {
|
||||
return ((Predicate<ItemStack>) ICogWheel::isLargeCogItem).and(ICogWheel::isDedicatedCogItem);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Predicate<BlockState> getStatePredicate() {
|
||||
return s -> !ICogWheel.isDedicatedCogWheel(s.getBlock()) && ICogWheel.isSmallCog(s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlacementOffset getOffset(Player player, Level world, BlockState state, BlockPos pos,
|
||||
BlockHitResult ray) {
|
||||
Direction face = ray.getDirection();
|
||||
Axis newAxis;
|
||||
|
||||
if (state.hasProperty(HorizontalKineticBlock.HORIZONTAL_FACING))
|
||||
newAxis = state.getValue(HorizontalKineticBlock.HORIZONTAL_FACING)
|
||||
.getAxis();
|
||||
else if (state.hasProperty(DirectionalKineticBlock.FACING))
|
||||
newAxis = state.getValue(DirectionalKineticBlock.FACING)
|
||||
.getAxis();
|
||||
else if (state.hasProperty(RotatedPillarKineticBlock.AXIS))
|
||||
newAxis = state.getValue(RotatedPillarKineticBlock.AXIS);
|
||||
else
|
||||
newAxis = Axis.Y;
|
||||
|
||||
if (face.getAxis() == newAxis)
|
||||
return PlacementOffset.fail();
|
||||
|
||||
List<Direction> directions =
|
||||
IPlacementHelper.orderedByDistanceExceptAxis(pos, ray.getLocation(), face.getAxis(), newAxis);
|
||||
|
||||
for (Direction d : directions) {
|
||||
BlockPos newPos = pos.relative(face)
|
||||
.relative(d);
|
||||
|
||||
if (!world.getBlockState(newPos)
|
||||
.canBeReplaced())
|
||||
continue;
|
||||
|
||||
if (!TFMGCogWheelBlock.isValidCogwheelPosition(false, world, newPos, newAxis))
|
||||
return PlacementOffset.fail();
|
||||
|
||||
return PlacementOffset.success(newPos, s -> s.setValue(TFMGCogWheelBlock.AXIS, newAxis));
|
||||
}
|
||||
|
||||
return PlacementOffset.fail();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@MethodsReturnNonnullByDefault
|
||||
public static class IntegratedSmallCogHelper implements IPlacementHelper {
|
||||
|
||||
@Override
|
||||
public Predicate<ItemStack> getItemPredicate() {
|
||||
return ((Predicate<ItemStack>) ICogWheel::isSmallCogItem).and(ICogWheel::isDedicatedCogItem);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Predicate<BlockState> getStatePredicate() {
|
||||
return s -> !ICogWheel.isDedicatedCogWheel(s.getBlock()) && ICogWheel.isSmallCog(s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlacementOffset getOffset(Player player, Level world, BlockState state, BlockPos pos,
|
||||
BlockHitResult ray) {
|
||||
Direction face = ray.getDirection();
|
||||
Axis newAxis;
|
||||
|
||||
if (state.hasProperty(HorizontalKineticBlock.HORIZONTAL_FACING))
|
||||
newAxis = state.getValue(HorizontalKineticBlock.HORIZONTAL_FACING)
|
||||
.getAxis();
|
||||
else if (state.hasProperty(DirectionalKineticBlock.FACING))
|
||||
newAxis = state.getValue(DirectionalKineticBlock.FACING)
|
||||
.getAxis();
|
||||
else if (state.hasProperty(RotatedPillarKineticBlock.AXIS))
|
||||
newAxis = state.getValue(RotatedPillarKineticBlock.AXIS);
|
||||
else
|
||||
newAxis = Axis.Y;
|
||||
|
||||
if (face.getAxis() == newAxis)
|
||||
return PlacementOffset.fail();
|
||||
|
||||
List<Direction> directions = IPlacementHelper.orderedByDistanceExceptAxis(pos, ray.getLocation(), newAxis);
|
||||
|
||||
for (Direction d : directions) {
|
||||
BlockPos newPos = pos.relative(d);
|
||||
|
||||
if (!world.getBlockState(newPos)
|
||||
.canBeReplaced())
|
||||
continue;
|
||||
|
||||
if (!TFMGCogWheelBlock.isValidCogwheelPosition(false, world, newPos, newAxis))
|
||||
return PlacementOffset.fail();
|
||||
|
||||
return PlacementOffset.success()
|
||||
.at(newPos)
|
||||
.withTransform(s -> s.setValue(TFMGCogWheelBlock.AXIS, newAxis));
|
||||
}
|
||||
|
||||
return PlacementOffset.fail();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
package com.drmangotea.tfmg.content.decoration.cogs;
|
||||
|
||||
import com.drmangotea.tfmg.registry.TFMGBlocks;
|
||||
import com.drmangotea.tfmg.registry.TFMGPartialModels;
|
||||
import com.jozufozu.flywheel.api.Instancer;
|
||||
import com.jozufozu.flywheel.api.Material;
|
||||
import com.jozufozu.flywheel.api.MaterialManager;
|
||||
import com.jozufozu.flywheel.core.PartialModel;
|
||||
import com.jozufozu.flywheel.util.transform.TransformStack;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.simibubi.create.AllPartialModels;
|
||||
import com.simibubi.create.content.kinetics.base.KineticBlockEntityRenderer;
|
||||
import com.simibubi.create.content.kinetics.base.SingleRotatingInstance;
|
||||
import com.simibubi.create.content.kinetics.base.flwdata.RotatingData;
|
||||
import com.simibubi.create.content.kinetics.simpleRelays.BracketedKineticBlockEntityRenderer;
|
||||
import com.simibubi.create.content.kinetics.simpleRelays.ICogWheel;
|
||||
import com.simibubi.create.content.kinetics.simpleRelays.SimpleKineticBlockEntity;
|
||||
import com.simibubi.create.foundation.render.AllMaterialSpecs;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.core.Direction.Axis;
|
||||
import net.minecraft.core.Direction.AxisDirection;
|
||||
|
||||
public class TFMGCogwheelInstance extends SingleRotatingInstance<SimpleKineticBlockEntity> {
|
||||
|
||||
protected RotatingData additionalShaft;
|
||||
|
||||
public TFMGCogwheelInstance(MaterialManager materialManager, SimpleKineticBlockEntity blockEntity) {
|
||||
super(materialManager, blockEntity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
super.init();
|
||||
if (!ICogWheel.isLargeCog(blockEntity.getBlockState()))
|
||||
return;
|
||||
|
||||
// Large cogs sometimes have to offset their teeth by 11.25 degrees in order to
|
||||
// mesh properly
|
||||
|
||||
float speed = blockEntity.getSpeed();
|
||||
Axis axis = KineticBlockEntityRenderer.getRotationAxisOf(blockEntity);
|
||||
BlockPos pos = blockEntity.getBlockPos();
|
||||
float offset = BracketedKineticBlockEntityRenderer.getShaftAngleOffset(axis, pos);
|
||||
Direction facing = Direction.fromAxisAndDirection(axis, AxisDirection.POSITIVE);
|
||||
Instancer<RotatingData> half = getRotatingMaterial().getModel(AllPartialModels.COGWHEEL_SHAFT, blockState,
|
||||
facing, () -> this.rotateToAxis(axis));
|
||||
|
||||
additionalShaft = setup(half.createInstance(), speed);
|
||||
additionalShaft.setRotationOffset(offset);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Instancer<RotatingData> getModel() {
|
||||
|
||||
Axis axis = KineticBlockEntityRenderer.getRotationAxisOf(blockEntity);
|
||||
Direction facing = Direction.fromAxisAndDirection(axis, AxisDirection.POSITIVE);
|
||||
|
||||
|
||||
if (!ICogWheel.isLargeCog(blockEntity.getBlockState()))
|
||||
return getCutoutRotatingMaterial().getModel(blockState);
|
||||
//return super.getModel();
|
||||
|
||||
PartialModel model = blockEntity.getBlockState().is(TFMGBlocks.LARGE_ALUMINUM_COGWHEEL.get()) ? TFMGPartialModels.LARGE_ALUMINUM_COGHWEEL : TFMGPartialModels.LARGE_STEEL_COGHWEEL;
|
||||
|
||||
return getCutoutRotatingMaterial().getModel(model, blockState, facing,
|
||||
() -> this.rotateToAxis(axis));
|
||||
}
|
||||
|
||||
protected Material<RotatingData> getCutoutRotatingMaterial() {
|
||||
return materialManager.defaultCutout()
|
||||
.material(AllMaterialSpecs.ROTATING);
|
||||
}
|
||||
|
||||
private PoseStack rotateToAxis(Axis axis) {
|
||||
Direction facing = Direction.fromAxisAndDirection(axis, AxisDirection.POSITIVE);
|
||||
PoseStack poseStack = new PoseStack();
|
||||
TransformStack.cast(poseStack)
|
||||
.centre()
|
||||
.rotateToFace(facing)
|
||||
.multiply(com.mojang.math.Axis.XN.rotationDegrees(-90))
|
||||
.unCentre();
|
||||
return poseStack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update() {
|
||||
super.update();
|
||||
if (additionalShaft != null) {
|
||||
updateRotation(additionalShaft);
|
||||
additionalShaft.setRotationOffset(TFMGCogwheelRenderer.getShaftAngleOffset(axis, pos));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateLight() {
|
||||
super.updateLight();
|
||||
if (additionalShaft != null)
|
||||
relight(pos, additionalShaft);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
super.remove();
|
||||
if (additionalShaft != null)
|
||||
additionalShaft.delete();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
package com.drmangotea.tfmg.content.decoration.cogs;
|
||||
|
||||
import com.drmangotea.tfmg.registry.TFMGBlocks;
|
||||
import com.drmangotea.tfmg.registry.TFMGPartialModels;
|
||||
import com.jozufozu.flywheel.backend.Backend;
|
||||
import com.jozufozu.flywheel.core.PartialModel;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.simibubi.create.AllBlocks;
|
||||
import com.simibubi.create.AllPartialModels;
|
||||
import com.simibubi.create.content.kinetics.base.KineticBlockEntityRenderer;
|
||||
import com.simibubi.create.content.kinetics.simpleRelays.SimpleKineticBlockEntity;
|
||||
import com.simibubi.create.foundation.render.CachedBufferer;
|
||||
import com.simibubi.create.foundation.render.SuperByteBuffer;
|
||||
import com.simibubi.create.foundation.utility.AnimationTickHolder;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider.Context;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.core.Direction.Axis;
|
||||
import net.minecraft.core.Direction.AxisDirection;
|
||||
|
||||
public class TFMGCogwheelRenderer extends KineticBlockEntityRenderer<SimpleKineticBlockEntity> {
|
||||
|
||||
public TFMGCogwheelRenderer(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderSafe(SimpleKineticBlockEntity be, float partialTicks, PoseStack ms,
|
||||
MultiBufferSource buffer, int light, int overlay) {
|
||||
|
||||
if (Backend.canUseInstancing(be.getLevel()))
|
||||
return;
|
||||
|
||||
if (!AllBlocks.LARGE_COGWHEEL.has(be.getBlockState())) {
|
||||
super.renderSafe(be, partialTicks, ms, buffer, light, overlay);
|
||||
return;
|
||||
}
|
||||
|
||||
Axis axis = getRotationAxisOf(be);
|
||||
Direction facing = Direction.fromAxisAndDirection(axis, AxisDirection.POSITIVE);
|
||||
|
||||
PartialModel model = be.getBlockState().is(TFMGBlocks.LARGE_ALUMINUM_COGWHEEL.get()) ? TFMGPartialModels.LARGE_ALUMINUM_COGHWEEL : TFMGPartialModels.LARGE_STEEL_COGHWEEL;
|
||||
|
||||
renderRotatingBuffer(be,
|
||||
CachedBufferer.partialFacingVertical(model, be.getBlockState(), facing),
|
||||
ms, buffer.getBuffer(RenderType.cutoutMipped()), light);
|
||||
|
||||
float angle = getAngleForLargeCogShaft(be, axis);
|
||||
SuperByteBuffer shaft =
|
||||
CachedBufferer.partialFacingVertical(AllPartialModels.COGWHEEL_SHAFT, be.getBlockState(), facing);
|
||||
kineticRotationTransform(shaft, be, axis, angle, light);
|
||||
shaft.renderInto(ms, buffer.getBuffer(RenderType.solid()));
|
||||
}
|
||||
|
||||
public static float getAngleForLargeCogShaft(SimpleKineticBlockEntity be, Axis axis) {
|
||||
BlockPos pos = be.getBlockPos();
|
||||
float offset = getShaftAngleOffset(axis, pos);
|
||||
float time = AnimationTickHolder.getRenderTime(be.getLevel());
|
||||
float angle = ((time * be.getSpeed() * 3f / 10 + offset) % 360) / 180 * (float) Math.PI;
|
||||
return angle;
|
||||
}
|
||||
|
||||
public static float getShaftAngleOffset(Axis axis, BlockPos pos) {
|
||||
float offset = 0;
|
||||
double d = (((axis == Axis.X) ? 0 : pos.getX()) + ((axis == Axis.Y) ? 0 : pos.getY())
|
||||
+ ((axis == Axis.Z) ? 0 : pos.getZ())) % 2;
|
||||
if (d == 0)
|
||||
offset = 22.5f;
|
||||
return offset;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
package com.drmangotea.tfmg.content.decoration.concrete;
|
||||
|
||||
import com.drmangotea.tfmg.registry.TFMGBlocks;
|
||||
import com.drmangotea.tfmg.registry.TFMGFluids;
|
||||
import com.simibubi.create.foundation.data.SharedProperties;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.sounds.SoundEvents;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.InteractionResult;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.Items;
|
||||
import net.minecraft.world.item.context.BlockPlaceContext;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.LevelAccessor;
|
||||
import net.minecraft.world.level.block.SimpleWaterloggedBlock;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
|
||||
import net.minecraft.world.level.block.state.properties.BooleanProperty;
|
||||
import net.minecraft.world.level.material.FluidState;
|
||||
import net.minecraft.world.level.material.Fluids;
|
||||
|
||||
public interface ConcreteloggedBlock {
|
||||
BooleanProperty CONCRETELOGGED = BooleanProperty.create("concretelogged");
|
||||
|
||||
|
||||
|
||||
default FluidState fluidState(BlockState state) {
|
||||
return state.getValue(CONCRETELOGGED) ? TFMGFluids.LIQUID_CONCRETE.getSource().getSource(false) : Fluids.EMPTY.defaultFluidState();
|
||||
}
|
||||
|
||||
default void updateConcrete(LevelAccessor level, BlockState state, BlockPos pos) {
|
||||
if (state.getValue(CONCRETELOGGED))
|
||||
level.scheduleTick(pos, TFMGFluids.LIQUID_CONCRETE.getSource(), TFMGFluids.LIQUID_CONCRETE.getSource().getTickDelay(level));
|
||||
}
|
||||
default InteractionResult onClicked(Level level, BlockPos pos, BlockState state, Player player, InteractionHand hand){
|
||||
ItemStack stack = player.getItemInHand(hand);
|
||||
|
||||
if(state.getValue(CONCRETELOGGED)){
|
||||
if(stack.is(Items.BUCKET)){
|
||||
level.setBlock(pos, state.setValue(CONCRETELOGGED, false),3);
|
||||
if(!player.isCreative())
|
||||
player.setItemInHand(hand, TFMGFluids.LIQUID_CONCRETE.getBucket().get().getDefaultInstance());
|
||||
player.playSound(SoundEvents.BUCKET_FILL, 1F, 1.0F + player.getRandom().nextFloat() * 0.4F);
|
||||
return InteractionResult.SUCCESS;
|
||||
}
|
||||
|
||||
}else {
|
||||
if(stack.is(TFMGFluids.LIQUID_CONCRETE.getBucket().get())){
|
||||
level.setBlock(pos, state.setValue(CONCRETELOGGED, true),3);
|
||||
if(!player.isCreative())
|
||||
player.setItemInHand(hand, Items.BUCKET.getDefaultInstance());
|
||||
player.playSound(SoundEvents.BUCKET_EMPTY, 1F, 1.0F + player.getRandom().nextFloat() * 0.4F);
|
||||
return InteractionResult.SUCCESS;
|
||||
}
|
||||
}
|
||||
return InteractionResult.PASS;
|
||||
}
|
||||
|
||||
default void tickDrying(Level level,BlockState state,BlockState newStack, BlockPos pos, RandomSource random){
|
||||
if(!state.getValue(CONCRETELOGGED))
|
||||
return;
|
||||
|
||||
int randomInt = random.nextInt(7) ;
|
||||
if(randomInt==2) {
|
||||
level.setBlock(pos, newStack, 3);
|
||||
}
|
||||
}
|
||||
|
||||
default BlockState withConcrete(BlockState placementState, BlockPlaceContext ctx) {
|
||||
return withConcrete(ctx.getLevel(), placementState, ctx.getClickedPos());
|
||||
}
|
||||
|
||||
static BlockState withConcrete(LevelAccessor level, BlockState placementState, BlockPos pos) {
|
||||
if (placementState == null)
|
||||
return null;
|
||||
FluidState ifluidstate = level.getFluidState(pos);
|
||||
if (placementState.isAir())
|
||||
return ifluidstate.getType() == TFMGFluids.LIQUID_CONCRETE.getSource() ? ifluidstate.createLegacyBlock() : placementState;
|
||||
return placementState.setValue(CONCRETELOGGED, ifluidstate.getType() == TFMGFluids.LIQUID_CONCRETE.getSource());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package com.drmangotea.tfmg.content.decoration.concrete;
|
||||
|
||||
import com.drmangotea.tfmg.registry.TFMGBlocks;
|
||||
import com.drmangotea.tfmg.registry.TFMGFluids;
|
||||
import com.simibubi.create.foundation.block.ProperWaterloggedBlock;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.InteractionResult;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.context.BlockPlaceContext;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.LevelAccessor;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.SimpleWaterloggedBlock;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.StateDefinition;
|
||||
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
|
||||
import net.minecraft.world.level.block.state.properties.BooleanProperty;
|
||||
import net.minecraft.world.level.material.FluidState;
|
||||
import net.minecraft.world.level.material.Fluids;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
|
||||
public class RebarBlock extends Block implements ConcreteloggedBlock {
|
||||
|
||||
|
||||
public RebarBlock(Properties p_49795_) {
|
||||
super(p_49795_);
|
||||
registerDefaultState(this.getStateDefinition().any().setValue(CONCRETELOGGED, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public FluidState getFluidState(BlockState state) {
|
||||
return fluidState(state);
|
||||
}
|
||||
@Override
|
||||
public BlockState updateShape(BlockState pState, Direction pDirection, BlockState pNeighborState,
|
||||
LevelAccessor pLevel, BlockPos pCurrentPos, BlockPos pNeighborPos) {
|
||||
updateConcrete(pLevel, pState, pCurrentPos);
|
||||
return pState;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InteractionResult use(BlockState blockState, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult blockHitResult) {
|
||||
return onClicked(level, pos, blockState, player, hand);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getStateForPlacement(BlockPlaceContext pContext) {
|
||||
return withConcrete(super.getStateForPlacement(pContext), pContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void randomTick(BlockState state, ServerLevel level, BlockPos pos, RandomSource randomSource) {
|
||||
tickDrying(level,state,TFMGBlocks.REBAR_CONCRETE.block.getDefaultState(),pos, randomSource);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRandomlyTicking(BlockState p_49921_) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
|
||||
super.createBlockStateDefinition(builder);
|
||||
builder.add(CONCRETELOGGED);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.drmangotea.tfmg.content.decoration.concrete;
|
||||
|
||||
import com.drmangotea.tfmg.base.TFMGShapes;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.level.BlockGetter;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.phys.shapes.CollisionContext;
|
||||
import net.minecraft.world.phys.shapes.VoxelShape;
|
||||
|
||||
public class RebarFloorBlock extends RebarBlock{
|
||||
public RebarFloorBlock(Properties p_49795_) {
|
||||
super(p_49795_);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VoxelShape getShape(BlockState p_60555_, BlockGetter p_60556_, BlockPos p_60557_, CollisionContext p_60558_) {
|
||||
return TFMGShapes.REBAR_FLOOR;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
package com.drmangotea.tfmg.content.decoration.concrete;
|
||||
|
||||
import com.drmangotea.tfmg.TFMG;
|
||||
import com.drmangotea.tfmg.base.TFMGDirectionalBlock;
|
||||
import com.drmangotea.tfmg.base.TFMGShapes;
|
||||
import com.drmangotea.tfmg.registry.TFMGBlocks;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.InteractionResult;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.context.BlockPlaceContext;
|
||||
import net.minecraft.world.level.BlockGetter;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.LevelAccessor;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.StateDefinition;
|
||||
import net.minecraft.world.level.material.FluidState;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.minecraft.world.phys.shapes.CollisionContext;
|
||||
import net.minecraft.world.phys.shapes.VoxelShape;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
public class RebarPillarBlock extends TFMGDirectionalBlock implements ConcreteloggedBlock {
|
||||
|
||||
|
||||
public RebarPillarBlock(Properties p_49795_) {
|
||||
super(p_49795_);
|
||||
registerDefaultState(this.getStateDefinition().any().setValue(CONCRETELOGGED, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public FluidState getFluidState(BlockState state) {
|
||||
return fluidState(state);
|
||||
}
|
||||
@Override
|
||||
public BlockState updateShape(BlockState pState, Direction pDirection, BlockState pNeighborState,
|
||||
LevelAccessor pLevel, BlockPos pCurrentPos, BlockPos pNeighborPos) {
|
||||
updateConcrete(pLevel, pState, pCurrentPos);
|
||||
return pState;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VoxelShape getShape(BlockState p_60555_, BlockGetter p_60556_, BlockPos p_60557_, CollisionContext p_60558_) {
|
||||
return TFMGShapes.REBAR_PILLAR.get(p_60555_.getValue(FACING));
|
||||
}
|
||||
|
||||
@Override
|
||||
public InteractionResult use(BlockState blockState, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult blockHitResult) {
|
||||
return onClicked(level, pos, blockState, player, hand);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getStateForPlacement(BlockPlaceContext pContext) {
|
||||
return withConcrete(super.getStateForPlacement(pContext), pContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void randomTick(BlockState state, ServerLevel level, BlockPos pos, RandomSource randomSource) {
|
||||
tickDrying(level,state,TFMGBlocks.REBAR_CONCRETE.block.getDefaultState(),pos, randomSource);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRandomlyTicking(BlockState p_49921_) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
|
||||
super.createBlockStateDefinition(builder);
|
||||
builder.add(CONCRETELOGGED);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package com.drmangotea.tfmg.content.decoration.concrete;
|
||||
|
||||
|
||||
import com.drmangotea.tfmg.registry.TFMGBlocks;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.InteractionResult;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.context.BlockPlaceContext;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.LevelAccessor;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.StairBlock;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.StateDefinition;
|
||||
import net.minecraft.world.level.material.FluidState;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
|
||||
public class RebarStairsBlock extends StairBlock implements ConcreteloggedBlock{
|
||||
|
||||
public RebarStairsBlock(BlockState state,Properties p_56863_) {
|
||||
super(state, p_56863_);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FluidState getFluidState(BlockState state) {
|
||||
return fluidState(state);
|
||||
}
|
||||
@Override
|
||||
public BlockState updateShape(BlockState pState, Direction pDirection, BlockState pNeighborState,
|
||||
LevelAccessor pLevel, BlockPos pCurrentPos, BlockPos pNeighborPos) {
|
||||
updateConcrete(pLevel, pState, pCurrentPos);
|
||||
return pState;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InteractionResult use(BlockState blockState, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult blockHitResult) {
|
||||
return onClicked(level, pos, blockState, player, hand);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getStateForPlacement(BlockPlaceContext pContext) {
|
||||
return withConcrete(super.getStateForPlacement(pContext), pContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void randomTick(BlockState state, ServerLevel level, BlockPos pos, RandomSource randomSource) {
|
||||
tickDrying(level,state,TFMGBlocks.REBAR_CONCRETE.stairs.getDefaultState().setValue(FACING, state.getValue(FACING)).setValue(HALF, state.getValue(HALF)),pos, randomSource);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRandomlyTicking(BlockState p_49921_) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
|
||||
super.createBlockStateDefinition(builder);
|
||||
builder.add(CONCRETELOGGED);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.drmangotea.tfmg.content.decoration.concrete;
|
||||
|
||||
import com.drmangotea.tfmg.base.WallMountBlock;
|
||||
import com.drmangotea.tfmg.content.decoration.LithiumTorchBlock;
|
||||
import com.simibubi.create.foundation.data.SpecialBlockStateGen;
|
||||
import com.tterrag.registrate.providers.DataGenContext;
|
||||
import com.tterrag.registrate.providers.RegistrateBlockstateProvider;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.StairBlock;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.properties.Half;
|
||||
import net.minecraftforge.client.model.generators.ModelFile;
|
||||
|
||||
import static com.simibubi.create.foundation.data.AssetLookup.partialBaseModel;
|
||||
|
||||
public class RebarStairsGenerator extends SpecialBlockStateGen {
|
||||
|
||||
|
||||
@Override
|
||||
protected int getXRotation(BlockState state) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getYRotation(BlockState state) {
|
||||
return switch (state.getValue(StairBlock.FACING)) {
|
||||
case NORTH -> 270;
|
||||
case SOUTH -> 90;
|
||||
case WEST -> 180;
|
||||
case EAST -> 0;
|
||||
case DOWN -> 0;
|
||||
case UP -> 0;
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends Block> ModelFile getModel(DataGenContext<Block, T> ctx, RegistrateBlockstateProvider prov,
|
||||
BlockState state) {
|
||||
return state.getValue(StairBlock.HALF)== Half.TOP ? partialBaseModel(ctx, prov, "upside_down")
|
||||
: partialBaseModel(ctx, prov);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.drmangotea.tfmg.content.decoration.concrete;
|
||||
|
||||
import com.drmangotea.tfmg.base.TFMGShapes;
|
||||
import com.drmangotea.tfmg.registry.TFMGBlocks;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.level.BlockGetter;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.phys.shapes.CollisionContext;
|
||||
import net.minecraft.world.phys.shapes.VoxelShape;
|
||||
|
||||
public class RebarWallBlock extends RebarBlock{
|
||||
public RebarWallBlock(Properties p_49795_) {
|
||||
super(p_49795_);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VoxelShape getShape(BlockState p_60555_, BlockGetter p_60556_, BlockPos p_60557_, CollisionContext p_60558_) {
|
||||
return TFMGShapes.CABLE_TUBE.get(Direction.UP);
|
||||
}
|
||||
@Override
|
||||
public void randomTick(BlockState state, ServerLevel level, BlockPos pos, RandomSource randomSource) {
|
||||
tickDrying(level,state,TFMGBlocks.REBAR_CONCRETE.wall.getDefaultState(),pos, randomSource);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,253 @@
|
||||
package com.drmangotea.tfmg.content.decoration.doors;
|
||||
|
||||
|
||||
import com.drmangotea.tfmg.registry.TFMGBlockEntities;
|
||||
import com.simibubi.create.content.contraptions.ContraptionWorld;
|
||||
import com.simibubi.create.content.decoration.slidingDoor.SlidingDoorShapes;
|
||||
import com.simibubi.create.content.equipment.wrench.IWrenchable;
|
||||
import com.simibubi.create.foundation.block.IBE;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.InteractionResult;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.context.BlockPlaceContext;
|
||||
import net.minecraft.world.level.BlockGetter;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.LevelAccessor;
|
||||
import net.minecraft.world.level.LevelReader;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.DoorBlock;
|
||||
import net.minecraft.world.level.block.RenderShape;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.StateDefinition.Builder;
|
||||
import net.minecraft.world.level.block.state.properties.BlockSetType;
|
||||
import net.minecraft.world.level.block.state.properties.BooleanProperty;
|
||||
import net.minecraft.world.level.block.state.properties.DoorHingeSide;
|
||||
import net.minecraft.world.level.block.state.properties.DoubleBlockHalf;
|
||||
import net.minecraft.world.level.gameevent.GameEvent;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.minecraft.world.phys.shapes.CollisionContext;
|
||||
import net.minecraft.world.phys.shapes.VoxelShape;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import static com.simibubi.create.content.decoration.slidingDoor.SlidingDoorBlock.TRAIN_SET_TYPE;
|
||||
|
||||
public class TFMGSlidingDoorBlock extends DoorBlock implements IWrenchable, IBE<TFMGSlidingDoorBlockEntity> {
|
||||
|
||||
public static final BooleanProperty VISIBLE = BooleanProperty.create("visible");
|
||||
private boolean folds;
|
||||
|
||||
public static TFMGSlidingDoorBlock metal(Properties p_52737_, boolean folds) {
|
||||
return new TFMGSlidingDoorBlock(p_52737_, TRAIN_SET_TYPE.get(), folds);
|
||||
}
|
||||
|
||||
public TFMGSlidingDoorBlock(Properties p_52737_, BlockSetType type, boolean folds) {
|
||||
super(p_52737_, type);
|
||||
this.folds = folds;
|
||||
}
|
||||
|
||||
public boolean isFoldingDoor() {
|
||||
return folds;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createBlockStateDefinition(Builder<Block, BlockState> pBuilder) {
|
||||
super.createBlockStateDefinition(pBuilder.add(VISIBLE));
|
||||
}
|
||||
|
||||
@Override
|
||||
public VoxelShape getShape(BlockState pState, BlockGetter pLevel, BlockPos pPos, CollisionContext pContext) {
|
||||
if (!pState.getValue(OPEN) && (pState.getValue(VISIBLE) || pLevel instanceof ContraptionWorld))
|
||||
return super.getShape(pState, pLevel, pPos, pContext);
|
||||
|
||||
Direction direction = pState.getValue(FACING);
|
||||
boolean hinge = pState.getValue(HINGE) == DoorHingeSide.RIGHT;
|
||||
return SlidingDoorShapes.get(direction, hinge, isFoldingDoor());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canSurvive(BlockState pState, LevelReader pLevel, BlockPos pPos) {
|
||||
return pState.getValue(HALF) == DoubleBlockHalf.LOWER || pLevel.getBlockState(pPos.below())
|
||||
.is(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VoxelShape getInteractionShape(BlockState pState, BlockGetter pLevel, BlockPos pPos) {
|
||||
return getShape(pState, pLevel, pPos, CollisionContext.empty());
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getStateForPlacement(BlockPlaceContext pContext) {
|
||||
BlockState stateForPlacement = super.getStateForPlacement(pContext);
|
||||
if (stateForPlacement != null && stateForPlacement.getValue(OPEN))
|
||||
return stateForPlacement.setValue(OPEN, false)
|
||||
.setValue(POWERED, false);
|
||||
return stateForPlacement;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlace(BlockState pState, Level pLevel, BlockPos pPos, BlockState pOldState, boolean pIsMoving) {
|
||||
if (!pOldState.is(this))
|
||||
deferUpdate(pLevel, pPos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState updateShape(BlockState pState, Direction pFacing, BlockState pFacingState, LevelAccessor pLevel,
|
||||
BlockPos pCurrentPos, BlockPos pFacingPos) {
|
||||
BlockState blockState = super.updateShape(pState, pFacing, pFacingState, pLevel, pCurrentPos, pFacingPos);
|
||||
if (blockState.isAir())
|
||||
return blockState;
|
||||
DoubleBlockHalf doubleblockhalf = blockState.getValue(HALF);
|
||||
if (pFacing.getAxis() == Direction.Axis.Y
|
||||
&& doubleblockhalf == DoubleBlockHalf.LOWER == (pFacing == Direction.UP)) {
|
||||
return pFacingState.is(this) && pFacingState.getValue(HALF) != doubleblockhalf
|
||||
? blockState.setValue(VISIBLE, pFacingState.getValue(VISIBLE))
|
||||
: Blocks.AIR.defaultBlockState();
|
||||
}
|
||||
return blockState;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOpen(@Nullable Entity entity, Level level, BlockState state, BlockPos pos, boolean open) {
|
||||
if (!state.is(this))
|
||||
return;
|
||||
if (state.getValue(OPEN) == open)
|
||||
return;
|
||||
BlockState changedState = state.setValue(OPEN, open);
|
||||
if (open)
|
||||
changedState = changedState.setValue(VISIBLE, false);
|
||||
level.setBlock(pos, changedState, 10);
|
||||
|
||||
DoorHingeSide hinge = changedState.getValue(HINGE);
|
||||
Direction facing = changedState.getValue(FACING);
|
||||
BlockPos otherPos =
|
||||
pos.relative(hinge == DoorHingeSide.LEFT ? facing.getClockWise() : facing.getCounterClockWise());
|
||||
BlockState otherDoor = level.getBlockState(otherPos);
|
||||
if (isDoubleDoor(changedState, hinge, facing, otherDoor))
|
||||
setOpen(entity, level, otherDoor, otherPos, open);
|
||||
|
||||
this.playSound(level, pos, open);
|
||||
level.gameEvent(entity, open ? GameEvent.BLOCK_OPEN : GameEvent.BLOCK_CLOSE, pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void neighborChanged(BlockState pState, Level pLevel, BlockPos pPos, Block pBlock, BlockPos pFromPos,
|
||||
boolean pIsMoving) {
|
||||
boolean lower = pState.getValue(HALF) == DoubleBlockHalf.LOWER;
|
||||
boolean isPowered = isDoorPowered(pLevel, pPos, pState);
|
||||
if (defaultBlockState().is(pBlock))
|
||||
return;
|
||||
if (isPowered == pState.getValue(POWERED))
|
||||
return;
|
||||
|
||||
TFMGSlidingDoorBlockEntity be = getBlockEntity(pLevel, lower ? pPos : pPos.below());
|
||||
if (be != null && be.deferUpdate)
|
||||
return;
|
||||
|
||||
BlockState changedState = pState.setValue(POWERED, Boolean.valueOf(isPowered))
|
||||
.setValue(OPEN, Boolean.valueOf(isPowered));
|
||||
if (isPowered)
|
||||
changedState = changedState.setValue(VISIBLE, false);
|
||||
|
||||
if (isPowered != pState.getValue(OPEN)) {
|
||||
this.playSound(pLevel, pPos, isPowered);
|
||||
pLevel.gameEvent(null, isPowered ? GameEvent.BLOCK_OPEN : GameEvent.BLOCK_CLOSE, pPos);
|
||||
|
||||
DoorHingeSide hinge = changedState.getValue(HINGE);
|
||||
Direction facing = changedState.getValue(FACING);
|
||||
BlockPos otherPos =
|
||||
pPos.relative(hinge == DoorHingeSide.LEFT ? facing.getClockWise() : facing.getCounterClockWise());
|
||||
BlockState otherDoor = pLevel.getBlockState(otherPos);
|
||||
|
||||
if (isDoubleDoor(changedState, hinge, facing, otherDoor)) {
|
||||
otherDoor = otherDoor.setValue(POWERED, Boolean.valueOf(isPowered))
|
||||
.setValue(OPEN, Boolean.valueOf(isPowered));
|
||||
if (isPowered)
|
||||
otherDoor = otherDoor.setValue(VISIBLE, false);
|
||||
pLevel.setBlock(otherPos, otherDoor, 2);
|
||||
}
|
||||
}
|
||||
|
||||
pLevel.setBlock(pPos, changedState, 2);
|
||||
}
|
||||
|
||||
public static boolean isDoorPowered(Level pLevel, BlockPos pPos, BlockState state) {
|
||||
boolean lower = state.getValue(HALF) == DoubleBlockHalf.LOWER;
|
||||
DoorHingeSide hinge = state.getValue(HINGE);
|
||||
Direction facing = state.getValue(FACING);
|
||||
BlockPos otherPos =
|
||||
pPos.relative(hinge == DoorHingeSide.LEFT ? facing.getClockWise() : facing.getCounterClockWise());
|
||||
BlockState otherDoor = pLevel.getBlockState(otherPos);
|
||||
|
||||
if (isDoubleDoor(state.cycle(OPEN), hinge, facing, otherDoor) && (pLevel.hasNeighborSignal(otherPos)
|
||||
|| pLevel.hasNeighborSignal(otherPos.relative(lower ? Direction.UP : Direction.DOWN))))
|
||||
return true;
|
||||
|
||||
return pLevel.hasNeighborSignal(pPos)
|
||||
|| pLevel.hasNeighborSignal(pPos.relative(lower ? Direction.UP : Direction.DOWN));
|
||||
}
|
||||
@Override
|
||||
public InteractionResult use(BlockState pState, Level pLevel, BlockPos pPos, Player pPlayer, InteractionHand pHand,
|
||||
BlockHitResult pHit) {
|
||||
|
||||
pState = pState.cycle(OPEN);
|
||||
if (pState.getValue(OPEN))
|
||||
pState = pState.setValue(VISIBLE, false);
|
||||
pLevel.setBlock(pPos, pState, 10);
|
||||
pLevel.gameEvent(pPlayer, isOpen(pState) ? GameEvent.BLOCK_OPEN : GameEvent.BLOCK_CLOSE, pPos);
|
||||
|
||||
DoorHingeSide hinge = pState.getValue(HINGE);
|
||||
Direction facing = pState.getValue(FACING);
|
||||
BlockPos otherPos =
|
||||
pPos.relative(hinge == DoorHingeSide.LEFT ? facing.getClockWise() : facing.getCounterClockWise());
|
||||
BlockState otherDoor = pLevel.getBlockState(otherPos);
|
||||
if (isDoubleDoor(pState, hinge, facing, otherDoor))
|
||||
use(otherDoor, pLevel, otherPos, pPlayer, pHand, pHit);
|
||||
else if (pState.getValue(OPEN))
|
||||
pLevel.levelEvent(pPlayer, getOpenSound(), pPos, 0);
|
||||
|
||||
return InteractionResult.sidedSuccess(pLevel.isClientSide);
|
||||
}
|
||||
public void deferUpdate(LevelAccessor level, BlockPos pos) {
|
||||
withBlockEntityDo(level, pos, sdte -> sdte.deferUpdate = true);
|
||||
}
|
||||
public static boolean isDoubleDoor(BlockState pState, DoorHingeSide hinge, Direction facing, BlockState otherDoor) {
|
||||
return otherDoor.getBlock() == pState.getBlock() && otherDoor.getValue(HINGE) != hinge
|
||||
&& otherDoor.getValue(FACING) == facing && otherDoor.getValue(OPEN) != pState.getValue(OPEN)
|
||||
&& otherDoor.getValue(HALF) == pState.getValue(HALF);
|
||||
}
|
||||
@Override
|
||||
public RenderShape getRenderShape(BlockState pState) {
|
||||
return pState.getValue(VISIBLE) ? RenderShape.MODEL : RenderShape.ENTITYBLOCK_ANIMATED;
|
||||
}
|
||||
private void playSound(Level pLevel, BlockPos pPos, boolean pIsOpening) {
|
||||
if (pIsOpening)
|
||||
pLevel.levelEvent((Player) null, this.getOpenSound(), pPos, 0);
|
||||
}
|
||||
private int getOpenSound() {
|
||||
return 1005;
|
||||
}
|
||||
@Nullable
|
||||
@Override
|
||||
public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {
|
||||
if (state.getValue(HALF) == DoubleBlockHalf.UPPER)
|
||||
return null;
|
||||
return IBE.super.newBlockEntity(pos, state);
|
||||
}
|
||||
@Override
|
||||
public Class<TFMGSlidingDoorBlockEntity> getBlockEntityClass() {
|
||||
return TFMGSlidingDoorBlockEntity.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockEntityType<? extends TFMGSlidingDoorBlockEntity> getBlockEntityType() {
|
||||
return TFMGBlockEntities.TFMG_SLIDING_DOOR.get();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
package com.drmangotea.tfmg.content.decoration.doors;
|
||||
|
||||
import com.simibubi.create.content.decoration.slidingDoor.SlidingDoorBlockEntity;
|
||||
import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour;
|
||||
import com.simibubi.create.foundation.utility.animation.LerpedFloat;
|
||||
import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.sounds.SoundEvents;
|
||||
import net.minecraft.sounds.SoundSource;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.DoorBlock;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.phys.AABB;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class TFMGSlidingDoorBlockEntity extends SlidingDoorBlockEntity {
|
||||
LerpedFloat animation;
|
||||
int bridgeTicks;
|
||||
boolean deferUpdate;
|
||||
public TFMGSlidingDoorBlockEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) {
|
||||
super(type, pos, state);
|
||||
animation = LerpedFloat.linear()
|
||||
.startWithValue(isOpen(state) ? 1 : 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
if (deferUpdate && !level.isClientSide()) {
|
||||
deferUpdate = false;
|
||||
BlockState blockState = getBlockState();
|
||||
blockState.neighborChanged(level, worldPosition, Blocks.AIR, worldPosition, false);
|
||||
}
|
||||
|
||||
super.tick();
|
||||
boolean open = isOpen(getBlockState());
|
||||
boolean wasSettled = animation.settled();
|
||||
animation.chase(open ? 1 : 0, .15f, Chaser.LINEAR);
|
||||
animation.tickChaser();
|
||||
|
||||
if (level.isClientSide()) {
|
||||
if (bridgeTicks < 2 && open)
|
||||
bridgeTicks++;
|
||||
else if (bridgeTicks > 0 && !open && isVisible(getBlockState()))
|
||||
bridgeTicks--;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!open && !wasSettled && animation.settled() && !isVisible(getBlockState()))
|
||||
showBlockModel();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AABB createRenderBoundingBox() {
|
||||
return super.createRenderBoundingBox().inflate(1);
|
||||
}
|
||||
|
||||
protected boolean isVisible(BlockState state) {
|
||||
return state.getOptionalValue(TFMGSlidingDoorBlock.VISIBLE)
|
||||
.orElse(true);
|
||||
}
|
||||
|
||||
protected boolean shouldRenderSpecial(BlockState state) {
|
||||
return !isVisible(state) || bridgeTicks != 0;
|
||||
}
|
||||
|
||||
protected void showBlockModel() {
|
||||
level.setBlock(worldPosition, getBlockState().setValue(TFMGSlidingDoorBlock.VISIBLE, true), 3);
|
||||
level.playSound(null, worldPosition, SoundEvents.IRON_DOOR_CLOSE, SoundSource.BLOCKS, .5f, 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBehaviours(List<BlockEntityBehaviour> behaviours) {}
|
||||
|
||||
public static boolean isOpen(BlockState state) {
|
||||
return state.getOptionalValue(DoorBlock.OPEN)
|
||||
.orElse(false);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
package com.drmangotea.tfmg.content.decoration.doors;
|
||||
|
||||
|
||||
import com.drmangotea.tfmg.registry.TFMGPartialModels;
|
||||
import com.jozufozu.flywheel.core.PartialModel;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||
import com.simibubi.create.foundation.blockEntity.renderer.SafeBlockEntityRenderer;
|
||||
import com.simibubi.create.foundation.render.CachedBufferer;
|
||||
import com.simibubi.create.foundation.render.SuperByteBuffer;
|
||||
import com.simibubi.create.foundation.utility.AngleHelper;
|
||||
import com.simibubi.create.foundation.utility.Couple;
|
||||
import com.simibubi.create.foundation.utility.Iterate;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider.Context;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.level.block.DoorBlock;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.properties.DoorHingeSide;
|
||||
import net.minecraft.world.level.block.state.properties.DoubleBlockHalf;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraftforge.registries.ForgeRegistries;
|
||||
|
||||
public class TFMGSlidingDoorRenderer extends SafeBlockEntityRenderer<TFMGSlidingDoorBlockEntity> {
|
||||
|
||||
public TFMGSlidingDoorRenderer(Context context) {}
|
||||
|
||||
@Override
|
||||
protected void renderSafe(TFMGSlidingDoorBlockEntity be, float partialTicks, PoseStack ms, MultiBufferSource buffer,
|
||||
int light, int overlay) {
|
||||
BlockState blockState = be.getBlockState();
|
||||
if (!be.shouldRenderSpecial(blockState))
|
||||
return;
|
||||
Direction facing = blockState.getValue(DoorBlock.FACING);
|
||||
Direction movementDirection = facing.getClockWise();
|
||||
if (blockState.getValue(DoorBlock.HINGE) == DoorHingeSide.LEFT)
|
||||
movementDirection = movementDirection.getOpposite();
|
||||
float value = be.animation.getValue(partialTicks);
|
||||
float value2 = Mth.clamp(value * 10, 0, 1);
|
||||
|
||||
VertexConsumer vb = buffer.getBuffer(RenderType.cutoutMipped());
|
||||
Vec3 offset = Vec3.atLowerCornerOf(movementDirection.getNormal())
|
||||
.scale(value * value * 13 / 16f)
|
||||
.add(Vec3.atLowerCornerOf(facing.getNormal())
|
||||
.scale(value2 * 1 / 32f));
|
||||
if (((TFMGSlidingDoorBlock) blockState.getBlock()).isFoldingDoor()) {
|
||||
Couple<PartialModel> partials =
|
||||
TFMGPartialModels.FOLDING_DOORS.get(ForgeRegistries.BLOCKS.getKey(blockState.getBlock()));
|
||||
if(partials==null)
|
||||
return;
|
||||
boolean flip = blockState.getValue(DoorBlock.HINGE) == DoorHingeSide.RIGHT;
|
||||
for (boolean left : Iterate.trueAndFalse) {
|
||||
SuperByteBuffer partial = CachedBufferer.partial(partials.get(left ^ flip), blockState);
|
||||
float f = flip ? -1 : 1;
|
||||
partial.translate(0, -1 / 512f, 0)
|
||||
.translate(Vec3.atLowerCornerOf(facing.getNormal())
|
||||
.scale(value2 * 1 / 32f));
|
||||
partial.rotateCentered(Direction.UP,
|
||||
Mth.DEG_TO_RAD * AngleHelper.horizontalAngle(facing.getClockWise()));
|
||||
|
||||
if (flip)
|
||||
partial.translate(0, 0, 1);
|
||||
partial.rotateY(91 * f * value * value);
|
||||
|
||||
if (!left)
|
||||
partial.translate(0, 0, f / 2f)
|
||||
.rotateY(-181 * f * value * value);
|
||||
|
||||
if (flip)
|
||||
partial.translate(0, 0, -1 / 2f);
|
||||
|
||||
partial.light(light)
|
||||
.renderInto(ms, vb);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
for (DoubleBlockHalf half : DoubleBlockHalf.values()) {
|
||||
CachedBufferer.block(blockState.setValue(DoorBlock.OPEN, false)
|
||||
.setValue(DoorBlock.HALF, half))
|
||||
.translate(0, half == DoubleBlockHalf.UPPER ? 1 - 1 / 512f : 0, 0)
|
||||
.translate(offset)
|
||||
.light(light)
|
||||
.renderInto(ms, vb);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,305 @@
|
||||
package com.drmangotea.tfmg.content.decoration.encased;
|
||||
|
||||
|
||||
import com.drmangotea.tfmg.registry.TFMGBlockEntities;
|
||||
import com.drmangotea.tfmg.registry.TFMGBlocks;
|
||||
import com.simibubi.create.content.contraptions.ITransformableBlock;
|
||||
import com.simibubi.create.content.contraptions.StructureTransform;
|
||||
import com.simibubi.create.content.decoration.encasing.EncasedBlock;
|
||||
import com.simibubi.create.content.kinetics.base.IRotate;
|
||||
import com.simibubi.create.content.kinetics.base.KineticBlockEntity;
|
||||
import com.simibubi.create.content.kinetics.base.RotatedPillarKineticBlock;
|
||||
import com.simibubi.create.content.kinetics.simpleRelays.CogWheelBlock;
|
||||
import com.simibubi.create.content.kinetics.simpleRelays.ICogWheel;
|
||||
import com.simibubi.create.content.kinetics.simpleRelays.SimpleKineticBlockEntity;
|
||||
import com.simibubi.create.content.schematics.requirement.ISpecialBlockItemRequirement;
|
||||
import com.simibubi.create.content.schematics.requirement.ItemRequirement;
|
||||
import com.simibubi.create.foundation.block.IBE;
|
||||
import com.simibubi.create.foundation.utility.Iterate;
|
||||
import com.simibubi.create.foundation.utility.VoxelShaper;
|
||||
import com.tterrag.registrate.util.entry.BlockEntityEntry;
|
||||
import com.tterrag.registrate.util.entry.BlockEntry;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.InteractionResult;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.context.BlockPlaceContext;
|
||||
import net.minecraft.world.item.context.UseOnContext;
|
||||
import net.minecraft.world.level.BlockGetter;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.LevelReader;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.Mirror;
|
||||
import net.minecraft.world.level.block.Rotation;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.StateDefinition;
|
||||
import net.minecraft.world.level.block.state.properties.BooleanProperty;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.minecraft.world.phys.HitResult;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class TFMGEncasedCogwheelBlock extends RotatedPillarKineticBlock
|
||||
implements ICogWheel, IBE<SimpleKineticBlockEntity>, ISpecialBlockItemRequirement, ITransformableBlock, EncasedBlock {
|
||||
public static final BooleanProperty TOP_SHAFT = BooleanProperty.create("top_shaft");
|
||||
public static final BooleanProperty BOTTOM_SHAFT = BooleanProperty.create("bottom_shaft");
|
||||
protected final boolean isLarge;
|
||||
private final Supplier<Block> casing;
|
||||
private final BlockEntry<?> blockSmall;
|
||||
private final BlockEntry<?> blockLarge;
|
||||
private final BlockEntityEntry<SimpleKineticBlockEntity> beSmall;
|
||||
private final BlockEntityEntry<SimpleKineticBlockEntity> beLarge;
|
||||
|
||||
public static TFMGEncasedCogwheelBlock steel(Properties properties, boolean large, Supplier<Block> casing) {
|
||||
return new TFMGEncasedCogwheelBlock(properties, large, casing, TFMGBlocks.STEEL_COGWHEEL, TFMGBlocks.LARGE_STEEL_COGWHEEL, TFMGBlockEntities.ENCASED_STEEL_COGWHEEL, TFMGBlockEntities.ENCASED_LARGE_STEEL_COGWHEEL);
|
||||
}
|
||||
|
||||
public static TFMGEncasedCogwheelBlock aluminum(Properties properties, boolean large, Supplier<Block> casing) {
|
||||
return new TFMGEncasedCogwheelBlock(properties, large, casing, TFMGBlocks.ALUMINUM_COGWHEEL, TFMGBlocks.LARGE_ALUMINUM_COGWHEEL, TFMGBlockEntities.ENCASED_ALUMINUM_COGWHEEL, TFMGBlockEntities.ENCASED_LARGE_ALUMINUM_COGWHEEL);
|
||||
}
|
||||
|
||||
public TFMGEncasedCogwheelBlock(Properties properties, boolean large, Supplier<Block> casing, BlockEntry<?> blockSmall, BlockEntry<?> blockLarge, BlockEntityEntry<SimpleKineticBlockEntity> beSmall, BlockEntityEntry<SimpleKineticBlockEntity> beLarge) {
|
||||
super(properties);
|
||||
|
||||
this.beSmall = beSmall;
|
||||
this.beLarge = beLarge;
|
||||
|
||||
this.blockSmall = blockSmall;
|
||||
this.blockLarge = blockLarge;
|
||||
|
||||
isLarge = large;
|
||||
this.casing = casing;
|
||||
registerDefaultState(defaultBlockState().setValue(TOP_SHAFT, false)
|
||||
.setValue(BOTTOM_SHAFT, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
|
||||
super.createBlockStateDefinition(builder.add(TOP_SHAFT, BOTTOM_SHAFT));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getCloneItemStack(BlockState state, HitResult target, BlockGetter world, BlockPos pos, Player player) {
|
||||
if (target instanceof BlockHitResult)
|
||||
return ((BlockHitResult) target).getDirection()
|
||||
.getAxis() != getRotationAxis(state)
|
||||
? isLarge ? blockLarge.asStack() : blockSmall.asStack()
|
||||
: getCasing().asItem().getDefaultInstance();
|
||||
return super.getCloneItemStack(state, target, world, pos, player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getStateForPlacement(BlockPlaceContext context) {
|
||||
BlockState placedOn = context.getLevel()
|
||||
.getBlockState(context.getClickedPos()
|
||||
.relative(context.getClickedFace()
|
||||
.getOpposite()));
|
||||
BlockState stateForPlacement = super.getStateForPlacement(context);
|
||||
if (ICogWheel.isSmallCog(placedOn))
|
||||
stateForPlacement =
|
||||
stateForPlacement.setValue(AXIS, ((IRotate) placedOn.getBlock()).getRotationAxis(placedOn));
|
||||
return stateForPlacement;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean skipRendering(BlockState pState, BlockState pAdjacentBlockState, Direction pDirection) {
|
||||
return pState.getBlock() == pAdjacentBlockState.getBlock()
|
||||
&& pState.getValue(AXIS) == pAdjacentBlockState.getValue(AXIS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InteractionResult onWrenched(BlockState state, UseOnContext context) {
|
||||
if (context.getClickedFace()
|
||||
.getAxis() != state.getValue(AXIS))
|
||||
return super.onWrenched(state, context);
|
||||
|
||||
Level level = context.getLevel();
|
||||
if (level.isClientSide)
|
||||
return InteractionResult.SUCCESS;
|
||||
|
||||
BlockPos pos = context.getClickedPos();
|
||||
KineticBlockEntity.switchToBlockState(level, pos, state.cycle(context.getClickedFace()
|
||||
.getAxisDirection() == Direction.AxisDirection.POSITIVE ? TOP_SHAFT : BOTTOM_SHAFT));
|
||||
playRotateSound(level, pos);
|
||||
return InteractionResult.SUCCESS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getRotatedBlockState(BlockState originalState, Direction targetedFace) {
|
||||
originalState = swapShaftsForRotation(originalState, Rotation.CLOCKWISE_90, targetedFace.getAxis());
|
||||
return originalState.setValue(RotatedPillarKineticBlock.AXIS,
|
||||
VoxelShaper
|
||||
.axisAsFace(originalState.getValue(RotatedPillarKineticBlock.AXIS))
|
||||
.getClockWise(targetedFace.getAxis())
|
||||
.getAxis());
|
||||
}
|
||||
|
||||
@Override
|
||||
public InteractionResult onSneakWrenched(BlockState state, UseOnContext context) {
|
||||
if (context.getLevel().isClientSide)
|
||||
return InteractionResult.SUCCESS;
|
||||
context.getLevel()
|
||||
.levelEvent(2001, context.getClickedPos(), Block.getId(state));
|
||||
KineticBlockEntity.switchToBlockState(context.getLevel(), context.getClickedPos(),
|
||||
(isLarge ? blockLarge : blockSmall).getDefaultState()
|
||||
.setValue(AXIS, state.getValue(AXIS)));
|
||||
return InteractionResult.SUCCESS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasShaftTowards(LevelReader world, BlockPos pos, BlockState state, Direction face) {
|
||||
return face.getAxis() == state.getValue(AXIS)
|
||||
&& state.getValue(face.getAxisDirection() == Direction.AxisDirection.POSITIVE ? TOP_SHAFT : BOTTOM_SHAFT);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean areStatesKineticallyEquivalent(BlockState oldState, BlockState newState) {
|
||||
if (newState.getBlock() instanceof TFMGEncasedCogwheelBlock
|
||||
&& oldState.getBlock() instanceof TFMGEncasedCogwheelBlock) {
|
||||
if (newState.getValue(TOP_SHAFT) != oldState.getValue(TOP_SHAFT))
|
||||
return false;
|
||||
if (newState.getValue(BOTTOM_SHAFT) != oldState.getValue(BOTTOM_SHAFT))
|
||||
return false;
|
||||
}
|
||||
return super.areStatesKineticallyEquivalent(oldState, newState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSmallCog() {
|
||||
return !isLarge;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLargeCog() {
|
||||
return isLarge;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canSurvive(BlockState state, LevelReader worldIn, BlockPos pos) {
|
||||
return CogWheelBlock.isValidCogwheelPosition(ICogWheel.isLargeCog(state), worldIn, pos, state.getValue(AXIS));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Direction.Axis getRotationAxis(BlockState state) {
|
||||
return state.getValue(AXIS);
|
||||
}
|
||||
|
||||
public BlockState swapShafts(BlockState state) {
|
||||
boolean bottom = state.getValue(BOTTOM_SHAFT);
|
||||
boolean top = state.getValue(TOP_SHAFT);
|
||||
state = state.setValue(BOTTOM_SHAFT, top);
|
||||
state = state.setValue(TOP_SHAFT, bottom);
|
||||
return state;
|
||||
}
|
||||
|
||||
public BlockState swapShaftsForRotation(BlockState state, Rotation rotation, Direction.Axis rotationAxis) {
|
||||
if (rotation == Rotation.NONE) {
|
||||
return state;
|
||||
}
|
||||
|
||||
Direction.Axis axis = state.getValue(AXIS);
|
||||
if (axis == rotationAxis) {
|
||||
return state;
|
||||
}
|
||||
if (rotation == Rotation.CLOCKWISE_180) {
|
||||
return swapShafts(state);
|
||||
}
|
||||
boolean clockwise = rotation == Rotation.CLOCKWISE_90;
|
||||
|
||||
if (rotationAxis == Direction.Axis.X) {
|
||||
if (axis == Direction.Axis.Z && !clockwise
|
||||
|| axis == Direction.Axis.Y && clockwise) {
|
||||
return swapShafts(state);
|
||||
}
|
||||
} else if (rotationAxis == Direction.Axis.Y) {
|
||||
if (axis == Direction.Axis.X && !clockwise
|
||||
|| axis == Direction.Axis.Z && clockwise) {
|
||||
return swapShafts(state);
|
||||
}
|
||||
} else if (rotationAxis == Direction.Axis.Z) {
|
||||
if (axis == Direction.Axis.Y && !clockwise
|
||||
|| axis == Direction.Axis.X && clockwise) {
|
||||
return swapShafts(state);
|
||||
}
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState mirror(BlockState state, Mirror mirror) {
|
||||
Direction.Axis axis = state.getValue(AXIS);
|
||||
if (axis == Direction.Axis.X && mirror == Mirror.FRONT_BACK
|
||||
|| axis == Direction.Axis.Z && mirror == Mirror.LEFT_RIGHT) {
|
||||
return swapShafts(state);
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState rotate(BlockState state, Rotation rotation) {
|
||||
state = swapShaftsForRotation(state, rotation, Direction.Axis.Y);
|
||||
return super.rotate(state, rotation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState transform(BlockState state, StructureTransform transform) {
|
||||
if (transform.mirror != null) {
|
||||
state = mirror(state, transform.mirror);
|
||||
}
|
||||
|
||||
if (transform.rotationAxis == Direction.Axis.Y) {
|
||||
return rotate(state, transform.rotation);
|
||||
}
|
||||
|
||||
state = swapShaftsForRotation(state, transform.rotation, transform.rotationAxis);
|
||||
state = state.setValue(AXIS, transform.rotateAxis(state.getValue(AXIS)));
|
||||
return state;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemRequirement getRequiredItems(BlockState state, BlockEntity be) {
|
||||
return ItemRequirement
|
||||
.of(isLarge ? blockLarge.getDefaultState() : blockSmall.getDefaultState(), be);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<SimpleKineticBlockEntity> getBlockEntityClass() {
|
||||
return SimpleKineticBlockEntity.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockEntityType<? extends SimpleKineticBlockEntity> getBlockEntityType() {
|
||||
return isLarge ? beLarge.get() : beSmall.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Block getCasing() {
|
||||
return casing.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleEncasing(BlockState state, Level level, BlockPos pos, ItemStack heldItem, Player player, InteractionHand hand,
|
||||
BlockHitResult ray) {
|
||||
BlockState encasedState = defaultBlockState()
|
||||
.setValue(AXIS, state.getValue(AXIS));
|
||||
|
||||
for (Direction d : Iterate.directionsInAxis(state.getValue(AXIS))) {
|
||||
BlockState adjacentState = level.getBlockState(pos.relative(d));
|
||||
if (!(adjacentState.getBlock() instanceof IRotate))
|
||||
continue;
|
||||
IRotate def = (IRotate) adjacentState.getBlock();
|
||||
if (!def.hasShaftTowards(level, pos.relative(d), adjacentState, d.getOpposite()))
|
||||
continue;
|
||||
encasedState =
|
||||
encasedState.cycle(d.getAxisDirection() == Direction.AxisDirection.POSITIVE ? TFMGEncasedCogwheelBlock.TOP_SHAFT
|
||||
: TFMGEncasedCogwheelBlock.BOTTOM_SHAFT);
|
||||
}
|
||||
|
||||
KineticBlockEntity.switchToBlockState(level, pos, encasedState);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
package com.drmangotea.tfmg.content.decoration.encased;
|
||||
|
||||
|
||||
import com.drmangotea.tfmg.registry.TFMGBlockEntities;
|
||||
import com.simibubi.create.AllBlocks;
|
||||
import com.simibubi.create.content.decoration.encasing.EncasedBlock;
|
||||
import com.simibubi.create.content.kinetics.base.AbstractEncasedShaftBlock;
|
||||
import com.simibubi.create.content.kinetics.base.KineticBlockEntity;
|
||||
import com.simibubi.create.content.kinetics.base.RotatedPillarKineticBlock;
|
||||
import com.simibubi.create.content.schematics.requirement.ISpecialBlockItemRequirement;
|
||||
import com.simibubi.create.content.schematics.requirement.ItemRequirement;
|
||||
import com.simibubi.create.foundation.block.IBE;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.InteractionResult;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.context.UseOnContext;
|
||||
import net.minecraft.world.level.BlockGetter;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.minecraft.world.phys.HitResult;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class TFMGEncasedShaftBlock extends AbstractEncasedShaftBlock
|
||||
implements IBE<KineticBlockEntity>, ISpecialBlockItemRequirement, EncasedBlock {
|
||||
|
||||
private final Supplier<Block> casing;
|
||||
|
||||
public TFMGEncasedShaftBlock(Properties properties, Supplier<Block> casing) {
|
||||
super(properties);
|
||||
this.casing = casing;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InteractionResult onSneakWrenched(BlockState state, UseOnContext context) {
|
||||
if (context.getLevel().isClientSide)
|
||||
return InteractionResult.SUCCESS;
|
||||
context.getLevel()
|
||||
.levelEvent(2001, context.getClickedPos(), Block.getId(state));
|
||||
KineticBlockEntity.switchToBlockState(context.getLevel(), context.getClickedPos(),
|
||||
AllBlocks.SHAFT.getDefaultState()
|
||||
.setValue(AXIS, state.getValue(AXIS)));
|
||||
return InteractionResult.SUCCESS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getCloneItemStack(BlockState state, HitResult target, BlockGetter world, BlockPos pos, Player player) {
|
||||
if (target instanceof BlockHitResult)
|
||||
return ((BlockHitResult) target).getDirection()
|
||||
.getAxis() == getRotationAxis(state) ? AllBlocks.SHAFT.asStack() : getCasing().asItem().getDefaultInstance();
|
||||
return super.getCloneItemStack(state, target, world, pos, player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemRequirement getRequiredItems(BlockState state, BlockEntity be) {
|
||||
return ItemRequirement.of(AllBlocks.SHAFT.getDefaultState(), be);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<KineticBlockEntity> getBlockEntityClass() {
|
||||
return KineticBlockEntity.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockEntityType<? extends KineticBlockEntity> getBlockEntityType() {
|
||||
return TFMGBlockEntities.TFMG_ENCASED_SHAFT.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Block getCasing() {
|
||||
return casing.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleEncasing(BlockState state, Level level, BlockPos pos, ItemStack heldItem, Player player, InteractionHand hand,
|
||||
BlockHitResult ray) {
|
||||
KineticBlockEntity.switchToBlockState(level, pos, defaultBlockState()
|
||||
.setValue(RotatedPillarKineticBlock.AXIS, state.getValue(RotatedPillarKineticBlock.AXIS)));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package com.drmangotea.tfmg.content.decoration.flywheels;
|
||||
|
||||
|
||||
import com.drmangotea.tfmg.registry.TFMGBlockEntities;
|
||||
import com.simibubi.create.AllShapes;
|
||||
import com.simibubi.create.content.kinetics.base.RotatedPillarKineticBlock;
|
||||
import com.simibubi.create.foundation.block.IBE;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.core.Direction.Axis;
|
||||
import net.minecraft.world.level.BlockGetter;
|
||||
import net.minecraft.world.level.LevelReader;
|
||||
import net.minecraft.world.level.block.RenderShape;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.phys.shapes.CollisionContext;
|
||||
import net.minecraft.world.phys.shapes.VoxelShape;
|
||||
|
||||
public class TFMGFlywheelBlock extends RotatedPillarKineticBlock implements IBE<TFMGFlywheelBlockEntity> {
|
||||
|
||||
public TFMGFlywheelBlock(Properties properties) {
|
||||
super(properties);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<TFMGFlywheelBlockEntity> getBlockEntityClass() {
|
||||
return TFMGFlywheelBlockEntity.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VoxelShape getShape(BlockState pState, BlockGetter pLevel, BlockPos pPos, CollisionContext pContext) {
|
||||
return AllShapes.LARGE_GEAR.get(pState.getValue(AXIS));
|
||||
}
|
||||
|
||||
@Override
|
||||
public RenderShape getRenderShape(BlockState pState) {
|
||||
return RenderShape.ENTITYBLOCK_ANIMATED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockEntityType<? extends TFMGFlywheelBlockEntity> getBlockEntityType() {
|
||||
return TFMGBlockEntities.TFMG_FLYWHEEL.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasShaftTowards(LevelReader world, BlockPos pos, BlockState state, Direction face) {
|
||||
return face.getAxis() == getRotationAxis(state);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Axis getRotationAxis(BlockState state) {
|
||||
return state.getValue(AXIS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getParticleTargetRadius() {
|
||||
return 2f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getParticleInitialRadius() {
|
||||
return 1.75f;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package com.drmangotea.tfmg.content.decoration.flywheels;
|
||||
|
||||
import com.simibubi.create.content.kinetics.base.KineticBlockEntity;
|
||||
import com.simibubi.create.foundation.utility.animation.LerpedFloat;
|
||||
import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.phys.AABB;
|
||||
|
||||
public class TFMGFlywheelBlockEntity extends KineticBlockEntity {
|
||||
|
||||
LerpedFloat visualSpeed = LerpedFloat.linear();
|
||||
float angle;
|
||||
|
||||
public TFMGFlywheelBlockEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) {
|
||||
super(type, pos, state);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AABB createRenderBoundingBox() {
|
||||
return super.createRenderBoundingBox().inflate(2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(CompoundTag compound, boolean clientPacket) {
|
||||
super.write(compound, clientPacket);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void read(CompoundTag compound, boolean clientPacket) {
|
||||
super.read(compound, clientPacket);
|
||||
if (clientPacket)
|
||||
visualSpeed.chase(getGeneratedSpeed(), 1 / 64f, Chaser.EXP);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
super.tick();
|
||||
|
||||
if (!level.isClientSide)
|
||||
return;
|
||||
|
||||
|
||||
|
||||
float targetSpeed = getSpeed();
|
||||
visualSpeed.updateChaseTarget(targetSpeed);
|
||||
visualSpeed.tickChaser();
|
||||
angle += visualSpeed.getValue() * 3 / 10f;
|
||||
angle %= 360;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
package com.drmangotea.tfmg.content.decoration.flywheels;
|
||||
|
||||
import com.jozufozu.flywheel.api.MaterialManager;
|
||||
import com.jozufozu.flywheel.api.instance.DynamicInstance;
|
||||
import com.jozufozu.flywheel.core.materials.model.ModelData;
|
||||
import com.jozufozu.flywheel.util.transform.TransformStack;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.simibubi.create.content.kinetics.base.KineticBlockEntityInstance;
|
||||
import com.simibubi.create.content.kinetics.base.flwdata.RotatingData;
|
||||
import com.simibubi.create.foundation.utility.AngleHelper;
|
||||
import com.simibubi.create.foundation.utility.AnimationTickHolder;
|
||||
import net.minecraft.core.Direction;
|
||||
|
||||
public class TFMGFlywheelInstance extends KineticBlockEntityInstance<TFMGFlywheelBlockEntity> implements DynamicInstance {
|
||||
|
||||
protected final RotatingData shaft;
|
||||
protected final ModelData wheel;
|
||||
protected float lastAngle = Float.NaN;
|
||||
|
||||
public TFMGFlywheelInstance(MaterialManager materialManager, TFMGFlywheelBlockEntity blockEntity) {
|
||||
super(materialManager, blockEntity);
|
||||
|
||||
shaft = setup(getRotatingMaterial().getModel(shaft())
|
||||
.createInstance());
|
||||
wheel = getTransformMaterial().getModel(blockState)
|
||||
.createInstance();
|
||||
|
||||
animate(blockEntity.angle);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beginFrame() {
|
||||
|
||||
float partialTicks = AnimationTickHolder.getPartialTicks();
|
||||
|
||||
float speed = blockEntity.visualSpeed.getValue(partialTicks) * 3 / 10f;
|
||||
float angle = blockEntity.angle + speed * partialTicks;
|
||||
|
||||
if (Math.abs(angle - lastAngle) < 0.001)
|
||||
return;
|
||||
|
||||
animate(angle);
|
||||
|
||||
lastAngle = angle;
|
||||
}
|
||||
|
||||
private void animate(float angle) {
|
||||
PoseStack ms = new PoseStack();
|
||||
TransformStack msr = TransformStack.cast(ms);
|
||||
|
||||
msr.translate(getInstancePosition());
|
||||
msr.centre()
|
||||
.rotate(Direction.get(Direction.AxisDirection.POSITIVE, axis), AngleHelper.rad(angle))
|
||||
.unCentre();
|
||||
|
||||
wheel.setTransform(ms);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update() {
|
||||
updateRotation(shaft);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateLight() {
|
||||
relight(pos, shaft, wheel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
shaft.delete();
|
||||
wheel.delete();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package com.drmangotea.tfmg.content.decoration.flywheels;
|
||||
|
||||
import com.jozufozu.flywheel.backend.Backend;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||
import com.simibubi.create.content.kinetics.base.KineticBlockEntityRenderer;
|
||||
import com.simibubi.create.foundation.render.CachedBufferer;
|
||||
import com.simibubi.create.foundation.render.SuperByteBuffer;
|
||||
import com.simibubi.create.foundation.utility.AngleHelper;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
|
||||
public class TFMGFlywheelRenderer extends KineticBlockEntityRenderer<TFMGFlywheelBlockEntity> {
|
||||
|
||||
public TFMGFlywheelRenderer(BlockEntityRendererProvider.Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderSafe(TFMGFlywheelBlockEntity be, float partialTicks, PoseStack ms, MultiBufferSource buffer,
|
||||
int light, int overlay) {
|
||||
super.renderSafe(be, partialTicks, ms, buffer, light, overlay);
|
||||
|
||||
if (Backend.canUseInstancing(be.getLevel()))
|
||||
return;
|
||||
|
||||
BlockState blockState = be.getBlockState();
|
||||
|
||||
float speed = be.visualSpeed.getValue(partialTicks) * 3 / 10f;
|
||||
float angle = be.angle + speed * partialTicks;
|
||||
|
||||
VertexConsumer vb = buffer.getBuffer(RenderType.solid());
|
||||
renderFlywheel(be, ms, light, blockState, angle, vb);
|
||||
}
|
||||
|
||||
private void renderFlywheel(TFMGFlywheelBlockEntity be, PoseStack ms, int light, BlockState blockState, float angle,
|
||||
VertexConsumer vb) {
|
||||
SuperByteBuffer wheel = CachedBufferer.block(blockState);
|
||||
kineticRotationTransform(wheel, be, getRotationAxisOf(be), AngleHelper.rad(angle), light);
|
||||
wheel.renderInto(ms, vb);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BlockState getRenderedBlockState(TFMGFlywheelBlockEntity be) {
|
||||
return shaft(getRotationAxisOf(be));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package com.drmangotea.tfmg.content.decoration.gearbox;
|
||||
|
||||
|
||||
import com.drmangotea.tfmg.registry.TFMGBlockEntities;
|
||||
import com.drmangotea.tfmg.registry.TFMGItems;
|
||||
import com.simibubi.create.content.kinetics.base.RotatedPillarKineticBlock;
|
||||
import com.simibubi.create.content.kinetics.gearbox.GearboxBlockEntity;
|
||||
import com.simibubi.create.foundation.block.IBE;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.core.Direction.Axis;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.context.BlockPlaceContext;
|
||||
import net.minecraft.world.level.BlockGetter;
|
||||
import net.minecraft.world.level.LevelReader;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.material.PushReaction;
|
||||
import net.minecraft.world.phys.HitResult;
|
||||
|
||||
public class SteelGearboxBlock extends RotatedPillarKineticBlock implements IBE<GearboxBlockEntity> {
|
||||
|
||||
public SteelGearboxBlock(Properties properties) {
|
||||
super(properties);
|
||||
}
|
||||
@Override
|
||||
public PushReaction getPistonPushReaction(BlockState state) {
|
||||
return PushReaction.PUSH_ONLY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getCloneItemStack(BlockState state, HitResult target, BlockGetter world, BlockPos pos,
|
||||
Player player) {
|
||||
if (state.getValue(AXIS).isVertical())
|
||||
return super.getCloneItemStack(state, target, world, pos, player);
|
||||
return new ItemStack(TFMGItems.STEEL_VERTICAL_GEARBOX.get());
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getStateForPlacement(BlockPlaceContext context) {
|
||||
return defaultBlockState().setValue(AXIS, Axis.Y);
|
||||
}
|
||||
|
||||
// IRotate:
|
||||
|
||||
@Override
|
||||
public boolean hasShaftTowards(LevelReader world, BlockPos pos, BlockState state, Direction face) {
|
||||
return face.getAxis() != state.getValue(AXIS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Axis getRotationAxis(BlockState state) {
|
||||
return state.getValue(AXIS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<GearboxBlockEntity> getBlockEntityClass() {
|
||||
return GearboxBlockEntity.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockEntityType<? extends GearboxBlockEntity> getBlockEntityType() {
|
||||
return TFMGBlockEntities.STEEL_GEARBOX.get();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package com.drmangotea.tfmg.content.decoration.gearbox;
|
||||
|
||||
|
||||
import com.drmangotea.tfmg.registry.TFMGBlocks;
|
||||
import com.simibubi.create.content.kinetics.base.IRotate;
|
||||
import com.simibubi.create.foundation.utility.Iterate;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.core.Direction.Axis;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.BlockItem;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class SteelVerticalGearboxItem extends BlockItem {
|
||||
|
||||
public SteelVerticalGearboxItem(Properties builder) {
|
||||
super(TFMGBlocks.STEEL_GEARBOX.get(), builder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescriptionId() {
|
||||
return "item.tfmg.steel_vertical_gearbox";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerBlocks(Map<Block, Item> p_195946_1_, Item p_195946_2_) {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean updateCustomBlockEntityTag(BlockPos pos, Level world, Player player, ItemStack stack, BlockState state) {
|
||||
Axis prefferedAxis = null;
|
||||
for (Direction side : Iterate.horizontalDirections) {
|
||||
BlockState blockState = world.getBlockState(pos.relative(side));
|
||||
if (blockState.getBlock() instanceof IRotate) {
|
||||
if (((IRotate) blockState.getBlock()).hasShaftTowards(world, pos.relative(side), blockState,
|
||||
side.getOpposite()))
|
||||
if (prefferedAxis != null && prefferedAxis != side.getAxis()) {
|
||||
prefferedAxis = null;
|
||||
break;
|
||||
} else {
|
||||
prefferedAxis = side.getAxis();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Axis axis = prefferedAxis == null ? player.getDirection()
|
||||
.getClockWise()
|
||||
.getAxis() : prefferedAxis == Axis.X ? Axis.Z : Axis.X;
|
||||
world.setBlockAndUpdate(pos, state.setValue(BlockStateProperties.AXIS, axis));
|
||||
return super.updateCustomBlockEntityTag(pos, world, player, stack, state);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package com.drmangotea.tfmg.content.decoration.pipes;
|
||||
|
||||
import com.drmangotea.tfmg.registry.TFMGBlockEntities;
|
||||
import com.simibubi.create.content.fluids.FluidTransportBehaviour;
|
||||
import com.simibubi.create.content.fluids.pipes.EncasedPipeBlock;
|
||||
import com.simibubi.create.content.fluids.pipes.FluidPipeBlockEntity;
|
||||
import com.simibubi.create.foundation.utility.Iterate;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.world.InteractionResult;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.context.UseOnContext;
|
||||
import net.minecraft.world.level.BlockGetter;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.phys.HitResult;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class TFMGEncasedPipeBlock extends EncasedPipeBlock {
|
||||
|
||||
public final TFMGPipes.PipeMaterial material;
|
||||
public TFMGEncasedPipeBlock(Properties p_i48339_1_, Supplier<Block> casing, TFMGPipes.PipeMaterial material) {
|
||||
super(p_i48339_1_, casing);
|
||||
this.material = material;
|
||||
}
|
||||
@Override
|
||||
public ItemStack getCloneItemStack(BlockState state, HitResult target, BlockGetter world, BlockPos pos, Player player) {
|
||||
return TFMGPipes.TFMG_PIPES.get(material).get(0).asStack();
|
||||
}
|
||||
@Override
|
||||
public InteractionResult onWrenched(BlockState state, UseOnContext context) {
|
||||
Level world = context.getLevel();
|
||||
BlockPos pos = context.getClickedPos();
|
||||
|
||||
if (world.isClientSide)
|
||||
return InteractionResult.SUCCESS;
|
||||
|
||||
context.getLevel()
|
||||
.levelEvent(2001, context.getClickedPos(), Block.getId(state));
|
||||
BlockState equivalentPipe = transferSixWayProperties(state, TFMGPipes.TFMG_PIPES.get(material).get(0).getDefaultState());
|
||||
|
||||
Direction firstFound = Direction.UP;
|
||||
for (Direction d : Iterate.directions)
|
||||
if (state.getValue(FACING_TO_PROPERTY_MAP.get(d))) {
|
||||
firstFound = d;
|
||||
break;
|
||||
}
|
||||
FluidTransportBehaviour.cacheFlows(world, pos);
|
||||
world.setBlockAndUpdate(pos, ((TFMGPipeBlock)TFMGPipes.TFMG_PIPES.get(material).get(0).get())
|
||||
.updateBlockState(equivalentPipe, firstFound, null, world, pos));
|
||||
FluidTransportBehaviour.loadFlows(world, pos);
|
||||
return InteractionResult.SUCCESS;
|
||||
}
|
||||
@Override
|
||||
public Class<FluidPipeBlockEntity> getBlockEntityClass() {
|
||||
return FluidPipeBlockEntity.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockEntityType<? extends FluidPipeBlockEntity> getBlockEntityType() {
|
||||
return TFMGBlockEntities.ENCASED_TFMG_PIPE.get();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.drmangotea.tfmg.content.decoration.pipes;
|
||||
|
||||
|
||||
import com.drmangotea.tfmg.registry.TFMGBlockEntities;
|
||||
import com.simibubi.create.content.fluids.pipes.IAxisPipe;
|
||||
import com.simibubi.create.content.fluids.pipes.valve.FluidValveBlock;
|
||||
import com.simibubi.create.content.fluids.pipes.valve.FluidValveBlockEntity;
|
||||
import com.simibubi.create.foundation.block.IBE;
|
||||
import com.simibubi.create.foundation.block.ProperWaterloggedBlock;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
import net.minecraft.world.level.block.state.properties.BooleanProperty;
|
||||
|
||||
public class TFMGFluidValveBlock extends FluidValveBlock
|
||||
implements IAxisPipe, IBE<FluidValveBlockEntity>, ProperWaterloggedBlock {
|
||||
|
||||
public static final BooleanProperty ENABLED = BooleanProperty.create("enabled");
|
||||
|
||||
public TFMGFluidValveBlock(Properties properties) {
|
||||
super(properties);
|
||||
registerDefaultState(defaultBlockState().setValue(ENABLED, false)
|
||||
.setValue(WATERLOGGED, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<FluidValveBlockEntity> getBlockEntityClass() {
|
||||
return FluidValveBlockEntity.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockEntityType<? extends FluidValveBlockEntity> getBlockEntityType() {
|
||||
return TFMGBlockEntities.TFMG_FLUID_VALVE.get();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
package com.drmangotea.tfmg.content.decoration.pipes;
|
||||
|
||||
|
||||
import com.drmangotea.tfmg.registry.TFMGBlockEntities;
|
||||
import com.simibubi.create.AllBlocks;
|
||||
import com.simibubi.create.content.fluids.FluidTransportBehaviour;
|
||||
import com.simibubi.create.content.fluids.pipes.EncasedPipeBlock;
|
||||
import com.simibubi.create.content.fluids.pipes.FluidPipeBlock;
|
||||
import com.simibubi.create.content.fluids.pipes.GlassFluidPipeBlock;
|
||||
import com.simibubi.create.content.fluids.pipes.StraightPipeBlockEntity;
|
||||
import com.simibubi.create.content.schematics.requirement.ItemRequirement;
|
||||
import com.simibubi.create.foundation.utility.Iterate;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.InteractionResult;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.BlockGetter;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.LevelAccessor;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.properties.BooleanProperty;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.minecraft.world.phys.HitResult;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class TFMGGlassPipeBlock extends GlassFluidPipeBlock {
|
||||
|
||||
public final TFMGPipes.PipeMaterial material;
|
||||
|
||||
public TFMGGlassPipeBlock(Properties p_i48339_1_, TFMGPipes.PipeMaterial material) {
|
||||
super(p_i48339_1_);
|
||||
this.material = material;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemRequirement getRequiredItems(BlockState state, BlockEntity te) {
|
||||
return ItemRequirement.of(TFMGPipes.TFMG_PIPES.get(material).get(0).getDefaultState(), te);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getCloneItemStack(BlockState state, HitResult target, BlockGetter world, BlockPos pos,
|
||||
Player player) {
|
||||
return TFMGPipes.TFMG_PIPES.get(material).get(0).asStack();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState toRegularPipe(LevelAccessor world, BlockPos pos, BlockState state) {
|
||||
Direction side = Direction.get(Direction.AxisDirection.POSITIVE, state.getValue(AXIS));
|
||||
Map<Direction, BooleanProperty> facingToPropertyMap = FluidPipeBlock.PROPERTY_BY_DIRECTION;
|
||||
return ((TFMGPipeBlock) TFMGPipes.TFMG_PIPES.get(material).get(0).get())
|
||||
.updateBlockState(TFMGPipes.TFMG_PIPES.get(material).get(0).getDefaultState()
|
||||
.setValue(facingToPropertyMap.get(side), true)
|
||||
.setValue(facingToPropertyMap.get(side.getOpposite()), true), side, null, world, pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand,
|
||||
BlockHitResult hit) {
|
||||
if (!AllBlocks.COPPER_CASING.isIn(player.getItemInHand(hand)))
|
||||
return InteractionResult.PASS;
|
||||
if (world.isClientSide)
|
||||
return InteractionResult.SUCCESS;
|
||||
BlockState newState = TFMGPipes.TFMG_PIPES.get(material).get(1).getDefaultState();
|
||||
for (Direction d : Iterate.directionsInAxis(getAxis(state)))
|
||||
newState = newState.setValue(EncasedPipeBlock.FACING_TO_PROPERTY_MAP.get(d), true);
|
||||
FluidTransportBehaviour.cacheFlows(world, pos);
|
||||
world.setBlockAndUpdate(pos, newState);
|
||||
FluidTransportBehaviour.loadFlows(world, pos);
|
||||
return InteractionResult.SUCCESS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<StraightPipeBlockEntity> getBlockEntityClass() {
|
||||
return StraightPipeBlockEntity.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockEntityType<? extends StraightPipeBlockEntity> getBlockEntityType() {
|
||||
return TFMGBlockEntities.GLASS_TFMG_PIPE.get();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
package com.drmangotea.tfmg.content.decoration.pipes;
|
||||
|
||||
import com.drmangotea.tfmg.registry.TFMGPartialModels;
|
||||
import com.simibubi.create.content.decoration.bracket.BracketedBlockEntityBehaviour;
|
||||
import com.simibubi.create.content.fluids.FluidTransportBehaviour;
|
||||
import com.simibubi.create.content.fluids.pipes.FluidPipeBlock;
|
||||
import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour;
|
||||
import com.simibubi.create.foundation.model.BakedModelWrapperWithData;
|
||||
import com.simibubi.create.foundation.utility.Iterate;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.ItemBlockRenderTypes;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.client.renderer.block.model.BakedQuad;
|
||||
import net.minecraft.client.resources.model.BakedModel;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.level.BlockAndTintGetter;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraftforge.client.ChunkRenderTypeSet;
|
||||
import net.minecraftforge.client.model.data.ModelData;
|
||||
import net.minecraftforge.client.model.data.ModelProperty;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static net.minecraft.world.level.block.PipeBlock.PROPERTY_BY_DIRECTION;
|
||||
|
||||
|
||||
public class TFMGPipeAttachmentModel extends BakedModelWrapperWithData {
|
||||
|
||||
public final TFMGPipes.PipeMaterial material;
|
||||
|
||||
private static final ModelProperty<PipeModelData> PIPE_PROPERTY = new ModelProperty<>();
|
||||
|
||||
public TFMGPipeAttachmentModel(BakedModel template, TFMGPipes.PipeMaterial material) {
|
||||
super(template);
|
||||
this.material = material;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ModelData.Builder gatherModelData(ModelData.Builder builder, BlockAndTintGetter world, BlockPos pos, BlockState state,
|
||||
ModelData blockEntityData) {
|
||||
PipeModelData data = new PipeModelData();
|
||||
FluidTransportBehaviour transport = BlockEntityBehaviour.get(world, pos, FluidTransportBehaviour.TYPE);
|
||||
BracketedBlockEntityBehaviour bracket = BlockEntityBehaviour.get(world, pos, BracketedBlockEntityBehaviour.TYPE);
|
||||
|
||||
if (transport != null)
|
||||
for (Direction d : Iterate.directions) {
|
||||
boolean shouldConnect = true;
|
||||
if (world.getBlockState(pos.relative(d)).getBlock() instanceof FluidPipeBlock) {
|
||||
|
||||
if (d.getAxis().isHorizontal())
|
||||
shouldConnect = world.getBlockState(pos.relative(d)).getValue(PROPERTY_BY_DIRECTION.get(d.getOpposite()));
|
||||
}
|
||||
data.putAttachment(d, transport.getRenderedRimAttachment(world, pos, state, d));
|
||||
|
||||
if (!shouldConnect)
|
||||
if (state.getBlock() instanceof FluidPipeBlock)
|
||||
if (state.getValue(PROPERTY_BY_DIRECTION.get(d)))
|
||||
data.putAttachment(d, FluidTransportBehaviour.AttachmentTypes.RIM);
|
||||
}
|
||||
if (bracket != null)
|
||||
data.putBracket(bracket.getBracket());
|
||||
|
||||
data.setEncased(FluidPipeBlock.shouldDrawCasing(world, pos, state));
|
||||
return builder.with(PIPE_PROPERTY, data);
|
||||
}
|
||||
@SuppressWarnings("removal")
|
||||
@Override
|
||||
public ChunkRenderTypeSet getRenderTypes(@NotNull BlockState state, @NotNull RandomSource rand, @NotNull ModelData data) {
|
||||
ChunkRenderTypeSet set = super.getRenderTypes(state, rand, data);
|
||||
if (set.isEmpty()) {
|
||||
return ItemBlockRenderTypes.getRenderLayers(state);
|
||||
}
|
||||
return set;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BakedQuad> getQuads(BlockState state, Direction side, RandomSource rand, ModelData data, RenderType renderType) {
|
||||
List<BakedQuad> quads = super.getQuads(state, side, rand, data, renderType);
|
||||
if (data.has(PIPE_PROPERTY)) {
|
||||
PipeModelData pipeData = data.get(PIPE_PROPERTY);
|
||||
quads = new ArrayList<>(quads);
|
||||
addQuads(quads, state, side, rand, data, pipeData, renderType);
|
||||
}
|
||||
return quads;
|
||||
}
|
||||
|
||||
private void addQuads(List<BakedQuad> quads, BlockState state, Direction side, RandomSource rand, ModelData data,
|
||||
PipeModelData pipeData, RenderType renderType) {
|
||||
BakedModel bracket = pipeData.getBracket();
|
||||
if (bracket != null)
|
||||
quads.addAll(bracket.getQuads(state, side, rand, data, renderType));
|
||||
for (Direction d : Iterate.directions) {
|
||||
FluidTransportBehaviour.AttachmentTypes type = pipeData.getAttachment(d);
|
||||
for (FluidTransportBehaviour.AttachmentTypes.ComponentPartials partial : type.partials) {
|
||||
quads.addAll(TFMGPartialModels.PIPE_ATTACHMENTS.get(material).get(partial)
|
||||
.get(d)
|
||||
.get()
|
||||
.getQuads(state, side, rand, data, renderType));
|
||||
}
|
||||
}
|
||||
if (pipeData.isEncased())
|
||||
quads.addAll(TFMGPartialModels.PIPE_CASINGS.get(material).get()
|
||||
.getQuads(state, side, rand, data, renderType));
|
||||
}
|
||||
|
||||
private static class PipeModelData {
|
||||
private FluidTransportBehaviour.AttachmentTypes[] attachments;
|
||||
private boolean encased;
|
||||
private BakedModel bracket;
|
||||
|
||||
public PipeModelData() {
|
||||
attachments = new FluidTransportBehaviour.AttachmentTypes[6];
|
||||
Arrays.fill(attachments, FluidTransportBehaviour.AttachmentTypes.NONE);
|
||||
}
|
||||
|
||||
public void putBracket(BlockState state) {
|
||||
if (state != null) {
|
||||
this.bracket = Minecraft.getInstance()
|
||||
.getBlockRenderer()
|
||||
.getBlockModel(state);
|
||||
}
|
||||
}
|
||||
public BakedModel getBracket() {
|
||||
return bracket;
|
||||
}
|
||||
|
||||
public void putAttachment(Direction face, FluidTransportBehaviour.AttachmentTypes rim) {
|
||||
attachments[face.get3DDataValue()] = rim;
|
||||
}
|
||||
public FluidTransportBehaviour.AttachmentTypes getAttachment(Direction face) {
|
||||
return attachments[face.get3DDataValue()];
|
||||
}
|
||||
|
||||
public void setEncased(boolean encased) {
|
||||
this.encased = encased;
|
||||
}
|
||||
|
||||
public boolean isEncased() {
|
||||
return encased;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,192 @@
|
||||
package com.drmangotea.tfmg.content.decoration.pipes;
|
||||
|
||||
import com.drmangotea.tfmg.registry.TFMGBlockEntities;
|
||||
import com.simibubi.create.AllBlocks;
|
||||
import com.simibubi.create.content.decoration.bracket.BracketedBlockEntityBehaviour;
|
||||
import com.simibubi.create.content.fluids.FluidPropagator;
|
||||
import com.simibubi.create.content.fluids.FluidTransportBehaviour;
|
||||
import com.simibubi.create.content.fluids.pipes.EncasedPipeBlock;
|
||||
import com.simibubi.create.content.fluids.pipes.FluidPipeBlock;
|
||||
import com.simibubi.create.content.fluids.pipes.FluidPipeBlockEntity;
|
||||
import com.simibubi.create.content.fluids.pipes.GlassFluidPipeBlock;
|
||||
import com.simibubi.create.foundation.advancement.AllAdvancements;
|
||||
import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour;
|
||||
import com.simibubi.create.foundation.utility.Iterate;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.InteractionResult;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.context.UseOnContext;
|
||||
import net.minecraft.world.level.BlockAndTintGetter;
|
||||
import net.minecraft.world.level.BlockGetter;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
import net.minecraft.world.level.block.state.BlockBehaviour;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.minecraft.world.phys.HitResult;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Arrays;
|
||||
|
||||
public class TFMGPipeBlock extends FluidPipeBlock {
|
||||
|
||||
public final TFMGPipes.PipeMaterial material;
|
||||
|
||||
public TFMGPipeBlock(BlockBehaviour.Properties properties, TFMGPipes.PipeMaterial material) {
|
||||
super(properties);
|
||||
this.material = material;
|
||||
}
|
||||
|
||||
public BlockState updateBlockState(BlockState state, Direction preferredDirection, @Nullable Direction ignore,
|
||||
BlockAndTintGetter world, BlockPos pos) {
|
||||
if (world.getBlockEntity(pos) instanceof TFMGPipeBlockEntity)
|
||||
if (((TFMGPipeBlockEntity) world.getBlockEntity(pos)).locked) {
|
||||
return state;
|
||||
}
|
||||
|
||||
BracketedBlockEntityBehaviour bracket = BlockEntityBehaviour.get(world, pos, BracketedBlockEntityBehaviour.TYPE);
|
||||
if (bracket != null && bracket.isBracketPresent())
|
||||
return state;
|
||||
|
||||
BlockState prevState = state;
|
||||
int prevStateSides = (int) Arrays.stream(Iterate.directions)
|
||||
.map(PROPERTY_BY_DIRECTION::get)
|
||||
.filter(prevState::getValue)
|
||||
.count();
|
||||
|
||||
// Update sides that are not ignored
|
||||
for (Direction d : Iterate.directions)
|
||||
if (d != ignore) {
|
||||
boolean shouldConnect = canConnectTo(world, pos.relative(d), world.getBlockState(pos.relative(d)), d);
|
||||
|
||||
if (world.getBlockEntity(pos.relative(d)) instanceof TFMGPipeBlockEntity) {
|
||||
if (((TFMGPipeBlockEntity) world.getBlockEntity(pos.relative(d))).locked) {
|
||||
shouldConnect = false;
|
||||
if (world.getBlockState(pos.relative(d)).getValue(PROPERTY_BY_DIRECTION.get(d.getOpposite()))) {
|
||||
shouldConnect = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
state = state.setValue(PROPERTY_BY_DIRECTION.get(d), shouldConnect);
|
||||
}
|
||||
|
||||
// See if it has enough connections
|
||||
Direction connectedDirection = null;
|
||||
for (Direction d : Iterate.directions) {
|
||||
if (isOpenAt(state, d)) {
|
||||
if (connectedDirection != null)
|
||||
return state;
|
||||
connectedDirection = d;
|
||||
}
|
||||
}
|
||||
// Add opposite end if only one connection
|
||||
if (connectedDirection != null)
|
||||
return state.setValue(PROPERTY_BY_DIRECTION.get(connectedDirection.getOpposite()), true);
|
||||
|
||||
// If we can't connect to anything and weren't connected before, do nothing
|
||||
if (prevStateSides == 2)
|
||||
return prevState;
|
||||
|
||||
// Use preferred
|
||||
return state.setValue(PROPERTY_BY_DIRECTION.get(preferredDirection), true)
|
||||
.setValue(PROPERTY_BY_DIRECTION.get(preferredDirection.getOpposite()), true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick(BlockState state, ServerLevel world, BlockPos pos, RandomSource r) {
|
||||
super.tick(state, world, pos, r);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InteractionResult onWrenched(BlockState state, UseOnContext context) {
|
||||
|
||||
|
||||
if (tryRemoveBracket(context))
|
||||
return InteractionResult.SUCCESS;
|
||||
Level world = context.getLevel();
|
||||
BlockPos pos = context.getClickedPos();
|
||||
Direction clickedFace = context.getClickedFace();
|
||||
|
||||
Direction.Axis axis = getAxis(world, pos, state);
|
||||
if (axis == null) {
|
||||
Vec3 clickLocation = context.getClickLocation()
|
||||
.subtract(pos.getX(), pos.getY(), pos.getZ());
|
||||
double closest = Float.MAX_VALUE;
|
||||
Direction argClosest = Direction.UP;
|
||||
for (Direction direction : Iterate.directions) {
|
||||
if (clickedFace.getAxis() == direction.getAxis())
|
||||
continue;
|
||||
Vec3 centerOf = Vec3.atCenterOf(direction.getNormal());
|
||||
double distance = centerOf.distanceToSqr(clickLocation);
|
||||
if (distance < closest) {
|
||||
closest = distance;
|
||||
argClosest = direction;
|
||||
}
|
||||
}
|
||||
axis = argClosest.getAxis();
|
||||
}
|
||||
|
||||
if (clickedFace.getAxis() == axis)
|
||||
return InteractionResult.PASS;
|
||||
if (!world.isClientSide) {
|
||||
withBlockEntityDo(world, pos, fpte -> fpte.getBehaviour(FluidTransportBehaviour.TYPE).interfaces.values()
|
||||
.stream()
|
||||
.filter(pc -> pc != null && pc.hasFlow())
|
||||
.findAny()
|
||||
.ifPresent($ -> AllAdvancements.GLASS_PIPE.awardTo(context.getPlayer())));
|
||||
|
||||
FluidTransportBehaviour.cacheFlows(world, pos);
|
||||
world.setBlockAndUpdate(pos, TFMGPipes.TFMG_PIPES.get(material).get(2).getDefaultState()
|
||||
.setValue(GlassFluidPipeBlock.AXIS, axis)
|
||||
.setValue(BlockStateProperties.WATERLOGGED, state.getValue(BlockStateProperties.WATERLOGGED)));
|
||||
FluidTransportBehaviour.loadFlows(world, pos);
|
||||
}
|
||||
return InteractionResult.SUCCESS;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Direction.Axis getAxis(BlockGetter world, BlockPos pos, BlockState state) {
|
||||
return FluidPropagator.getStraightPipeAxis(state);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getCloneItemStack(BlockState state, HitResult target, BlockGetter world, BlockPos pos,
|
||||
Player player) {
|
||||
return TFMGPipes.TFMG_PIPES.get(material).get(0).asStack();
|
||||
}
|
||||
|
||||
@Override
|
||||
public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand,
|
||||
BlockHitResult hit) {
|
||||
if (!AllBlocks.COPPER_CASING.isIn(player.getItemInHand(hand)))
|
||||
return InteractionResult.PASS;
|
||||
if (world.isClientSide)
|
||||
return InteractionResult.SUCCESS;
|
||||
|
||||
FluidTransportBehaviour.cacheFlows(world, pos);
|
||||
world.setBlockAndUpdate(pos,
|
||||
EncasedPipeBlock.transferSixWayProperties(state, TFMGPipes.TFMG_PIPES.get(material).get(1).getDefaultState()));
|
||||
FluidTransportBehaviour.loadFlows(world, pos);
|
||||
return InteractionResult.SUCCESS;
|
||||
}
|
||||
@Override
|
||||
public Class<FluidPipeBlockEntity> getBlockEntityClass() {
|
||||
return FluidPipeBlockEntity.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockEntityType<? extends FluidPipeBlockEntity> getBlockEntityType() {
|
||||
return TFMGBlockEntities.TFMG_PIPE.get();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
package com.drmangotea.tfmg.content.decoration.pipes;
|
||||
|
||||
|
||||
import com.simibubi.create.AllBlocks;
|
||||
import com.simibubi.create.content.fluids.FluidTransportBehaviour;
|
||||
import com.simibubi.create.content.fluids.pipes.FluidPipeBlock;
|
||||
import com.simibubi.create.content.fluids.pipes.FluidPipeBlockEntity;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.sounds.SoundEvents;
|
||||
import net.minecraft.sounds.SoundSource;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.LevelAccessor;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
|
||||
import net.minecraft.world.level.block.state.properties.BooleanProperty;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class TFMGPipeBlockEntity extends FluidPipeBlockEntity {
|
||||
|
||||
public boolean locked = false;
|
||||
public TFMGPipeBlockEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) {
|
||||
super(type, pos, state);
|
||||
}
|
||||
|
||||
public void toggleLock(Player player) {
|
||||
level.playSound(player, getBlockPos(), SoundEvents.ITEM_PICKUP, SoundSource.BLOCKS, 0.4f, 0.5f);
|
||||
|
||||
locked = !locked;
|
||||
if (locked)
|
||||
return;
|
||||
|
||||
BlockState newState;
|
||||
Level world = level;
|
||||
BlockPos pos = getBlockPos();
|
||||
FluidTransportBehaviour.cacheFlows(world, pos);
|
||||
newState = updatePipe(world, pos, getBlockState()).setValue(BlockStateProperties.WATERLOGGED, getBlockState().getValue(BlockStateProperties.WATERLOGGED));
|
||||
world.setBlock(pos, newState, 3);
|
||||
FluidTransportBehaviour.loadFlows(world, pos);
|
||||
}
|
||||
|
||||
public BlockState updatePipe(LevelAccessor world, BlockPos pos, BlockState state) {
|
||||
Direction side = Direction.UP;
|
||||
Map<Direction, BooleanProperty> facingToPropertyMap = FluidPipeBlock.PROPERTY_BY_DIRECTION;
|
||||
return AllBlocks.FLUID_PIPE.get()
|
||||
.updateBlockState(state.getBlock().defaultBlockState()
|
||||
.setValue(facingToPropertyMap.get(side), true)
|
||||
.setValue(facingToPropertyMap.get(side.getOpposite()), true), side, null, world, pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(CompoundTag compound, boolean clientPacket) {
|
||||
compound.putBoolean("Locked", locked);
|
||||
super.write(compound, clientPacket);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void read(CompoundTag compound, boolean clientPacket) {
|
||||
super.read(compound, clientPacket);
|
||||
locked = compound.getBoolean("Locked");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package com.drmangotea.tfmg.content.decoration.pipes;
|
||||
|
||||
import com.simibubi.create.content.fluids.FluidTransportBehaviour;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.resources.model.BakedModel;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public class TFMGPipeModelData {
|
||||
private FluidTransportBehaviour.AttachmentTypes[] attachments;
|
||||
private boolean encased;
|
||||
private BakedModel bracket;
|
||||
|
||||
public TFMGPipeModelData() {
|
||||
attachments = new FluidTransportBehaviour.AttachmentTypes[6];
|
||||
Arrays.fill(attachments, FluidTransportBehaviour.AttachmentTypes.NONE);
|
||||
}
|
||||
|
||||
public void putBracket(BlockState state) {
|
||||
if (state != null) {
|
||||
this.bracket = Minecraft.getInstance()
|
||||
.getBlockRenderer()
|
||||
.getBlockModel(state);
|
||||
}
|
||||
}
|
||||
|
||||
public BakedModel getBracket() {
|
||||
return bracket;
|
||||
}
|
||||
|
||||
public void putAttachment(Direction face, FluidTransportBehaviour.AttachmentTypes rim) {
|
||||
attachments[face.get3DDataValue()] = rim;
|
||||
}
|
||||
|
||||
public FluidTransportBehaviour.AttachmentTypes getAttachment(Direction face) {
|
||||
return attachments[face.get3DDataValue()];
|
||||
}
|
||||
|
||||
public void setEncased(boolean encased) {
|
||||
this.encased = encased;
|
||||
}
|
||||
|
||||
public boolean isEncased() {
|
||||
return encased;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,157 @@
|
||||
package com.drmangotea.tfmg.content.decoration.pipes;
|
||||
|
||||
import com.simibubi.create.AllBlocks;
|
||||
import com.simibubi.create.AllSpriteShifts;
|
||||
import com.simibubi.create.content.decoration.encasing.EncasedCTBehaviour;
|
||||
import com.simibubi.create.content.decoration.encasing.EncasingRegistry;
|
||||
import com.simibubi.create.content.fluids.PipeAttachmentModel;
|
||||
import com.simibubi.create.content.fluids.pipes.SmartFluidPipeGenerator;
|
||||
import com.simibubi.create.content.fluids.pipes.valve.FluidValveBlock;
|
||||
import com.simibubi.create.content.kinetics.BlockStressDefaults;
|
||||
import com.simibubi.create.foundation.data.AssetLookup;
|
||||
import com.simibubi.create.foundation.data.BlockStateGen;
|
||||
import com.simibubi.create.foundation.data.CreateRegistrate;
|
||||
import com.simibubi.create.foundation.data.SharedProperties;
|
||||
import com.tterrag.registrate.util.entry.BlockEntry;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
|
||||
import net.minecraft.world.level.material.MapColor;
|
||||
import net.minecraftforge.client.model.generators.ConfiguredModel;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static com.drmangotea.tfmg.TFMG.REGISTRATE;
|
||||
import static com.simibubi.create.foundation.data.ModelGen.customItemModel;
|
||||
import static com.simibubi.create.foundation.data.TagGen.axeOrPickaxe;
|
||||
import static com.simibubi.create.foundation.data.TagGen.pickaxeOnly;
|
||||
|
||||
@SuppressWarnings("removal")
|
||||
public class TFMGPipes {
|
||||
|
||||
public static final Map<PipeMaterial, List<BlockEntry<? extends Block>>> TFMG_PIPES = new HashMap<>();
|
||||
|
||||
static {
|
||||
|
||||
|
||||
for (PipeMaterial pipeType : PipeMaterial.values()) {
|
||||
|
||||
List<BlockEntry<? extends Block>> pipes = new ArrayList<>();
|
||||
|
||||
BlockEntry<TFMGPipeBlock> pipe =
|
||||
REGISTRATE.block(pipeType.name + "_pipe", p -> new TFMGPipeBlock(p, pipeType))
|
||||
.initialProperties(SharedProperties::copperMetal)
|
||||
.transform(pickaxeOnly())
|
||||
.blockstate(BlockStateGen.pipe())
|
||||
.onRegister(CreateRegistrate.blockModel(() -> t -> new TFMGPipeAttachmentModel(t, pipeType)))
|
||||
.item()
|
||||
.transform(customItemModel())
|
||||
.register();
|
||||
|
||||
pipes.add(pipe);
|
||||
|
||||
BlockEntry<TFMGEncasedPipeBlock> copper_encased_pipe =
|
||||
REGISTRATE.block("copper_encased_" + pipeType.name + "_pipe", p -> new TFMGEncasedPipeBlock(p, AllBlocks.COPPER_CASING::get, pipeType))
|
||||
.initialProperties(SharedProperties::copperMetal)
|
||||
.properties(p -> p.noOcclusion().mapColor(MapColor.TERRACOTTA_LIGHT_GRAY))
|
||||
.transform(axeOrPickaxe())
|
||||
.blockstate(BlockStateGen.encasedPipe())
|
||||
.onRegister(CreateRegistrate.connectedTextures(() -> new EncasedCTBehaviour(AllSpriteShifts.COPPER_CASING)))
|
||||
.onRegister(CreateRegistrate.casingConnectivity((block, cc) -> cc.make(block, AllSpriteShifts.COPPER_CASING,
|
||||
(s, f) -> !s.getValue(TFMGEncasedPipeBlock.FACING_TO_PROPERTY_MAP.get(f)))))
|
||||
.onRegister(CreateRegistrate.blockModel(() -> PipeAttachmentModel::new))
|
||||
.loot((p, b) -> p.dropOther(b, pipe.get()))
|
||||
.transform(EncasingRegistry.addVariantTo(AllBlocks.FLUID_PIPE))
|
||||
.register();
|
||||
|
||||
pipes.add(copper_encased_pipe);
|
||||
|
||||
BlockEntry<TFMGGlassPipeBlock> glass_pipe =
|
||||
REGISTRATE.block("glass_" + pipeType.name + "_pipe", p -> new TFMGGlassPipeBlock(p, pipeType))
|
||||
.initialProperties(SharedProperties::copperMetal)
|
||||
.addLayer(() -> RenderType::cutoutMipped)
|
||||
.transform(pickaxeOnly())
|
||||
.blockstate((c, p) -> {
|
||||
p.getVariantBuilder(c.getEntry())
|
||||
.forAllStatesExcept(state -> {
|
||||
Direction.Axis axis = state.getValue(BlockStateProperties.AXIS);
|
||||
return ConfiguredModel.builder()
|
||||
.modelFile(p.models()
|
||||
.getExistingFile(p.modLoc("block/" + pipeType.name + "_pipe/window")))
|
||||
.uvLock(false)
|
||||
.rotationX(axis == Direction.Axis.Y ? 0 : 90)
|
||||
.rotationY(axis == Direction.Axis.X ? 90 : 0)
|
||||
.build();
|
||||
}, BlockStateProperties.WATERLOGGED);
|
||||
})
|
||||
.onRegister(CreateRegistrate.blockModel(() -> t -> new TFMGPipeAttachmentModel(t, pipeType)))
|
||||
.loot((p, b) -> p.dropOther(b, pipe.get()))
|
||||
.register();
|
||||
|
||||
pipes.add(glass_pipe);
|
||||
|
||||
BlockEntry<TFMGPumpBlock> fluid_pump =
|
||||
REGISTRATE.block(pipeType.name + "_mechanical_pump", TFMGPumpBlock::new)
|
||||
.initialProperties(SharedProperties::copperMetal)
|
||||
.transform(pickaxeOnly())
|
||||
.blockstate(BlockStateGen.directionalBlockProviderIgnoresWaterlogged(true))
|
||||
.onRegister(CreateRegistrate.blockModel(() -> t -> new TFMGPipeAttachmentModel(t, pipeType)))
|
||||
.transform(BlockStressDefaults.setImpact(4.0))
|
||||
.item()
|
||||
.transform(customItemModel())
|
||||
.register();
|
||||
|
||||
pipes.add(fluid_pump);
|
||||
|
||||
BlockEntry<TFMGSmartFluidPipeBlock> smart_pipe =
|
||||
REGISTRATE.block(pipeType.name + "_smart_fluid_pipe", TFMGSmartFluidPipeBlock::new)
|
||||
.initialProperties(SharedProperties::copperMetal)
|
||||
.transform(pickaxeOnly())
|
||||
.blockstate(new SmartFluidPipeGenerator()::generate)
|
||||
.onRegister(CreateRegistrate.blockModel(() -> t -> new TFMGPipeAttachmentModel(t, pipeType)))
|
||||
.item()
|
||||
.transform(customItemModel())
|
||||
.register();
|
||||
|
||||
pipes.add(smart_pipe);
|
||||
|
||||
BlockEntry<TFMGFluidValveBlock> fluid_valve =
|
||||
REGISTRATE.block(pipeType.name + "_fluid_valve", TFMGFluidValveBlock::new)
|
||||
.initialProperties(SharedProperties::copperMetal)
|
||||
.transform(pickaxeOnly())
|
||||
.blockstate((c, p) -> BlockStateGen.directionalAxisBlock(c, p,
|
||||
(state, vertical) -> AssetLookup.partialBaseModel(c, p, vertical ? "vertical" : "horizontal",
|
||||
state.getValue(FluidValveBlock.ENABLED) ? "open" : "closed")))
|
||||
.onRegister(CreateRegistrate.blockModel(() -> t -> new TFMGPipeAttachmentModel(t, pipeType)))
|
||||
.item()
|
||||
.transform(customItemModel())
|
||||
.register();
|
||||
|
||||
pipes.add(fluid_valve);
|
||||
|
||||
TFMG_PIPES.put(pipeType, pipes);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public static void init() {}
|
||||
|
||||
public enum PipeMaterial {
|
||||
BRASS("brass"),
|
||||
STEEL("steel"),
|
||||
ALUMINUM("aluminum"),
|
||||
CAST_IRON("cast_iron"),
|
||||
PLASTIC("plastic");
|
||||
|
||||
public final String name;
|
||||
|
||||
PipeMaterial(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.drmangotea.tfmg.content.decoration.pipes;
|
||||
|
||||
|
||||
import com.drmangotea.tfmg.registry.TFMGBlockEntities;
|
||||
import com.simibubi.create.content.fluids.pump.PumpBlock;
|
||||
import com.simibubi.create.content.fluids.pump.PumpBlockEntity;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
|
||||
public class TFMGPumpBlock extends PumpBlock {
|
||||
public TFMGPumpBlock(Properties p_i48415_1_) {
|
||||
super(p_i48415_1_);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick(BlockState state, ServerLevel world, BlockPos pos, RandomSource r) {
|
||||
super.tick(state, world, pos, r);
|
||||
this.getBlockEntity(world, pos).updatePressureChange();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<PumpBlockEntity> getBlockEntityClass() {
|
||||
return PumpBlockEntity.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockEntityType<? extends PumpBlockEntity> getBlockEntityType() {
|
||||
return TFMGBlockEntities.TFMG_MECHANICAL_PUMP.get();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.drmangotea.tfmg.content.decoration.pipes;
|
||||
|
||||
|
||||
import com.drmangotea.tfmg.registry.TFMGBlockEntities;
|
||||
import com.simibubi.create.content.equipment.wrench.IWrenchable;
|
||||
import com.simibubi.create.content.fluids.pipes.IAxisPipe;
|
||||
import com.simibubi.create.content.fluids.pipes.SmartFluidPipeBlock;
|
||||
import com.simibubi.create.content.fluids.pipes.SmartFluidPipeBlockEntity;
|
||||
import com.simibubi.create.foundation.block.IBE;
|
||||
import com.simibubi.create.foundation.block.ProperWaterloggedBlock;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
|
||||
public class TFMGSmartFluidPipeBlock extends SmartFluidPipeBlock
|
||||
implements IBE<SmartFluidPipeBlockEntity>, IAxisPipe, IWrenchable, ProperWaterloggedBlock {
|
||||
public TFMGSmartFluidPipeBlock(Properties p_i48339_1_) {
|
||||
super(p_i48339_1_);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<SmartFluidPipeBlockEntity> getBlockEntityClass() {
|
||||
return SmartFluidPipeBlockEntity.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockEntityType<? extends SmartFluidPipeBlockEntity> getBlockEntityType() {
|
||||
return TFMGBlockEntities.TFMG_SMART_FLUID_PIPE.get();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
package com.drmangotea.tfmg.content.decoration.tank;
|
||||
|
||||
|
||||
import com.drmangotea.tfmg.registry.TFMGPartialModels;
|
||||
import com.jozufozu.flywheel.util.transform.TransformStack;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||
import com.simibubi.create.AllPartialModels;
|
||||
import com.simibubi.create.foundation.blockEntity.renderer.SafeBlockEntityRenderer;
|
||||
import com.simibubi.create.foundation.fluid.FluidRenderer;
|
||||
import com.simibubi.create.foundation.render.CachedBufferer;
|
||||
import com.simibubi.create.foundation.utility.Iterate;
|
||||
import com.simibubi.create.foundation.utility.animation.LerpedFloat;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraftforge.fluids.FluidStack;
|
||||
import net.minecraftforge.fluids.capability.templates.FluidTank;
|
||||
|
||||
public class SteelFluidTankRenderer extends SafeBlockEntityRenderer<SteelTankBlockEntity> {
|
||||
|
||||
public SteelFluidTankRenderer(BlockEntityRendererProvider.Context context) {}
|
||||
@Override
|
||||
protected void renderSafe(SteelTankBlockEntity te, float partialTicks, PoseStack ms, MultiBufferSource buffer,
|
||||
int light, int overlay) {
|
||||
if (!te.isController())
|
||||
return;
|
||||
if (!te.window) {
|
||||
if (te.isDistillationTower)
|
||||
renderAsDistillationTower(te, partialTicks, ms, buffer, light, overlay);
|
||||
return;
|
||||
}
|
||||
LerpedFloat fluidLevel = te.getFluidLevel();
|
||||
if (fluidLevel == null)
|
||||
return;
|
||||
|
||||
float capHeight = 1 / 4f;
|
||||
float tankHullWidth = 1 / 16f + 1 / 128f;
|
||||
float minPuddleHeight = 1 / 16f;
|
||||
float totalHeight = te.height - 2 * capHeight - minPuddleHeight;
|
||||
|
||||
float level = fluidLevel.getValue(partialTicks);
|
||||
if (level < 1 / (512f * totalHeight))
|
||||
return;
|
||||
float clampedLevel = Mth.clamp(level * totalHeight, 0, totalHeight);
|
||||
|
||||
FluidTank tank = te.tankInventory;
|
||||
FluidStack fluidStack = tank.getFluid();
|
||||
|
||||
if (fluidStack.isEmpty())
|
||||
return;
|
||||
boolean top = fluidStack.getFluid()
|
||||
.getFluidType()
|
||||
.isLighterThanAir();
|
||||
|
||||
float xMin = tankHullWidth;
|
||||
float xMax = xMin + te.width - 2 * tankHullWidth;
|
||||
float yMin = totalHeight + capHeight + minPuddleHeight - clampedLevel;
|
||||
float yMax = yMin + clampedLevel;
|
||||
|
||||
if (top) {
|
||||
yMin += totalHeight - clampedLevel;
|
||||
yMax += totalHeight - clampedLevel;
|
||||
}
|
||||
|
||||
float zMin = tankHullWidth;
|
||||
float zMax = zMin + te.width - 2 * tankHullWidth;
|
||||
|
||||
ms.pushPose();
|
||||
ms.translate(0, clampedLevel - totalHeight, 0);
|
||||
FluidRenderer.renderFluidBox(fluidStack, xMin, yMin, zMin, xMax, yMax, zMax, buffer, ms, light, false);
|
||||
ms.popPose();
|
||||
}
|
||||
|
||||
protected void renderAsDistillationTower(SteelTankBlockEntity te, float partialTicks, PoseStack ms, MultiBufferSource buffer,
|
||||
int light, int overlay) {
|
||||
BlockState blockState = te.getBlockState();
|
||||
VertexConsumer vb = buffer.getBuffer(RenderType.solid());
|
||||
ms.pushPose();
|
||||
TransformStack msr = TransformStack.cast(ms);
|
||||
msr.translate(te.width / 2f, 0.5, te.width / 2f);
|
||||
|
||||
float dialPivot = 5.75f / 16;
|
||||
|
||||
for (Direction d : Iterate.horizontalDirections) {
|
||||
ms.pushPose();
|
||||
CachedBufferer.partial(TFMGPartialModels.TOWER_GAUGE, blockState)
|
||||
.rotateY(d.toYRot())
|
||||
.unCentre()
|
||||
.translate(te.width / 2f - 6 / 16f, 0, 0)
|
||||
.light(light)
|
||||
.renderInto(ms, vb);
|
||||
CachedBufferer.partial(AllPartialModels.BOILER_GAUGE_DIAL, blockState)
|
||||
.rotateY(d.toYRot())
|
||||
.unCentre()
|
||||
.translate(te.width / 2f - 6 / 16f, 0, 0)
|
||||
.translate(0, dialPivot, dialPivot)
|
||||
.rotateX(-te.visualGaugeRotation.getValue(partialTicks))
|
||||
.translate(0, -dialPivot, -dialPivot)
|
||||
.light(light)
|
||||
.renderInto(ms, vb);
|
||||
ms.popPose();
|
||||
}
|
||||
ms.popPose();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldRenderOffScreen(SteelTankBlockEntity te) {
|
||||
return te.isController();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,355 @@
|
||||
package com.drmangotea.tfmg.content.decoration.tank;
|
||||
|
||||
|
||||
import com.drmangotea.tfmg.registry.TFMGBlockEntities;
|
||||
import com.simibubi.create.api.connectivity.ConnectivityHandler;
|
||||
import com.simibubi.create.content.equipment.wrench.IWrenchable;
|
||||
import com.simibubi.create.content.fluids.transfer.GenericItemEmptying;
|
||||
import com.simibubi.create.content.fluids.transfer.GenericItemFilling;
|
||||
import com.simibubi.create.foundation.block.IBE;
|
||||
import com.simibubi.create.foundation.blockEntity.ComparatorUtil;
|
||||
import com.simibubi.create.foundation.fluid.FluidHelper;
|
||||
import com.simibubi.create.foundation.fluid.FluidHelper.FluidExchange;
|
||||
import com.simibubi.create.foundation.utility.Lang;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.core.particles.BlockParticleOption;
|
||||
import net.minecraft.core.particles.ParticleTypes;
|
||||
import net.minecraft.sounds.SoundEvent;
|
||||
import net.minecraft.sounds.SoundEvents;
|
||||
import net.minecraft.sounds.SoundSource;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.util.StringRepresentable;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.InteractionResult;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.context.UseOnContext;
|
||||
import net.minecraft.world.level.BlockGetter;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.LevelAccessor;
|
||||
import net.minecraft.world.level.LevelReader;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.Mirror;
|
||||
import net.minecraft.world.level.block.Rotation;
|
||||
import net.minecraft.world.level.block.SoundType;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.StateDefinition.Builder;
|
||||
import net.minecraft.world.level.block.state.properties.BooleanProperty;
|
||||
import net.minecraft.world.level.block.state.properties.EnumProperty;
|
||||
import net.minecraft.world.level.material.Fluid;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraft.world.phys.shapes.CollisionContext;
|
||||
import net.minecraft.world.phys.shapes.Shapes;
|
||||
import net.minecraft.world.phys.shapes.VoxelShape;
|
||||
import net.minecraftforge.common.capabilities.ForgeCapabilities;
|
||||
import net.minecraftforge.common.util.ForgeSoundType;
|
||||
import net.minecraftforge.common.util.LazyOptional;
|
||||
import net.minecraftforge.fluids.FluidStack;
|
||||
import net.minecraftforge.fluids.capability.IFluidHandler;
|
||||
|
||||
public class SteelTankBlock extends Block implements IWrenchable, IBE<SteelTankBlockEntity> {
|
||||
public static final BooleanProperty TOP = BooleanProperty.create("top");
|
||||
public static final BooleanProperty BOTTOM = BooleanProperty.create("bottom");
|
||||
public static final EnumProperty<Shape> SHAPE = EnumProperty.create("shape", Shape.class);
|
||||
private boolean creative;
|
||||
public static SteelTankBlock regular(Properties p_i48440_1_) {
|
||||
return new SteelTankBlock(p_i48440_1_, false);
|
||||
}
|
||||
public static SteelTankBlock creative(Properties p_i48440_1_) {
|
||||
return new SteelTankBlock(p_i48440_1_, true);
|
||||
}
|
||||
|
||||
protected SteelTankBlock(Properties p_i48440_1_, boolean creative) {
|
||||
super(p_i48440_1_);
|
||||
this.creative = creative;
|
||||
registerDefaultState(defaultBlockState().setValue(TOP, true)
|
||||
.setValue(BOTTOM, true)
|
||||
.setValue(SHAPE, Shape.WINDOW));
|
||||
}
|
||||
|
||||
public static boolean isTank(BlockState state) {
|
||||
return state.getBlock() instanceof SteelTankBlock;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean moved) {
|
||||
if (oldState.getBlock() == state.getBlock())
|
||||
return;
|
||||
if (moved)
|
||||
return;
|
||||
withBlockEntityDo(world, pos, SteelTankBlockEntity::updateConnectivity);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createBlockStateDefinition(Builder<Block, BlockState> p_206840_1_) {
|
||||
p_206840_1_.add(TOP, BOTTOM, SHAPE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLightEmission(BlockState state, BlockGetter world, BlockPos pos) {
|
||||
SteelTankBlockEntity tankAt = ConnectivityHandler.partAt(getBlockEntityType(), world, pos);
|
||||
if (tankAt == null)
|
||||
return 0;
|
||||
SteelTankBlockEntity controllerTE = (SteelTankBlockEntity) tankAt.getControllerBE();
|
||||
if (controllerTE == null || !controllerTE.window)
|
||||
return 0;
|
||||
return tankAt.luminosity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InteractionResult onWrenched(BlockState state, UseOnContext context) {
|
||||
withBlockEntityDo(context.getLevel(), context.getClickedPos(), SteelTankBlockEntity::toggleWindows);
|
||||
return InteractionResult.SUCCESS;
|
||||
}
|
||||
|
||||
static final VoxelShape CAMPFIRE_SMOKE_CLIP = Block.box(0, 4, 0, 16, 16, 16);
|
||||
|
||||
@Override
|
||||
public VoxelShape getCollisionShape(BlockState pState, BlockGetter pLevel, BlockPos pPos,
|
||||
CollisionContext pContext) {
|
||||
if (pContext == CollisionContext.empty())
|
||||
return CAMPFIRE_SMOKE_CLIP;
|
||||
return pState.getShape(pLevel, pPos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VoxelShape getBlockSupportShape(BlockState pState, BlockGetter pReader, BlockPos pPos) {
|
||||
return Shapes.block();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState updateShape(BlockState pState, Direction pDirection, BlockState pNeighborState,
|
||||
LevelAccessor pLevel, BlockPos pCurrentPos, BlockPos pNeighborPos) {
|
||||
if (pDirection == Direction.DOWN && pNeighborState.getBlock() != this)
|
||||
withBlockEntityDo(pLevel, pCurrentPos, SteelTankBlockEntity::updateBoilerTemperature);
|
||||
return pState;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand,
|
||||
BlockHitResult ray) {
|
||||
ItemStack heldItem = player.getItemInHand(hand);
|
||||
boolean onClient = world.isClientSide;
|
||||
|
||||
if (heldItem.isEmpty())
|
||||
return InteractionResult.PASS;
|
||||
if (!player.isCreative() && !creative)
|
||||
return InteractionResult.PASS;
|
||||
|
||||
FluidExchange exchange = null;
|
||||
SteelTankBlockEntity te = ConnectivityHandler.partAt(getBlockEntityType(), world, pos);
|
||||
if (te == null)
|
||||
return InteractionResult.FAIL;
|
||||
|
||||
LazyOptional<IFluidHandler> tankCapability = te.getCapability(ForgeCapabilities.FLUID_HANDLER);
|
||||
if (!tankCapability.isPresent())
|
||||
return InteractionResult.PASS;
|
||||
IFluidHandler fluidTank = tankCapability.orElse(null);
|
||||
FluidStack prevFluidInTank = fluidTank.getFluidInTank(0)
|
||||
.copy();
|
||||
|
||||
if (FluidHelper.tryEmptyItemIntoBE(world, player, hand, heldItem, te))
|
||||
exchange = FluidExchange.ITEM_TO_TANK;
|
||||
else if (FluidHelper.tryFillItemFromBE(world, player, hand, heldItem, te))
|
||||
exchange = FluidExchange.TANK_TO_ITEM;
|
||||
|
||||
if (exchange == null) {
|
||||
if (GenericItemEmptying.canItemBeEmptied(world, heldItem)
|
||||
|| GenericItemFilling.canItemBeFilled(world, heldItem))
|
||||
return InteractionResult.SUCCESS;
|
||||
return InteractionResult.PASS;
|
||||
}
|
||||
|
||||
SoundEvent soundevent = null;
|
||||
BlockState fluidState = null;
|
||||
FluidStack fluidInTank = tankCapability.map(fh -> fh.getFluidInTank(0))
|
||||
.orElse(FluidStack.EMPTY);
|
||||
|
||||
if (exchange == FluidExchange.ITEM_TO_TANK) {
|
||||
|
||||
|
||||
Fluid fluid = fluidInTank.getFluid();
|
||||
fluidState = fluid.defaultFluidState()
|
||||
.createLegacyBlock();
|
||||
soundevent = FluidHelper.getEmptySound(fluidInTank);
|
||||
}
|
||||
|
||||
if (exchange == FluidExchange.TANK_TO_ITEM) {
|
||||
|
||||
Fluid fluid = prevFluidInTank.getFluid();
|
||||
fluidState = fluid.defaultFluidState()
|
||||
.createLegacyBlock();
|
||||
soundevent = FluidHelper.getFillSound(prevFluidInTank);
|
||||
}
|
||||
|
||||
if (soundevent != null && !onClient) {
|
||||
float pitch = Mth
|
||||
.clamp(1 - (1f * fluidInTank.getAmount() / (SteelTankBlockEntity.getCapacityMultiplier() * 16)), 0, 1);
|
||||
pitch /= 1.5f;
|
||||
pitch += .5f;
|
||||
pitch += (world.random.nextFloat() - .5f) / 4f;
|
||||
world.playSound(null, pos, soundevent, SoundSource.BLOCKS, .5f, pitch);
|
||||
}
|
||||
|
||||
if (!fluidInTank.isFluidStackIdentical(prevFluidInTank)) {
|
||||
if (te instanceof SteelTankBlockEntity) {
|
||||
SteelTankBlockEntity controllerTE = (SteelTankBlockEntity) ((SteelTankBlockEntity) te).getControllerBE();
|
||||
if (controllerTE != null) {
|
||||
if (fluidState != null && onClient) {
|
||||
BlockParticleOption blockParticleData =
|
||||
new BlockParticleOption(ParticleTypes.BLOCK, fluidState);
|
||||
float level = (float) fluidInTank.getAmount() / fluidTank.getTankCapacity(0);
|
||||
|
||||
boolean reversed = fluidInTank.getFluid()
|
||||
.getFluidType()
|
||||
.isLighterThanAir();
|
||||
if (reversed)
|
||||
level = 1 - level;
|
||||
|
||||
Vec3 vec = ray.getLocation();
|
||||
vec = new Vec3(vec.x, controllerTE.getBlockPos()
|
||||
.getY() + level * (controllerTE.height - .5f) + .25f, vec.z);
|
||||
Vec3 motion = player.position()
|
||||
.subtract(vec)
|
||||
.scale(1 / 20f);
|
||||
vec = vec.add(motion);
|
||||
world.addParticle(blockParticleData, vec.x, vec.y, vec.z, motion.x, motion.y, motion.z);
|
||||
return InteractionResult.SUCCESS;
|
||||
}
|
||||
|
||||
controllerTE.sendDataImmediately();
|
||||
controllerTE.setChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
return InteractionResult.SUCCESS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRemove(BlockState state, Level world, BlockPos pos, BlockState newState, boolean isMoving) {
|
||||
if (state.hasBlockEntity() && (state.getBlock() != newState.getBlock() || !newState.hasBlockEntity())) {
|
||||
BlockEntity te = world.getBlockEntity(pos);
|
||||
if (!(te instanceof SteelTankBlockEntity))
|
||||
return;
|
||||
SteelTankBlockEntity tankTE = (SteelTankBlockEntity) te;
|
||||
world.removeBlockEntity(pos);
|
||||
ConnectivityHandler.splitMulti(tankTE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<SteelTankBlockEntity> getBlockEntityClass() {
|
||||
return SteelTankBlockEntity.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockEntityType<? extends SteelTankBlockEntity> getBlockEntityType() {
|
||||
return creative ? TFMGBlockEntities.STEEL_FLUID_TANK.get() : TFMGBlockEntities.STEEL_FLUID_TANK.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState mirror(BlockState state, Mirror mirror) {
|
||||
if (mirror == Mirror.NONE)
|
||||
return state;
|
||||
boolean x = mirror == Mirror.FRONT_BACK;
|
||||
switch (state.getValue(SHAPE)) {
|
||||
case WINDOW_NE:
|
||||
return state.setValue(SHAPE, x ? Shape.WINDOW_NW : Shape.WINDOW_SE);
|
||||
case WINDOW_NW:
|
||||
return state.setValue(SHAPE, x ? Shape.WINDOW_NE : Shape.WINDOW_SW);
|
||||
case WINDOW_SE:
|
||||
return state.setValue(SHAPE, x ? Shape.WINDOW_SW : Shape.WINDOW_NE);
|
||||
case WINDOW_SW:
|
||||
return state.setValue(SHAPE, x ? Shape.WINDOW_SE : Shape.WINDOW_NW);
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState rotate(BlockState state, Rotation rotation) {
|
||||
for (int i = 0; i < rotation.ordinal(); i++)
|
||||
state = rotateOnce(state);
|
||||
return state;
|
||||
}
|
||||
|
||||
private BlockState rotateOnce(BlockState state) {
|
||||
switch (state.getValue(SHAPE)) {
|
||||
case WINDOW_NE:
|
||||
return state.setValue(SHAPE, Shape.WINDOW_SE);
|
||||
case WINDOW_NW:
|
||||
return state.setValue(SHAPE, Shape.WINDOW_NE);
|
||||
case WINDOW_SE:
|
||||
return state.setValue(SHAPE, Shape.WINDOW_SW);
|
||||
case WINDOW_SW:
|
||||
return state.setValue(SHAPE, Shape.WINDOW_NW);
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
public enum Shape implements StringRepresentable {
|
||||
PLAIN, WINDOW, WINDOW_NW, WINDOW_SW, WINDOW_NE, WINDOW_SE;
|
||||
@Override
|
||||
public String getSerializedName() {
|
||||
return Lang.asId(name());
|
||||
}
|
||||
}
|
||||
|
||||
// Tanks are less noisy when placed in batch
|
||||
public static final SoundType SILENCED_METAL =
|
||||
new ForgeSoundType(0.1F, 1.5F, () -> SoundEvents.METAL_BREAK, () -> SoundEvents.METAL_STEP,
|
||||
() -> SoundEvents.METAL_PLACE, () -> SoundEvents.METAL_HIT, () -> SoundEvents.METAL_FALL);
|
||||
|
||||
@Override
|
||||
public SoundType getSoundType(BlockState state, LevelReader world, BlockPos pos, Entity entity) {
|
||||
SoundType soundType = super.getSoundType(state, world, pos, entity);
|
||||
if (entity != null && entity.getPersistentData()
|
||||
.contains("SilenceTankSound"))
|
||||
return SILENCED_METAL;
|
||||
return soundType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasAnalogOutputSignal(BlockState state) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAnalogOutputSignal(BlockState blockState, Level worldIn, BlockPos pos) {
|
||||
return getBlockEntityOptional(worldIn, pos).map(SteelTankBlockEntity::getControllerBE)
|
||||
.map(te -> ComparatorUtil.fractionToRedstoneLevel(te.getFillState()))
|
||||
.orElse(0);
|
||||
}
|
||||
|
||||
public static boolean updateTowerState(Level pLevel, BlockPos tankPos, boolean assemble, boolean simulate) {
|
||||
BlockState tankState = pLevel.getBlockState(tankPos);
|
||||
|
||||
if (!(tankState.getBlock() instanceof SteelTankBlock tank))
|
||||
return false;
|
||||
|
||||
SteelTankBlockEntity tankBE = tank.getBlockEntity(pLevel, tankPos);
|
||||
if (tankBE == null)
|
||||
return false;
|
||||
|
||||
if (assemble && tankBE.getControllerBE().isDistillationTower)
|
||||
return false;
|
||||
|
||||
if (!simulate) {
|
||||
tankBE.getControllerBE().updateBoilerState();
|
||||
tankBE.getControllerBE().isDistillationTower = assemble;
|
||||
tankBE.getControllerBE().refreshCapability();
|
||||
|
||||
|
||||
tankBE.updateBoilerState();
|
||||
tankBE.isDistillationTower = assemble;
|
||||
tankBE.refreshCapability();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,650 @@
|
||||
package com.drmangotea.tfmg.content.decoration.tank;
|
||||
|
||||
import com.drmangotea.tfmg.registry.TFMGBlocks;
|
||||
import com.simibubi.create.api.connectivity.ConnectivityHandler;
|
||||
import com.simibubi.create.content.equipment.goggles.IHaveGoggleInformation;
|
||||
import com.simibubi.create.content.fluids.tank.BoilerHeaters;
|
||||
import com.simibubi.create.content.fluids.tank.FluidTankBlockEntity;
|
||||
import com.simibubi.create.foundation.blockEntity.IMultiBlockEntityContainer;
|
||||
import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour;
|
||||
import com.simibubi.create.foundation.fluid.SmartFluidTank;
|
||||
import com.simibubi.create.foundation.utility.Iterate;
|
||||
import com.simibubi.create.foundation.utility.animation.LerpedFloat;
|
||||
import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser;
|
||||
import com.simibubi.create.infrastructure.config.AllConfigs;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.NbtUtils;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.phys.AABB;
|
||||
import net.minecraftforge.common.capabilities.Capability;
|
||||
import net.minecraftforge.common.capabilities.ForgeCapabilities;
|
||||
import net.minecraftforge.common.util.LazyOptional;
|
||||
import net.minecraftforge.fluids.FluidStack;
|
||||
import net.minecraftforge.fluids.FluidType;
|
||||
import net.minecraftforge.fluids.IFluidTank;
|
||||
import net.minecraftforge.fluids.capability.IFluidHandler;
|
||||
import net.minecraftforge.fluids.capability.IFluidHandler.FluidAction;
|
||||
import net.minecraftforge.fluids.capability.templates.FluidTank;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.List;
|
||||
|
||||
import static java.lang.Math.abs;
|
||||
|
||||
public class SteelTankBlockEntity extends FluidTankBlockEntity implements IHaveGoggleInformation, IMultiBlockEntityContainer.Fluid {
|
||||
private static final int MAX_SIZE = 3;
|
||||
protected LazyOptional<IFluidHandler> fluidCapability;
|
||||
protected boolean forceFluidLevelUpdate;
|
||||
public FluidTank tankInventory;
|
||||
protected BlockPos controller;
|
||||
protected BlockPos lastKnownPos;
|
||||
protected boolean updateConnectivity;
|
||||
public boolean window;
|
||||
public int luminosity;
|
||||
public int width;
|
||||
public int height;
|
||||
public int gaugeRotation = 0;
|
||||
public int activeHeat;
|
||||
public boolean isDistillationTower = false;
|
||||
private static final int SYNC_RATE = 8;
|
||||
protected int syncCooldown;
|
||||
protected boolean queuedSync;
|
||||
|
||||
// For rendering purposes only
|
||||
private LerpedFloat fluidLevel;
|
||||
public LerpedFloat visualGaugeRotation = LerpedFloat.angular();
|
||||
public SteelTankBlockEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) {
|
||||
super(type, pos, state);
|
||||
setLazyTickRate(10);
|
||||
tankInventory = createInventory();
|
||||
fluidCapability = LazyOptional.of(() -> tankInventory);
|
||||
forceFluidLevelUpdate = true;
|
||||
updateConnectivity = false;
|
||||
window = true;
|
||||
height = 1;
|
||||
width = 1;
|
||||
refreshCapability();
|
||||
}
|
||||
|
||||
protected SmartFluidTank createInventory() {
|
||||
return new SmartFluidTank(getCapacityMultiplier(), this::onFluidStackChanged);
|
||||
}
|
||||
public void updateConnectivity() {
|
||||
updateConnectivity = false;
|
||||
if (level.isClientSide)
|
||||
return;
|
||||
if (!isController())
|
||||
return;
|
||||
refreshCapability();
|
||||
ConnectivityHandler.formMulti(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
super.tick();
|
||||
getGaugeRotation();
|
||||
visualGaugeRotation.chase(gaugeRotation, 0.2f, Chaser.EXP);
|
||||
visualGaugeRotation.tickChaser();
|
||||
if (syncCooldown > 0) {
|
||||
syncCooldown--;
|
||||
if (syncCooldown == 0 && queuedSync)
|
||||
sendData();
|
||||
}
|
||||
|
||||
if (lastKnownPos == null)
|
||||
lastKnownPos = getBlockPos();
|
||||
else if (!lastKnownPos.equals(worldPosition) && worldPosition != null) {
|
||||
onPositionChanged();
|
||||
return;
|
||||
}
|
||||
if (updateConnectivity)
|
||||
updateConnectivity();
|
||||
if (fluidLevel != null)
|
||||
fluidLevel.tickChaser();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockPos getLastKnownPos() {
|
||||
return lastKnownPos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isController() {
|
||||
return controller == null || worldPosition.getX() == controller.getX()
|
||||
&& worldPosition.getY() == controller.getY() && worldPosition.getZ() == controller.getZ();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
super.initialize();
|
||||
sendData();
|
||||
if (level.isClientSide)
|
||||
invalidateRenderBoundingBox();
|
||||
}
|
||||
|
||||
private void onPositionChanged() {
|
||||
removeController(true);
|
||||
lastKnownPos = worldPosition;
|
||||
}
|
||||
|
||||
protected void onFluidStackChanged(FluidStack newFluidStack) {
|
||||
if (!hasLevel())
|
||||
return;
|
||||
FluidType attributes = newFluidStack.getFluid()
|
||||
.getFluidType();
|
||||
int luminosity = (int) (attributes.getLightLevel(newFluidStack) / 1.2f);
|
||||
boolean reversed = attributes.isLighterThanAir();
|
||||
int maxY = (int) ((getFillState() * height) + 1);
|
||||
for (int yOffset = 0; yOffset < height; yOffset++) {
|
||||
boolean isBright = reversed ? (height - yOffset <= maxY) : (yOffset < maxY);
|
||||
int actualLuminosity = isBright ? luminosity : luminosity > 0 ? 1 : 0;
|
||||
for (int xOffset = 0; xOffset < width; xOffset++) {
|
||||
for (int zOffset = 0; zOffset < width; zOffset++) {
|
||||
BlockPos pos = this.worldPosition.offset(xOffset, yOffset, zOffset);
|
||||
SteelTankBlockEntity tankAt = ConnectivityHandler.partAt(getType(), level, pos);
|
||||
if (tankAt == null)
|
||||
continue;
|
||||
level.updateNeighbourForOutputSignal(pos, tankAt.getBlockState()
|
||||
.getBlock());
|
||||
if (tankAt.luminosity == actualLuminosity)
|
||||
continue;
|
||||
tankAt.setLuminosity(actualLuminosity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!level.isClientSide) {
|
||||
setChanged();
|
||||
sendData();
|
||||
}
|
||||
|
||||
if (isVirtual()) {
|
||||
if (fluidLevel == null)
|
||||
fluidLevel = LerpedFloat.linear()
|
||||
.startWithValue(getFillState());
|
||||
fluidLevel.chase(getFillState(), .5f, Chaser.EXP);
|
||||
}
|
||||
}
|
||||
|
||||
protected void setLuminosity(int luminosity) {
|
||||
if (level.isClientSide)
|
||||
return;
|
||||
if (this.luminosity == luminosity)
|
||||
return;
|
||||
this.luminosity = luminosity;
|
||||
sendData();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public SteelTankBlockEntity getControllerBE() {
|
||||
if (isController())
|
||||
return this;
|
||||
BlockEntity tileEntity = level.getBlockEntity(controller);
|
||||
if (tileEntity instanceof SteelTankBlockEntity)
|
||||
return (SteelTankBlockEntity) tileEntity;
|
||||
return null;
|
||||
}
|
||||
|
||||
public void applyFluidTankSize(int blocks) {
|
||||
tankInventory.setCapacity(blocks * getCapacityMultiplier());
|
||||
int overflow = tankInventory.getFluidAmount() - tankInventory.getCapacity();
|
||||
if (overflow > 0)
|
||||
tankInventory.drain(overflow, FluidAction.EXECUTE);
|
||||
forceFluidLevelUpdate = true;
|
||||
}
|
||||
|
||||
public void removeController(boolean keepFluids) {
|
||||
if (level.isClientSide)
|
||||
return;
|
||||
updateConnectivity = true;
|
||||
if (!keepFluids)
|
||||
applyFluidTankSize(1);
|
||||
controller = null;
|
||||
width = 1;
|
||||
height = 1;
|
||||
|
||||
onFluidStackChanged(tankInventory.getFluid());
|
||||
|
||||
BlockState state = getBlockState();
|
||||
if (SteelTankBlock.isTank(state)) {
|
||||
state = state.setValue(SteelTankBlock.BOTTOM, true);
|
||||
state = state.setValue(SteelTankBlock.TOP, true);
|
||||
state = state.setValue(SteelTankBlock.SHAPE, window ? SteelTankBlock.Shape.WINDOW : SteelTankBlock.Shape.PLAIN);
|
||||
getLevel().setBlock(worldPosition, state, 22);
|
||||
}
|
||||
refreshCapability();
|
||||
setChanged();
|
||||
sendData();
|
||||
}
|
||||
|
||||
public void toggleWindows() {
|
||||
SteelTankBlockEntity te = getControllerBE();
|
||||
if (te == null)
|
||||
return;
|
||||
if (isDistillationTower)
|
||||
return;
|
||||
te.setWindows(!te.window);
|
||||
}
|
||||
|
||||
public void sendDataImmediately() {
|
||||
syncCooldown = 0;
|
||||
queuedSync = false;
|
||||
sendData();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendData() {
|
||||
if (syncCooldown > 0) {
|
||||
queuedSync = true;
|
||||
return;
|
||||
}
|
||||
super.sendData();
|
||||
queuedSync = false;
|
||||
syncCooldown = SYNC_RATE;
|
||||
}
|
||||
|
||||
public void setWindows(boolean window) {
|
||||
this.window = window;
|
||||
for (int yOffset = 0; yOffset < height; yOffset++) {
|
||||
for (int xOffset = 0; xOffset < width; xOffset++) {
|
||||
for (int zOffset = 0; zOffset < width; zOffset++) {
|
||||
BlockPos pos = this.worldPosition.offset(xOffset, yOffset, zOffset);
|
||||
BlockState blockState = level.getBlockState(pos);
|
||||
if (!SteelTankBlock.isTank(blockState))
|
||||
continue;
|
||||
SteelTankBlock.Shape shape = SteelTankBlock.Shape.PLAIN;
|
||||
if (window) {
|
||||
// SIZE 1: Every tank has a window
|
||||
if (width == 1)
|
||||
shape = SteelTankBlock.Shape.WINDOW;
|
||||
// SIZE 2: Every tank has a corner window
|
||||
if (width == 2)
|
||||
shape = xOffset == 0 ? zOffset == 0 ? SteelTankBlock.Shape.WINDOW_NW : SteelTankBlock.Shape.WINDOW_SW
|
||||
: zOffset == 0 ? SteelTankBlock.Shape.WINDOW_NE : SteelTankBlock.Shape.WINDOW_SE;
|
||||
// SIZE 3: Tanks in the center have a window
|
||||
if (width == 3 && abs(abs(xOffset) - abs(zOffset)) == 1)
|
||||
shape = SteelTankBlock.Shape.WINDOW;
|
||||
}
|
||||
|
||||
level.setBlock(pos, blockState.setValue(SteelTankBlock.SHAPE, shape), 22);
|
||||
level.getChunkSource()
|
||||
.getLightEngine()
|
||||
.checkBlock(pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void updateBoilerState() {
|
||||
if (!isController())
|
||||
return;
|
||||
boolean wasTower = isDistillationTower;
|
||||
boolean changed = evaluate();
|
||||
|
||||
if (wasTower != isDistillationTower) {
|
||||
if (isDistillationTower)
|
||||
setWindows(false);
|
||||
for (int yOffset = 0; yOffset < height; yOffset++)
|
||||
for (int xOffset = 0; xOffset < width; xOffset++)
|
||||
for (int zOffset = 0; zOffset < width; zOffset++)
|
||||
if (level.getBlockEntity(
|
||||
worldPosition.offset(xOffset, yOffset, zOffset)) instanceof SteelTankBlockEntity fte)
|
||||
fte.refreshCapability();
|
||||
}
|
||||
if (changed) {
|
||||
notifyUpdate();
|
||||
refreshCapability();
|
||||
|
||||
}
|
||||
}
|
||||
public boolean evaluate() {
|
||||
boolean hadController = isDistillationTower;
|
||||
boolean foundController = false;
|
||||
BlockPos pos1 = controller == null ? getBlockPos() : controller;
|
||||
for (int yOffset = 0; yOffset < getControllerBE().height; yOffset++) {
|
||||
for (int xOffset = 0; xOffset < getControllerBE().width; xOffset++) {
|
||||
for (int zOffset = 0; zOffset < getControllerBE().width; zOffset++) {
|
||||
BlockPos pos = pos1.offset(xOffset, yOffset, zOffset);
|
||||
BlockState blockState = level.getBlockState(pos);
|
||||
if (!SteelTankBlock.isTank(blockState))
|
||||
continue;
|
||||
for (Direction d : Iterate.directions) {
|
||||
BlockPos attachedPos = pos.relative(d);
|
||||
BlockState attachedState = level.getBlockState(attachedPos);
|
||||
|
||||
if (attachedState.is(TFMGBlocks.STEEL_DISTILLATION_CONTROLLER.get())) {
|
||||
|
||||
if (!foundController) {
|
||||
foundController = true;
|
||||
} else
|
||||
level.destroyBlock(attachedPos, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
isDistillationTower = foundController;
|
||||
|
||||
return hadController != foundController;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void lazyTick() {
|
||||
super.lazyTick();
|
||||
if (isDistillationTower)
|
||||
updateTemperature();
|
||||
}
|
||||
public void updateTemperature() {
|
||||
int prevHeat = activeHeat;
|
||||
activeHeat = 0;
|
||||
BlockPos pos1 = controller == null ? getBlockPos() : controller;
|
||||
SteelTankBlockEntity be = getControllerBE() == null ? this : getControllerBE();
|
||||
|
||||
for (int xOffset = 0; xOffset < be.width; xOffset++) {
|
||||
for (int zOffset = 0; zOffset < be.width; zOffset++) {
|
||||
BlockPos pos = pos1.offset(xOffset, -1, zOffset);
|
||||
BlockState blockState = level.getBlockState(pos);
|
||||
float heat = BoilerHeaters.getActiveHeat(level, pos, blockState);
|
||||
if (heat > 0) {
|
||||
activeHeat += heat;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (activeHeat != prevHeat)
|
||||
notifyUpdate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setController(BlockPos controller) {
|
||||
if (level.isClientSide && !isVirtual())
|
||||
return;
|
||||
if (controller.equals(this.controller))
|
||||
return;
|
||||
this.controller = controller;
|
||||
refreshCapability();
|
||||
setChanged();
|
||||
sendData();
|
||||
}
|
||||
public void refreshCapability() {
|
||||
LazyOptional<IFluidHandler> oldCap = fluidCapability;
|
||||
fluidCapability = LazyOptional.of(() -> handlerForCapability());
|
||||
oldCap.invalidate();
|
||||
}
|
||||
|
||||
private IFluidHandler handlerForCapability() {
|
||||
return isController() ?
|
||||
tankInventory
|
||||
: getControllerBE() != null ? getControllerBE().handlerForCapability() : tankInventory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockPos getController() {
|
||||
return isController() ? worldPosition : controller;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AABB createRenderBoundingBox() {
|
||||
if (isController())
|
||||
return super.createRenderBoundingBox().expandTowards(width - 1, height - 1, width - 1);
|
||||
else
|
||||
return super.createRenderBoundingBox();
|
||||
}
|
||||
@Nullable
|
||||
public SteelTankBlockEntity getOtherFluidTankTileEntity(Direction direction) {
|
||||
BlockEntity otherTE = level.getBlockEntity(worldPosition.relative(direction));
|
||||
if (otherTE instanceof SteelTankBlockEntity)
|
||||
return (SteelTankBlockEntity) otherTE;
|
||||
return null;
|
||||
}
|
||||
@Override
|
||||
public boolean addToGoggleTooltip(List<Component> tooltip, boolean isPlayerSneaking) {
|
||||
SteelTankBlockEntity controllerTE = getControllerBE();
|
||||
if (isDistillationTower)
|
||||
return false;
|
||||
if (getControllerBE() != null)
|
||||
if (getControllerBE().isDistillationTower)
|
||||
return false;
|
||||
|
||||
return containedFluidTooltip(tooltip, isPlayerSneaking,
|
||||
controllerTE.getCapability(ForgeCapabilities.FLUID_HANDLER));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void read(CompoundTag compound, boolean clientPacket) {
|
||||
super.read(compound, clientPacket);
|
||||
|
||||
BlockPos controllerBefore = controller;
|
||||
int prevSize = width;
|
||||
int prevHeight = height;
|
||||
int prevLum = luminosity;
|
||||
|
||||
updateConnectivity = compound.contains("Uninitialized");
|
||||
luminosity = compound.getInt("Luminosity");
|
||||
controller = null;
|
||||
lastKnownPos = null;
|
||||
isDistillationTower = compound.getBoolean("isDistillationTower");
|
||||
|
||||
if (compound.contains("LastKnownPos"))
|
||||
lastKnownPos = NbtUtils.readBlockPos(compound.getCompound("LastKnownPos"));
|
||||
if (compound.contains("Controller"))
|
||||
controller = NbtUtils.readBlockPos(compound.getCompound("Controller"));
|
||||
|
||||
if (isController()) {
|
||||
window = compound.getBoolean("Window");
|
||||
width = compound.getInt("Size");
|
||||
height = compound.getInt("Height");
|
||||
tankInventory.setCapacity(getTotalTankSize() * getCapacityMultiplier());
|
||||
tankInventory.readFromNBT(compound.getCompound("TankContent"));
|
||||
if (tankInventory.getSpace() < 0)
|
||||
tankInventory.drain(-tankInventory.getSpace(), FluidAction.EXECUTE);
|
||||
}
|
||||
|
||||
if (compound.contains("ForceFluidLevel") || fluidLevel == null)
|
||||
fluidLevel = LerpedFloat.linear()
|
||||
.startWithValue(getFillState());
|
||||
if (!clientPacket)
|
||||
return;
|
||||
|
||||
boolean changeOfController =
|
||||
controllerBefore == null ? controller != null : !controllerBefore.equals(controller);
|
||||
if (changeOfController || prevSize != width || prevHeight != height) {
|
||||
if (hasLevel())
|
||||
level.sendBlockUpdated(getBlockPos(), getBlockState(), getBlockState(), 16);
|
||||
if (isController())
|
||||
tankInventory.setCapacity(getCapacityMultiplier() * getTotalTankSize());
|
||||
invalidateRenderBoundingBox();
|
||||
}
|
||||
if (isController()) {
|
||||
float fillState = getFillState();
|
||||
if (compound.contains("ForceFluidLevel") || fluidLevel == null)
|
||||
fluidLevel = LerpedFloat.linear()
|
||||
.startWithValue(fillState);
|
||||
fluidLevel.chase(fillState, 0.5f, Chaser.EXP);
|
||||
}
|
||||
if (luminosity != prevLum && hasLevel())
|
||||
level.getChunkSource()
|
||||
.getLightEngine()
|
||||
.checkBlock(worldPosition);
|
||||
|
||||
if (compound.contains("LazySync"))
|
||||
fluidLevel.chase(fluidLevel.getChaseTarget(), 0.125f, Chaser.EXP);
|
||||
}
|
||||
public void getGaugeRotation() {
|
||||
|
||||
gaugeRotation = Math.min(90, activeHeat * 15);
|
||||
}
|
||||
|
||||
public float getFillState() {
|
||||
return (float) tankInventory.getFluidAmount() / tankInventory.getCapacity();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(CompoundTag compound, boolean clientPacket) {
|
||||
|
||||
if (updateConnectivity)
|
||||
compound.putBoolean("Uninitialized", true);
|
||||
compound.putBoolean("isDistillationTower", isDistillationTower);
|
||||
if (lastKnownPos != null)
|
||||
compound.put("LastKnownPos", NbtUtils.writeBlockPos(lastKnownPos));
|
||||
if (!isController())
|
||||
compound.put("Controller", NbtUtils.writeBlockPos(controller));
|
||||
if (isController()) {
|
||||
compound.putBoolean("Window", window);
|
||||
compound.put("TankContent", tankInventory.writeToNBT(new CompoundTag()));
|
||||
compound.putInt("Size", width);
|
||||
compound.putInt("Height", height);
|
||||
}
|
||||
compound.putInt("Luminosity", luminosity);
|
||||
|
||||
forEachBehaviour(tb -> tb.write(compound, clientPacket));
|
||||
|
||||
if (!clientPacket)
|
||||
return;
|
||||
if (forceFluidLevelUpdate)
|
||||
compound.putBoolean("ForceFluidLevel", true);
|
||||
if (queuedSync)
|
||||
compound.putBoolean("LazySync", true);
|
||||
forceFluidLevelUpdate = false;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> cap, @Nullable Direction side) {
|
||||
if (!fluidCapability.isPresent())
|
||||
refreshCapability();
|
||||
if (cap == ForgeCapabilities.FLUID_HANDLER)
|
||||
return fluidCapability.cast();
|
||||
return super.getCapability(cap, side);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBehaviours(List<BlockEntityBehaviour> behaviours) {
|
||||
//registerAwardables(behaviours, AllAdvancements.STEAM_ENGINE_MAXED, AllAdvancements.PIPE_ORGAN);
|
||||
}
|
||||
|
||||
public IFluidTank getTankInventory() {
|
||||
return tankInventory;
|
||||
}
|
||||
public int getTotalTankSize() {
|
||||
return width * width * height;
|
||||
}
|
||||
public static int getMaxSize() {
|
||||
return MAX_SIZE;
|
||||
}
|
||||
public static int getCapacityMultiplier() {
|
||||
return AllConfigs.server().fluids.fluidTankCapacity.get() * 1000;
|
||||
}
|
||||
public static int getMaxHeight() {
|
||||
return AllConfigs.server().fluids.fluidTankMaxHeight.get();
|
||||
}
|
||||
|
||||
public LerpedFloat getFluidLevel() {
|
||||
return fluidLevel;
|
||||
}
|
||||
public void setFluidLevel(LerpedFloat fluidLevel) {
|
||||
this.fluidLevel = fluidLevel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preventConnectivityUpdate() {
|
||||
updateConnectivity = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyMultiUpdated() {
|
||||
BlockState state = this.getBlockState();
|
||||
if (SteelTankBlock.isTank(state)) { // safety
|
||||
state = state.setValue(SteelTankBlock.BOTTOM, getController().getY() == getBlockPos().getY());
|
||||
state = state.setValue(SteelTankBlock.TOP, getController().getY() + height - 1 == getBlockPos().getY());
|
||||
level.setBlock(getBlockPos(), state, 6);
|
||||
}
|
||||
if (isController())
|
||||
setWindows(window);
|
||||
onFluidStackChanged(tankInventory.getFluid());
|
||||
updateBoilerState();
|
||||
setChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setExtraData(@Nullable Object data) {
|
||||
if (data instanceof Boolean)
|
||||
window = (boolean) data;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Object getExtraData() {
|
||||
return window;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object modifyExtraData(Object data) {
|
||||
if (data instanceof Boolean windows) {
|
||||
windows |= window;
|
||||
return windows;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Direction.Axis getMainConnectionAxis() {
|
||||
return Direction.Axis.Y;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxLength(Direction.Axis longAxis, int width) {
|
||||
if (longAxis == Direction.Axis.Y)
|
||||
return getMaxHeight();
|
||||
return getMaxWidth();
|
||||
}
|
||||
@Override
|
||||
public int getMaxWidth() {
|
||||
return MAX_SIZE;
|
||||
}
|
||||
@Override
|
||||
public int getHeight() {
|
||||
return height;
|
||||
}
|
||||
@Override
|
||||
public void setHeight(int height) {
|
||||
this.height = height;
|
||||
}
|
||||
@Override
|
||||
public int getWidth() {
|
||||
return width;
|
||||
}
|
||||
@Override
|
||||
public void setWidth(int width) {
|
||||
this.width = width;
|
||||
}
|
||||
@Override
|
||||
public boolean hasTank() {
|
||||
return true;
|
||||
}
|
||||
@Override
|
||||
public int getTankSize(int tank) {
|
||||
return getCapacityMultiplier();
|
||||
}
|
||||
@Override
|
||||
public void setTankSize(int tank, int blocks) {
|
||||
applyFluidTankSize(blocks);
|
||||
}
|
||||
@Override
|
||||
public IFluidTank getTank(int tank) {
|
||||
return tankInventory;
|
||||
}
|
||||
@Override
|
||||
public FluidStack getFluid(int tank) {
|
||||
return tankInventory.getFluid()
|
||||
.copy();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
package com.drmangotea.tfmg.content.decoration.tank;
|
||||
|
||||
import com.simibubi.create.foundation.data.AssetLookup;
|
||||
import com.simibubi.create.foundation.data.SpecialBlockStateGen;
|
||||
import com.tterrag.registrate.providers.DataGenContext;
|
||||
import com.tterrag.registrate.providers.RegistrateBlockstateProvider;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraftforge.client.model.generators.ModelFile;
|
||||
|
||||
public class SteelTankGenerator extends SpecialBlockStateGen {
|
||||
|
||||
private String prefix;
|
||||
|
||||
public SteelTankGenerator() {
|
||||
this("");
|
||||
}
|
||||
|
||||
public SteelTankGenerator(String prefix) {
|
||||
this.prefix = prefix;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getXRotation(BlockState state) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getYRotation(BlockState state) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends Block> ModelFile getModel(DataGenContext<Block, T> ctx, RegistrateBlockstateProvider prov,
|
||||
BlockState state) {
|
||||
Boolean top = state.getValue(SteelTankBlock.TOP);
|
||||
Boolean bottom = state.getValue(SteelTankBlock.BOTTOM);
|
||||
SteelTankBlock.Shape shape = state.getValue(SteelTankBlock.SHAPE);
|
||||
|
||||
String shapeName = "middle";
|
||||
if (top && bottom)
|
||||
shapeName = "single";
|
||||
else if (top)
|
||||
shapeName = "top";
|
||||
else if (bottom)
|
||||
shapeName = "bottom";
|
||||
|
||||
String modelName = shapeName + (shape == SteelTankBlock.Shape.PLAIN ? "" : "_" + shape.getSerializedName());
|
||||
|
||||
if (!prefix.isEmpty())
|
||||
return prov.models()
|
||||
.withExistingParent(prefix + modelName, prov.modLoc("block/fluid_tank/block_" + modelName))
|
||||
.texture("0", prov.modLoc("block/" + prefix + "casing"))
|
||||
.texture("1", prov.modLoc("block/" + prefix + "fluid_tank"))
|
||||
.texture("3", prov.modLoc("block/" + prefix + "fluid_tank_window"))
|
||||
.texture("4", prov.modLoc("block/" + prefix + "casing"))
|
||||
.texture("5", prov.modLoc("block/" + prefix + "fluid_tank_window_single"))
|
||||
.texture("particle", prov.modLoc("block/" + prefix + "steel_fluid_tank"));
|
||||
|
||||
return AssetLookup.partialBaseModel(ctx, prov, modelName);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
package com.drmangotea.tfmg.content.decoration.tank;
|
||||
|
||||
|
||||
import com.drmangotea.tfmg.registry.TFMGBlockEntities;
|
||||
import com.simibubi.create.api.connectivity.ConnectivityHandler;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.world.InteractionResult;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.BlockItem;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.context.BlockPlaceContext;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraftforge.fluids.FluidStack;
|
||||
|
||||
public class SteelTankItem extends BlockItem {
|
||||
|
||||
public SteelTankItem(Block p_i48527_1_, Properties p_i48527_2_) {
|
||||
super(p_i48527_1_, p_i48527_2_);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InteractionResult place(BlockPlaceContext ctx) {
|
||||
InteractionResult initialResult = super.place(ctx);
|
||||
if (!initialResult.consumesAction())
|
||||
return initialResult;
|
||||
tryMultiPlace(ctx);
|
||||
return initialResult;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean updateCustomBlockEntityTag(BlockPos p_195943_1_, Level p_195943_2_, Player p_195943_3_,
|
||||
ItemStack p_195943_4_, BlockState p_195943_5_) {
|
||||
MinecraftServer minecraftserver = p_195943_2_.getServer();
|
||||
if (minecraftserver == null)
|
||||
return false;
|
||||
CompoundTag nbt = p_195943_4_.getTagElement("BlockEntityTag");
|
||||
if (nbt != null) {
|
||||
nbt.remove("Luminosity");
|
||||
nbt.remove("Size");
|
||||
nbt.remove("Height");
|
||||
nbt.remove("Controller");
|
||||
nbt.remove("LastKnownPos");
|
||||
if (nbt.contains("TankContent")) {
|
||||
FluidStack fluid = FluidStack.loadFluidStackFromNBT(nbt.getCompound("TankContent"));
|
||||
if (!fluid.isEmpty()) {
|
||||
fluid.setAmount(Math.min(SteelTankBlockEntity.getCapacityMultiplier(), fluid.getAmount()));
|
||||
nbt.put("TankContent", fluid.writeToNBT(new CompoundTag()));
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.updateCustomBlockEntityTag(p_195943_1_, p_195943_2_, p_195943_3_, p_195943_4_, p_195943_5_);
|
||||
}
|
||||
|
||||
private void tryMultiPlace(BlockPlaceContext ctx) {
|
||||
|
||||
Player player = ctx.getPlayer();
|
||||
if (player == null)
|
||||
return;
|
||||
if (player.isShiftKeyDown())
|
||||
return;
|
||||
Direction face = ctx.getClickedFace();
|
||||
if (!face.getAxis()
|
||||
.isVertical())
|
||||
return;
|
||||
ItemStack stack = ctx.getItemInHand();
|
||||
Level world = ctx.getLevel();
|
||||
BlockPos pos = ctx.getClickedPos();
|
||||
BlockPos placedOnPos = pos.relative(face.getOpposite());
|
||||
BlockState placedOnState = world.getBlockState(placedOnPos);
|
||||
|
||||
if (!SteelTankBlock.isTank(placedOnState))
|
||||
return;
|
||||
|
||||
SteelTankBlockEntity tankAt = ConnectivityHandler.partAt(
|
||||
TFMGBlockEntities.STEEL_FLUID_TANK.get(), world, placedOnPos
|
||||
);
|
||||
if (tankAt == null)
|
||||
return;
|
||||
SteelTankBlockEntity controllerTE = (SteelTankBlockEntity) tankAt.getControllerBE();
|
||||
if (controllerTE == null)
|
||||
return;
|
||||
|
||||
int width = controllerTE.width;
|
||||
if (width == 1)
|
||||
return;
|
||||
|
||||
int tanksToPlace = 0;
|
||||
BlockPos startPos = face == Direction.DOWN ? controllerTE.getBlockPos()
|
||||
.below()
|
||||
: controllerTE.getBlockPos()
|
||||
.above(controllerTE.height);
|
||||
|
||||
if (startPos.getY() != pos.getY())
|
||||
return;
|
||||
|
||||
for (int xOffset = 0; xOffset < width; xOffset++) {
|
||||
for (int zOffset = 0; zOffset < width; zOffset++) {
|
||||
BlockPos offsetPos = startPos.offset(xOffset, 0, zOffset);
|
||||
BlockState blockState = world.getBlockState(offsetPos);
|
||||
if (SteelTankBlock.isTank(blockState))
|
||||
continue;
|
||||
if (!blockState.canBeReplaced())
|
||||
return;
|
||||
tanksToPlace++;
|
||||
}
|
||||
}
|
||||
|
||||
if (!player.isCreative() && stack.getCount() < tanksToPlace)
|
||||
return;
|
||||
|
||||
for (int xOffset = 0; xOffset < width; xOffset++) {
|
||||
for (int zOffset = 0; zOffset < width; zOffset++) {
|
||||
BlockPos offsetPos = startPos.offset(xOffset, 0, zOffset);
|
||||
BlockState blockState = world.getBlockState(offsetPos);
|
||||
if (SteelTankBlock.isTank(blockState))
|
||||
continue;
|
||||
BlockPlaceContext context = BlockPlaceContext.at(ctx, offsetPos, face);
|
||||
player.getPersistentData()
|
||||
.putBoolean("SilenceTankSound", true);
|
||||
super.place(context);
|
||||
player.getPersistentData()
|
||||
.remove("SilenceTankSound");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
package com.drmangotea.tfmg.content.decoration.tank;
|
||||
|
||||
|
||||
import com.drmangotea.tfmg.base.TFMGSpriteShifts;
|
||||
import com.simibubi.create.api.connectivity.ConnectivityHandler;
|
||||
import com.simibubi.create.content.fluids.tank.FluidTankCTBehaviour;
|
||||
import com.simibubi.create.foundation.block.connected.CTModel;
|
||||
import com.simibubi.create.foundation.block.connected.CTSpriteShiftEntry;
|
||||
import com.simibubi.create.foundation.utility.Iterate;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.client.renderer.block.model.BakedQuad;
|
||||
import net.minecraft.client.resources.model.BakedModel;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.level.BlockAndTintGetter;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraftforge.client.model.data.ModelData;
|
||||
import net.minecraftforge.client.model.data.ModelProperty;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class TFMGFluidTankModel extends CTModel {
|
||||
|
||||
protected static final ModelProperty<CullData> CULL_PROPERTY = new ModelProperty<>();
|
||||
|
||||
public static TFMGFluidTankModel standard(BakedModel originalModel) {
|
||||
return new TFMGFluidTankModel(originalModel, TFMGSpriteShifts.STEEL_FLUID_TANK, TFMGSpriteShifts.STEEL_FLUID_TANK_TOP,
|
||||
TFMGSpriteShifts.STEEL_FLUID_TANK_INNER);
|
||||
}
|
||||
|
||||
|
||||
private TFMGFluidTankModel(BakedModel originalModel, CTSpriteShiftEntry side, CTSpriteShiftEntry top,
|
||||
CTSpriteShiftEntry inner) {
|
||||
super(originalModel, new FluidTankCTBehaviour(side, top, inner));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ModelData.Builder gatherModelData(ModelData.Builder builder, BlockAndTintGetter world, BlockPos pos, BlockState state,
|
||||
ModelData blockEntityData) {
|
||||
super.gatherModelData(builder, world, pos, state, blockEntityData);
|
||||
CullData cullData = new CullData();
|
||||
for (Direction d : Iterate.horizontalDirections)
|
||||
cullData.setCulled(d, ConnectivityHandler.isConnected(world, pos, pos.relative(d)));
|
||||
return builder.with(CULL_PROPERTY, cullData);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BakedQuad> getQuads(BlockState state, Direction side, RandomSource rand, ModelData extraData, RenderType renderType) {
|
||||
if (side != null)
|
||||
return Collections.emptyList();
|
||||
|
||||
List<BakedQuad> quads = new ArrayList<>();
|
||||
for (Direction d : Iterate.directions) {
|
||||
if (extraData.has(CULL_PROPERTY) && extraData.get(CULL_PROPERTY)
|
||||
.isCulled(d))
|
||||
continue;
|
||||
quads.addAll(super.getQuads(state, d, rand, extraData, renderType));
|
||||
}
|
||||
quads.addAll(super.getQuads(state, null, rand, extraData, renderType));
|
||||
return quads;
|
||||
}
|
||||
private class CullData {
|
||||
boolean[] culledFaces;
|
||||
|
||||
public CullData() {
|
||||
culledFaces = new boolean[4];
|
||||
Arrays.fill(culledFaces, false);
|
||||
}
|
||||
|
||||
void setCulled(Direction face, boolean cull) {
|
||||
if (face.getAxis()
|
||||
.isVertical())
|
||||
return;
|
||||
culledFaces[face.get2DDataValue()] = cull;
|
||||
}
|
||||
|
||||
boolean isCulled(Direction face) {
|
||||
if (face.getAxis()
|
||||
.isVertical())
|
||||
return false;
|
||||
return culledFaces[face.get2DDataValue()];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.drmangotea.tfmg.content.electricity.base;
|
||||
|
||||
|
||||
import com.simibubi.create.foundation.blockEntity.SmartBlockEntity;
|
||||
import com.simibubi.create.foundation.networking.BlockEntityDataPacket;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
|
||||
public class ConnectNeightborsPacket extends BlockEntityDataPacket<SmartBlockEntity> {
|
||||
|
||||
|
||||
|
||||
|
||||
public ConnectNeightborsPacket(BlockPos pos) {
|
||||
super(pos);
|
||||
|
||||
|
||||
}
|
||||
|
||||
public ConnectNeightborsPacket(FriendlyByteBuf buffer) {
|
||||
super(buffer);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void writeData(FriendlyByteBuf buffer) {}
|
||||
|
||||
@Override
|
||||
protected void handlePacket(SmartBlockEntity blockEntity) {
|
||||
|
||||
if(blockEntity instanceof IElectric be) {
|
||||
be.onPlaced();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package com.drmangotea.tfmg.content.electricity.base;
|
||||
|
||||
|
||||
import com.simibubi.create.foundation.blockEntity.SmartBlockEntity;
|
||||
import com.simibubi.create.foundation.networking.BlockEntityDataPacket;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
|
||||
public class ConnectionPacket extends BlockEntityDataPacket<SmartBlockEntity> {
|
||||
|
||||
|
||||
|
||||
|
||||
public ConnectionPacket(BlockPos pos) {
|
||||
super(pos);
|
||||
|
||||
|
||||
}
|
||||
|
||||
public ConnectionPacket(FriendlyByteBuf buffer) {
|
||||
super(buffer);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void writeData(FriendlyByteBuf buffer) {}
|
||||
|
||||
@Override
|
||||
protected void handlePacket(SmartBlockEntity blockEntity) {
|
||||
|
||||
if(blockEntity instanceof IElectric be) {
|
||||
be.onConnected();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,245 @@
|
||||
package com.drmangotea.tfmg.content.electricity.base;
|
||||
|
||||
import com.drmangotea.tfmg.TFMG;
|
||||
import com.drmangotea.tfmg.registry.TFMGPackets;
|
||||
import com.simibubi.create.content.equipment.goggles.IHaveHoveringInformation;
|
||||
import com.simibubi.create.foundation.blockEntity.SmartBlockEntity;
|
||||
import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.world.level.LevelAccessor;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraftforge.network.PacketDistributor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ElectricBlockEntity extends SmartBlockEntity implements IElectric, IHaveHoveringInformation {
|
||||
|
||||
public ElectricBlockValues data = new ElectricBlockValues(getPos());
|
||||
|
||||
int powerPercentage = 100;
|
||||
public ElectricBlockEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) {
|
||||
super(type, pos, state);
|
||||
data.connectNextTick = true;
|
||||
}
|
||||
@Override
|
||||
public boolean addToTooltip(List<Component> tooltip, boolean isPlayerSneaking) {
|
||||
return makeElectricityTooltip(tooltip, isPlayerSneaking);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void addBehaviours(List<BlockEntityBehaviour> behaviours) {}
|
||||
|
||||
@Override
|
||||
public LevelAccessor getLevelAccessor(){
|
||||
return level;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean destroyed() {
|
||||
return data.destroyed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ElectricalNetwork getOrCreateElectricNetwork() {
|
||||
if(level.getBlockEntity(BlockPos.of(data.electricalNetworkId)) instanceof IElectric) {
|
||||
return TFMG.NETWORK_MANAGER.getOrCreateNetworkFor((IElectric) level.getBlockEntity(BlockPos.of(data.electricalNetworkId)));
|
||||
} else {
|
||||
ElectricNetworkManager.networks.get(getLevel())
|
||||
.remove(data.electricalNetworkId);
|
||||
return TFMG.NETWORK_MANAGER.getOrCreateNetworkFor(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ElectricBlockValues getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public int getPowerPercentage() {
|
||||
return powerPercentage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float resistance() {
|
||||
return 0;
|
||||
}
|
||||
@Override
|
||||
public int voltageGeneration() {
|
||||
|
||||
int voltageGeneration = 0;
|
||||
|
||||
for(Direction direction : Direction.values()){
|
||||
if(hasElectricitySlot(direction)){
|
||||
|
||||
if(level.getBlockEntity(getBlockPos().relative(direction)) instanceof VoltageAlteringBlockEntity be)
|
||||
if(be.getData().getId() !=getData().getId())
|
||||
if(be.getData().getVoltage()!=0)
|
||||
if(be.hasElectricitySlot(direction)){
|
||||
voltageGeneration = Math.max(voltageGeneration,be.getOutputVoltage());
|
||||
data.getsOutsidePower = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(voltageGeneration == 0)
|
||||
data.getsOutsidePower = false;
|
||||
|
||||
return voltageGeneration;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int powerGeneration() {
|
||||
|
||||
int powerGeneration = 0;
|
||||
|
||||
for(Direction direction : Direction.values()){
|
||||
if(hasElectricitySlot(direction)){
|
||||
|
||||
if(level.getBlockEntity(getBlockPos().relative(direction)) instanceof VoltageAlteringBlockEntity be)
|
||||
if(be.getData().getId() !=getData().getId())
|
||||
if(be.getData().getVoltage()!=0)
|
||||
if(be.hasElectricitySlot(direction)){
|
||||
powerGeneration = Math.max(powerGeneration,be.getOutputPower());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return powerGeneration;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int frequencyGeneration() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void updateNextTick() {
|
||||
data.updateNextTick = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateNetwork() {
|
||||
getOrCreateElectricNetwork().updateNetwork();
|
||||
if(!level.isClientSide)
|
||||
TFMGPackets.getChannel().send(PacketDistributor.ALL.noArg(), new NetworkUpdatePacket(BlockPos.of(getPos())));
|
||||
sendData();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendStuff() {
|
||||
sendData();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVoltage(int newVoltage) {
|
||||
if(canBeInGroups()){
|
||||
data.voltage = (int) (((float)resistance()/data.group.resistance)*(float)data.voltageSupply);
|
||||
return;
|
||||
}
|
||||
data.voltage = newVoltage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFrequency(int newFrequency) {
|
||||
data.frequency = newFrequency;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNetworkResistance(int newUsage) {
|
||||
data.networkResistance = newUsage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNetworkResistance() {
|
||||
return data.networkResistance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setWattage(int newWattage) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPowerPercentage(int percentage) {
|
||||
powerPercentage = percentage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNetwork(long network) {
|
||||
this.data.electricalNetworkId = network;
|
||||
if(network!=getPos())
|
||||
ElectricNetworkManager.networks.get(getLevel())
|
||||
.remove(getPos());
|
||||
}
|
||||
|
||||
public boolean networkUndersupplied(){
|
||||
return getNetworkPowerUsage()>data.networkPowerGeneration;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public long getPos() {
|
||||
return getBlockPos().asLong();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
super.remove();
|
||||
this.data.destroyed = true;
|
||||
for(Direction d : Direction.values()) {
|
||||
if(hasElectricitySlot(d))
|
||||
if(getLevelAccessor().getBlockEntity(BlockPos.of(getPos()).relative(d)) instanceof IElectric be&&be.hasElectricitySlot(d.getOpposite())) {
|
||||
ElectricNetworkManager.networks.get(getLevel())
|
||||
.remove(be.getPos());
|
||||
be.setNetwork(be.getPos());
|
||||
be.onPlaced();
|
||||
be.updateNextTick();
|
||||
}
|
||||
}
|
||||
if(data.electricalNetworkId != getPos())
|
||||
getOrCreateElectricNetwork().getMembers().remove(this);
|
||||
|
||||
if(data.electricalNetworkId == getPos())
|
||||
ElectricNetworkManager.networks.get(getLevel())
|
||||
.remove(getData().getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
super.tick();
|
||||
if(data.connectNextTick) {
|
||||
onPlaced();
|
||||
data.connectNextTick = false;
|
||||
}
|
||||
if(data.updateNextTick) {
|
||||
updateNetwork();
|
||||
data.updateNextTick = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void write(CompoundTag tag, boolean clientPacket) {
|
||||
super.write(tag, clientPacket);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void read(CompoundTag tag, boolean clientPacket) {
|
||||
super.read(tag, clientPacket);
|
||||
if(!clientPacket)
|
||||
data.connectNextTick = true;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.drmangotea.tfmg.content.electricity.base;
|
||||
|
||||
public class ElectricBlockValues {
|
||||
|
||||
|
||||
public long electricalNetworkId;
|
||||
public boolean destroyed = false;
|
||||
public boolean connectNextTick = false;
|
||||
public boolean updateNextTick = false;
|
||||
public boolean getsOutsidePower = false;
|
||||
public int networkResistance = 0;
|
||||
public int voltage = 0;
|
||||
public int frequency = 0;
|
||||
public int voltageSupply = 0;
|
||||
public int networkPowerGeneration =0;
|
||||
|
||||
public ElectricalGroup group = new ElectricalGroup(0);
|
||||
|
||||
public ElectricBlockValues(long pos){
|
||||
this.electricalNetworkId = pos;
|
||||
}
|
||||
|
||||
public long getId(){
|
||||
return electricalNetworkId;
|
||||
}
|
||||
public boolean destroyed(){
|
||||
return destroyed;
|
||||
}
|
||||
public int getVoltage(){
|
||||
return voltage;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.drmangotea.tfmg.content.electricity.base;
|
||||
|
||||
import net.minecraft.world.level.LevelAccessor;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class ElectricNetworkManager {
|
||||
|
||||
public static Map<LevelAccessor, Map<Long, ElectricalNetwork>> networks = new HashMap<>();
|
||||
|
||||
public void onLoadWorld(LevelAccessor world) {
|
||||
networks.put(world, new HashMap<>());
|
||||
|
||||
}
|
||||
public void onUnloadWorld(LevelAccessor world) {
|
||||
networks.remove(world);
|
||||
|
||||
}
|
||||
public ElectricalNetwork getOrCreateNetworkFor(IElectric be) {
|
||||
Long id = be.getData().getId();
|
||||
ElectricalNetwork network;
|
||||
Map<Long, ElectricalNetwork> map = networks.computeIfAbsent(be.getLevelAccessor(), $ -> new HashMap<>());
|
||||
|
||||
if (!map.containsKey(id)) {
|
||||
network = new ElectricalNetwork(id);
|
||||
|
||||
if(be instanceof IElectric) {
|
||||
network.add((IElectric) be);
|
||||
be.setNetwork(be.getData().getId());
|
||||
}
|
||||
map.put(id, network);
|
||||
}
|
||||
network = map.get(id);
|
||||
return network;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.drmangotea.tfmg.content.electricity.base;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ElectricalGroup {
|
||||
|
||||
public int id;
|
||||
public float resistance=0;
|
||||
|
||||
public ElectricalGroup(int id){
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
package com.drmangotea.tfmg.content.electricity.base;
|
||||
|
||||
import com.drmangotea.tfmg.TFMG;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class ElectricalNetwork {
|
||||
|
||||
public ElectricalNetwork(long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public List<IElectric> members = new ArrayList<>();
|
||||
|
||||
public long id;
|
||||
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void add(IElectric be) {
|
||||
List<Long> posList = new ArrayList<>();
|
||||
|
||||
members.forEach(member -> posList.add(member.getData().getId()));
|
||||
|
||||
if (posList.contains(be.getData().getId()))
|
||||
return;
|
||||
members.add(be);
|
||||
|
||||
}
|
||||
|
||||
public void updateNetwork() {
|
||||
int maxVoltage = 0;
|
||||
int power = 0;
|
||||
int frequency = 0;
|
||||
int resistance = 0;
|
||||
int powerGeneration = 0;
|
||||
|
||||
|
||||
|
||||
Map<Integer, Float> groups = new HashMap<>();
|
||||
|
||||
for (IElectric member : members) {
|
||||
int groupId = member.getData().group.id;
|
||||
|
||||
maxVoltage = Math.max(member.voltageGeneration(), maxVoltage);
|
||||
power += member.powerGeneration();
|
||||
frequency = frequency == 0 ? member.frequencyGeneration() : (frequency + member.frequencyGeneration()) / 2;
|
||||
resistance += (int) member.resistance();
|
||||
powerGeneration += member.powerGeneration();
|
||||
if(member.canBeInGroups())
|
||||
groups.put(groupId, (groups.containsKey(groupId) ? groups.get(groupId) + member.resistance() : member.resistance()));
|
||||
}
|
||||
|
||||
int powerPercentage = resistance > 0 ? (int) (Math.min(((float) power / (float) resistance * 100f), 100)) : 100;
|
||||
|
||||
for (IElectric member : members) {
|
||||
|
||||
int oldVoltage = member.getData().getVoltage();
|
||||
int oldPower = member.getPowerUsage();
|
||||
|
||||
member.setVoltage(maxVoltage);
|
||||
member.getData().voltageSupply = maxVoltage;
|
||||
member.getData().networkPowerGeneration = powerGeneration;
|
||||
member.setWattage(power);
|
||||
member.setFrequency(frequency);
|
||||
member.setNetworkResistance(resistance);
|
||||
member.onNetworkChanged(oldVoltage, oldPower);
|
||||
member.setPowerPercentage(powerPercentage);
|
||||
member.updateNearbyNetworks(member);
|
||||
if(groups.containsKey(member.getData().group.id))
|
||||
member.getData().group.resistance = groups.get(member.getData().group.id);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public List<IElectric> getMembers() {
|
||||
return members;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,172 @@
|
||||
package com.drmangotea.tfmg.content.electricity.base;
|
||||
|
||||
import com.drmangotea.tfmg.TFMG;
|
||||
import com.drmangotea.tfmg.base.TFMGUtils;
|
||||
import com.drmangotea.tfmg.registry.TFMGPackets;
|
||||
import com.simibubi.create.foundation.utility.Lang;
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.world.level.LevelAccessor;
|
||||
import net.minecraftforge.network.PacketDistributor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
public interface IElectric {
|
||||
long getPos();
|
||||
LevelAccessor getLevelAccessor();
|
||||
boolean destroyed();
|
||||
ElectricalNetwork getOrCreateElectricNetwork();
|
||||
default boolean hasElectricitySlot(Direction direction){
|
||||
return true;
|
||||
}
|
||||
|
||||
default void onPlaced(){
|
||||
if(!getLevelAccessor().isClientSide())
|
||||
TFMGPackets.getChannel().send(PacketDistributor.ALL.noArg(), new ConnectNeightborsPacket(BlockPos.of(getPos())));
|
||||
TFMG.NETWORK_MANAGER.getOrCreateNetworkFor(this);
|
||||
setNetwork(getPos());
|
||||
updateNetwork();
|
||||
onConnected();
|
||||
sendStuff();
|
||||
updateNextTick();
|
||||
}
|
||||
default void onConnected(){
|
||||
|
||||
|
||||
BlockPos pos = BlockPos.of(getPos());
|
||||
for(Direction d : Direction.values()){
|
||||
if(hasElectricitySlot(d))
|
||||
if(getLevelAccessor().getBlockEntity(pos.relative(d)) instanceof IElectric be){
|
||||
if(be.hasElectricitySlot(d.getOpposite())) {
|
||||
if (!be.destroyed()) {
|
||||
getOrCreateElectricNetwork().add(be);
|
||||
if (be.getData().getId() != getData().getId()) {
|
||||
be.setNetwork(getData().getId());
|
||||
be.onConnected();
|
||||
if (!getLevelAccessor().isClientSide())
|
||||
sendStuff();
|
||||
}
|
||||
}
|
||||
} else if(be.getData().getId()!=getData().getId()){
|
||||
be.updateNextTick();
|
||||
}
|
||||
}
|
||||
}
|
||||
sendStuff();
|
||||
}
|
||||
|
||||
|
||||
default boolean makeElectricityTooltip(List<Component> tooltip, boolean isPlayerSneaking){
|
||||
|
||||
|
||||
Lang.translate("multimeter.header")
|
||||
.style(ChatFormatting.WHITE)
|
||||
.forGoggles(tooltip, 1);
|
||||
Lang.text(" R = "+TFMGUtils.formatUnits(voltageGeneration()>0 ? getGeneratorResistance() : resistance(), "Ω"))
|
||||
.style(ChatFormatting.GOLD)
|
||||
.forGoggles(tooltip, 1);
|
||||
Lang.text(" P = "+TFMGUtils.formatUnits(getPowerUsage(), "W"))
|
||||
.style(ChatFormatting.GOLD)
|
||||
.forGoggles(tooltip, 1);
|
||||
Lang.text(" U = "+TFMGUtils.formatUnits(getData().getVoltage(), "V"))
|
||||
.style(ChatFormatting.AQUA)
|
||||
.forGoggles(tooltip, 1);
|
||||
Lang.text(" I = "+TFMGUtils.formatUnits(getCurrent(), "A"))
|
||||
.style(ChatFormatting.GREEN)
|
||||
.forGoggles(tooltip, 1);
|
||||
|
||||
////////
|
||||
Lang.text(" Network Resistance: "+TFMGUtils.formatUnits(getNetworkResistance(), "Ω"))
|
||||
.style(ChatFormatting.YELLOW)
|
||||
.forGoggles(tooltip, 1);
|
||||
Lang.text(" Network Power Usage: "+TFMGUtils.formatUnits(getNetworkPowerUsage(), "W"))
|
||||
.style(ChatFormatting.YELLOW)
|
||||
.forGoggles(tooltip, 1);
|
||||
Lang.text(" Group: "+getData().group.id)
|
||||
.style(ChatFormatting.DARK_PURPLE)
|
||||
.forGoggles(tooltip, 1);
|
||||
Lang.text(" Group Resistance: "+getData().group.resistance)
|
||||
.style(ChatFormatting.DARK_PURPLE)
|
||||
.forGoggles(tooltip, 1);
|
||||
Lang.text(" Voltage Supply: "+getData().voltageSupply)
|
||||
.style(ChatFormatting.DARK_PURPLE)
|
||||
.forGoggles(tooltip, 1);
|
||||
|
||||
|
||||
if(voltageGeneration() > 0) {
|
||||
Lang.translate("multimeter.power_generated")
|
||||
.add(Component.literal(TFMGUtils.formatUnits(powerGeneration(), "W")))
|
||||
.style(ChatFormatting.BLUE)
|
||||
.forGoggles(tooltip, 1);
|
||||
Lang.translate("multimeter.voltage_generated")
|
||||
.add(Component.literal(TFMGUtils.formatUnits(voltageGeneration(), "V")))
|
||||
.style(ChatFormatting.BLUE)
|
||||
.forGoggles(tooltip, 1);
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
default void updateNearbyNetworks(IElectric member){
|
||||
if(member.getData().getsOutsidePower)
|
||||
for(Direction direction : Direction.values()){
|
||||
if(member.getLevelAccessor().getBlockEntity(BlockPos.of(member.getPos()).relative(direction)) instanceof IElectric be&&be.getData().getId()!=be.getData().getId()){
|
||||
be.updateNextTick();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ElectricBlockValues getData();
|
||||
default int getPowerUsage(){
|
||||
return (int) (getData().getVoltage()*getCurrent());
|
||||
}
|
||||
default int getNetworkPowerUsage(){
|
||||
int power=0;
|
||||
for(IElectric member : getOrCreateElectricNetwork().members)
|
||||
power+=member.getPowerUsage();
|
||||
return power;
|
||||
}
|
||||
default void onNetworkChanged(int oldVoltage, int oldPower){}
|
||||
|
||||
default float getGeneratorResistance(){
|
||||
if(getData().voltageSupply == 0)
|
||||
return 0;
|
||||
return (float) powerGeneration() / (float)getData().networkPowerGeneration *(float)getNetworkResistance();
|
||||
}
|
||||
default float getGeneratorLoad(){
|
||||
if(getNetworkPowerUsage() == 0)
|
||||
return 0;
|
||||
return (float) powerGeneration() / (float)getData().networkPowerGeneration *getNetworkPowerUsage();
|
||||
}
|
||||
int getPowerPercentage();
|
||||
float resistance();
|
||||
int voltageGeneration();
|
||||
int powerGeneration();
|
||||
int frequencyGeneration();
|
||||
int getNetworkResistance();
|
||||
default int getMaxAmps(){
|
||||
return (int) getCurrent();
|
||||
}
|
||||
default float getCurrent(){
|
||||
return getData().getVoltage()==0||resistance() == 0 ? 0 : ((float) getData().getVoltage() / (float) resistance());
|
||||
}
|
||||
void updateNextTick();
|
||||
void updateNetwork();
|
||||
void sendStuff();
|
||||
void setVoltage(int newVoltage);
|
||||
void setFrequency(int newFrequency);
|
||||
void setNetworkResistance(int newUsage);
|
||||
void setWattage(int newWattage);
|
||||
void setPowerPercentage(int percentage);
|
||||
void setNetwork(long network);
|
||||
default boolean canBeInGroups(){
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
package com.drmangotea.tfmg.content.electricity.base;
|
||||
|
||||
public interface IVoltageChanger {
|
||||
}
|
||||
@@ -0,0 +1,266 @@
|
||||
package com.drmangotea.tfmg.content.electricity.base;
|
||||
|
||||
import com.drmangotea.tfmg.TFMG;
|
||||
import com.drmangotea.tfmg.registry.TFMGPackets;
|
||||
import com.simibubi.create.content.equipment.goggles.IHaveGoggleInformation;
|
||||
import com.simibubi.create.content.equipment.goggles.IHaveHoveringInformation;
|
||||
import com.simibubi.create.content.kinetics.base.GeneratingKineticBlockEntity;
|
||||
import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.world.level.LevelAccessor;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraftforge.network.PacketDistributor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class KineticElectricBlockEntity extends GeneratingKineticBlockEntity implements IElectric, IHaveGoggleInformation, IHaveHoveringInformation {
|
||||
|
||||
public ElectricBlockValues data = new ElectricBlockValues(getPos());
|
||||
int powerPercentage = 100;
|
||||
|
||||
int timer = 0;
|
||||
|
||||
|
||||
public KineticElectricBlockEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) {
|
||||
super(type, pos, state);
|
||||
data.connectNextTick = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addToTooltip(List<Component> tooltip, boolean isPlayerSneaking) {
|
||||
return makeElectricityTooltip(tooltip, isPlayerSneaking);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBehaviours(List<BlockEntityBehaviour> behaviours) {}
|
||||
|
||||
@Override
|
||||
public LevelAccessor getLevelAccessor(){
|
||||
return level;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean destroyed() {
|
||||
return data.destroyed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ElectricalNetwork getOrCreateElectricNetwork() {
|
||||
if(level.getBlockEntity(BlockPos.of(data.electricalNetworkId)) instanceof IElectric) {
|
||||
return TFMG.NETWORK_MANAGER.getOrCreateNetworkFor((IElectric) level.getBlockEntity(BlockPos.of(data.electricalNetworkId)));
|
||||
} else {
|
||||
ElectricNetworkManager.networks.get(getLevel())
|
||||
.remove(data.electricalNetworkId);
|
||||
return TFMG.NETWORK_MANAGER.getOrCreateNetworkFor(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ElectricBlockValues getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public int getPowerPercentage() {
|
||||
return powerPercentage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float resistance() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int voltageGeneration() {
|
||||
|
||||
int voltageGeneration = 0;
|
||||
|
||||
for(Direction direction : Direction.values()){
|
||||
if(hasElectricitySlot(direction)){
|
||||
|
||||
if(level.getBlockEntity(getBlockPos().relative(direction)) instanceof VoltageAlteringBlockEntity be)
|
||||
if(be.getData().getId() !=getData().getId())
|
||||
if(be.getData().getVoltage()!=0)
|
||||
if(be.hasElectricitySlot(direction)){
|
||||
voltageGeneration = Math.max(voltageGeneration,be.getOutputVoltage());
|
||||
data.getsOutsidePower = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(voltageGeneration == 0)
|
||||
data.getsOutsidePower = false;
|
||||
|
||||
return voltageGeneration;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int powerGeneration() {
|
||||
|
||||
int powerGeneration = 0;
|
||||
|
||||
for(Direction direction : Direction.values()){
|
||||
if(hasElectricitySlot(direction)){
|
||||
|
||||
if(level.getBlockEntity(getBlockPos().relative(direction)) instanceof VoltageAlteringBlockEntity be)
|
||||
if(be.getData().getId() !=getData().getId())
|
||||
if(be.getData().getVoltage()!=0)
|
||||
if(be.hasElectricitySlot(direction)){
|
||||
powerGeneration = Math.max(powerGeneration,be.getOutputPower());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return powerGeneration;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int frequencyGeneration() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void updateNextTick() {
|
||||
data.updateNextTick = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateNetwork() {
|
||||
getOrCreateElectricNetwork().updateNetwork();
|
||||
if(!level.isClientSide)
|
||||
TFMGPackets.getChannel().send(PacketDistributor.ALL.noArg(), new NetworkUpdatePacket(BlockPos.of(getPos())));
|
||||
sendData();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendStuff() {
|
||||
sendData();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVoltage(int newVoltage) {
|
||||
if(canBeInGroups()){
|
||||
data.voltage = (int) (((float)resistance()/data.group.resistance)*(float)data.voltageSupply);
|
||||
return;
|
||||
}
|
||||
data.voltage = newVoltage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFrequency(int newFrequency) {
|
||||
data.frequency = newFrequency;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNetworkResistance(int newUsage) {
|
||||
data.networkResistance = newUsage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNetworkResistance() {
|
||||
return data.networkResistance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setWattage(int newWattage) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPowerPercentage(int percentage) {
|
||||
powerPercentage = percentage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNetwork(long network) {
|
||||
this.data.electricalNetworkId = network;
|
||||
if(network!=getPos())
|
||||
ElectricNetworkManager.networks.get(getLevel())
|
||||
.remove(getPos());
|
||||
}
|
||||
|
||||
public boolean networkUndersupplied(){
|
||||
return getNetworkPowerUsage()>data.networkPowerGeneration;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public long getPos() {
|
||||
return getBlockPos().asLong();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
super.remove();
|
||||
this.data.destroyed = true;
|
||||
for(Direction d : Direction.values()) {
|
||||
if(hasElectricitySlot(d))
|
||||
if(getLevelAccessor().getBlockEntity(BlockPos.of(getPos()).relative(d)) instanceof IElectric be&&be.hasElectricitySlot(d.getOpposite())) {
|
||||
ElectricNetworkManager.networks.get(getLevel())
|
||||
.remove(be.getPos());
|
||||
be.setNetwork(be.getPos());
|
||||
be.onPlaced();
|
||||
be.updateNextTick();
|
||||
}
|
||||
}
|
||||
if(data.electricalNetworkId != getPos())
|
||||
getOrCreateElectricNetwork().getMembers().remove(this);
|
||||
|
||||
if(data.electricalNetworkId == getPos())
|
||||
ElectricNetworkManager.networks.get(getLevel())
|
||||
.remove(getData().getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
super.tick();
|
||||
|
||||
if(timer == 2){
|
||||
updateNextTick();
|
||||
}
|
||||
if(timer<=2){
|
||||
timer++;
|
||||
}
|
||||
|
||||
|
||||
if(data.connectNextTick) {
|
||||
onPlaced();
|
||||
data.connectNextTick = false;
|
||||
}
|
||||
if(data.updateNextTick) {
|
||||
updateNetwork();
|
||||
data.updateNextTick = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void write(CompoundTag tag, boolean clientPacket) {
|
||||
super.write(tag, clientPacket);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void read(CompoundTag tag, boolean clientPacket) {
|
||||
super.read(tag, clientPacket);
|
||||
if(!clientPacket)
|
||||
data.connectNextTick = true;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSpeedChanged(float previousSpeed) {
|
||||
super.onSpeedChanged(previousSpeed);
|
||||
updateNextTick();
|
||||
timer = 0;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.drmangotea.tfmg.content.electricity.base;
|
||||
|
||||
|
||||
import com.drmangotea.tfmg.content.electricity.utilities.diode.ElectricDiodeBlockEntity;
|
||||
import com.simibubi.create.foundation.blockEntity.SmartBlockEntity;
|
||||
import com.simibubi.create.foundation.networking.BlockEntityDataPacket;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
|
||||
public class NetworkUpdatePacket extends BlockEntityDataPacket<SmartBlockEntity> {
|
||||
|
||||
|
||||
|
||||
|
||||
public NetworkUpdatePacket(BlockPos pos) {
|
||||
super(pos);
|
||||
|
||||
|
||||
}
|
||||
|
||||
public NetworkUpdatePacket(FriendlyByteBuf buffer) {
|
||||
super(buffer);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void writeData(FriendlyByteBuf buffer) {}
|
||||
|
||||
@Override
|
||||
protected void handlePacket(SmartBlockEntity blockEntity) {
|
||||
|
||||
if(blockEntity instanceof IElectric be) {
|
||||
be.updateNetwork();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user