Curses
- Added the Peculiar Bell and the Cursed Bell
|
@ -0,0 +1,19 @@
|
||||||
|
{
|
||||||
|
"type": "minecraft:block",
|
||||||
|
"pools": [
|
||||||
|
{
|
||||||
|
"rolls": 1,
|
||||||
|
"entries": [
|
||||||
|
{
|
||||||
|
"type": "minecraft:item",
|
||||||
|
"name": "create:cursed_bell"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"conditions": [
|
||||||
|
{
|
||||||
|
"condition": "minecraft:survives_explosion"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
{
|
||||||
|
"type": "minecraft:block",
|
||||||
|
"pools": [
|
||||||
|
{
|
||||||
|
"rolls": 1,
|
||||||
|
"entries": [
|
||||||
|
{
|
||||||
|
"type": "minecraft:item",
|
||||||
|
"name": "create:peculiar_bell"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"conditions": [
|
||||||
|
{
|
||||||
|
"condition": "minecraft:survives_explosion"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -24,6 +24,8 @@
|
||||||
"create:pulley_magnet",
|
"create:pulley_magnet",
|
||||||
"create:furnace_engine",
|
"create:furnace_engine",
|
||||||
"create:redstone_link",
|
"create:redstone_link",
|
||||||
|
"create:peculiar_bell",
|
||||||
|
"create:cursed_bell",
|
||||||
"#minecraft:doors",
|
"#minecraft:doors",
|
||||||
"#minecraft:beds",
|
"#minecraft:beds",
|
||||||
"minecraft:flower_pot",
|
"minecraft:flower_pot",
|
||||||
|
|
|
@ -114,7 +114,8 @@ import com.simibubi.create.content.contraptions.relays.gauge.GaugeBlock;
|
||||||
import com.simibubi.create.content.contraptions.relays.gauge.GaugeGenerator;
|
import com.simibubi.create.content.contraptions.relays.gauge.GaugeGenerator;
|
||||||
import com.simibubi.create.content.contraptions.relays.gearbox.GearboxBlock;
|
import com.simibubi.create.content.contraptions.relays.gearbox.GearboxBlock;
|
||||||
import com.simibubi.create.content.curiosities.armor.CopperBacktankBlock;
|
import com.simibubi.create.content.curiosities.armor.CopperBacktankBlock;
|
||||||
import com.simibubi.create.content.curiosities.projector.ChromaticProjectorBlock;
|
import com.simibubi.create.content.curiosities.bell.CursedBellBlock;
|
||||||
|
import com.simibubi.create.content.curiosities.bell.PeculiarBellBlock;
|
||||||
import com.simibubi.create.content.logistics.block.belts.tunnel.BeltTunnelBlock;
|
import com.simibubi.create.content.logistics.block.belts.tunnel.BeltTunnelBlock;
|
||||||
import com.simibubi.create.content.logistics.block.belts.tunnel.BrassTunnelBlock;
|
import com.simibubi.create.content.logistics.block.belts.tunnel.BrassTunnelBlock;
|
||||||
import com.simibubi.create.content.logistics.block.belts.tunnel.BrassTunnelCTBehaviour;
|
import com.simibubi.create.content.logistics.block.belts.tunnel.BrassTunnelCTBehaviour;
|
||||||
|
@ -1301,6 +1302,22 @@ public class AllBlocks {
|
||||||
})
|
})
|
||||||
.register();
|
.register();
|
||||||
|
|
||||||
|
public static final BlockEntry<PeculiarBellBlock> PECULIAR_BELL =
|
||||||
|
REGISTRATE.block("peculiar_bell", PeculiarBellBlock::new)
|
||||||
|
.initialProperties(SharedProperties::softMetal)
|
||||||
|
.tag(AllBlockTags.BRITTLE.tag)
|
||||||
|
.item()
|
||||||
|
.build()
|
||||||
|
.register();
|
||||||
|
|
||||||
|
public static final BlockEntry<CursedBellBlock> CURSED_BELL =
|
||||||
|
REGISTRATE.block("cursed_bell", CursedBellBlock::new)
|
||||||
|
.initialProperties(() -> PECULIAR_BELL.get())
|
||||||
|
.tag(AllBlockTags.BRITTLE.tag)
|
||||||
|
.item()
|
||||||
|
.build()
|
||||||
|
.register();
|
||||||
|
|
||||||
// Materials
|
// Materials
|
||||||
|
|
||||||
static {
|
static {
|
||||||
|
|
|
@ -9,6 +9,8 @@ import com.simibubi.create.content.contraptions.particle.CubeParticleData;
|
||||||
import com.simibubi.create.content.contraptions.particle.HeaterParticleData;
|
import com.simibubi.create.content.contraptions.particle.HeaterParticleData;
|
||||||
import com.simibubi.create.content.contraptions.particle.ICustomParticleData;
|
import com.simibubi.create.content.contraptions.particle.ICustomParticleData;
|
||||||
import com.simibubi.create.content.contraptions.particle.RotationIndicatorParticleData;
|
import com.simibubi.create.content.contraptions.particle.RotationIndicatorParticleData;
|
||||||
|
import com.simibubi.create.content.curiosities.bell.SoulBaseParticle;
|
||||||
|
import com.simibubi.create.content.curiosities.bell.SoulParticle;
|
||||||
import com.simibubi.create.foundation.utility.Lang;
|
import com.simibubi.create.foundation.utility.Lang;
|
||||||
|
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
|
@ -31,8 +33,9 @@ public enum AllParticleTypes {
|
||||||
CUBE(CubeParticleData::new),
|
CUBE(CubeParticleData::new),
|
||||||
FLUID_PARTICLE(FluidParticleData::new),
|
FLUID_PARTICLE(FluidParticleData::new),
|
||||||
BASIN_FLUID(FluidParticleData::new),
|
BASIN_FLUID(FluidParticleData::new),
|
||||||
FLUID_DRIP(FluidParticleData::new)
|
FLUID_DRIP(FluidParticleData::new),
|
||||||
|
SOUL(SoulParticle.Data::new),
|
||||||
|
SOUL_BASE(SoulBaseParticle.Data::new)
|
||||||
;
|
;
|
||||||
|
|
||||||
private ParticleEntry<?> entry;
|
private ParticleEntry<?> entry;
|
||||||
|
|
|
@ -119,6 +119,8 @@ import com.simibubi.create.content.contraptions.relays.gearbox.GearshiftTileEnti
|
||||||
import com.simibubi.create.content.curiosities.armor.CopperBacktankInstance;
|
import com.simibubi.create.content.curiosities.armor.CopperBacktankInstance;
|
||||||
import com.simibubi.create.content.curiosities.armor.CopperBacktankRenderer;
|
import com.simibubi.create.content.curiosities.armor.CopperBacktankRenderer;
|
||||||
import com.simibubi.create.content.curiosities.armor.CopperBacktankTileEntity;
|
import com.simibubi.create.content.curiosities.armor.CopperBacktankTileEntity;
|
||||||
|
import com.simibubi.create.content.curiosities.bell.CursedBellTileEntity;
|
||||||
|
import com.simibubi.create.content.curiosities.bell.PeculiarBellTileEntity;
|
||||||
import com.simibubi.create.content.curiosities.projector.ChromaticProjectorInstance;
|
import com.simibubi.create.content.curiosities.projector.ChromaticProjectorInstance;
|
||||||
import com.simibubi.create.content.curiosities.projector.ChromaticProjectorTileEntity;
|
import com.simibubi.create.content.curiosities.projector.ChromaticProjectorTileEntity;
|
||||||
import com.simibubi.create.content.logistics.block.belts.tunnel.BeltTunnelInstance;
|
import com.simibubi.create.content.logistics.block.belts.tunnel.BeltTunnelInstance;
|
||||||
|
@ -658,6 +660,7 @@ public class AllTileEntities {
|
||||||
.validBlocks(AllBlocks.ADJUSTABLE_PULSE_REPEATER)
|
.validBlocks(AllBlocks.ADJUSTABLE_PULSE_REPEATER)
|
||||||
.renderer(() -> AdjustableRepeaterRenderer::new)
|
.renderer(() -> AdjustableRepeaterRenderer::new)
|
||||||
.register();
|
.register();
|
||||||
|
|
||||||
public static final TileEntityEntry<CopperBacktankTileEntity> COPPER_BACKTANK = Create.registrate()
|
public static final TileEntityEntry<CopperBacktankTileEntity> COPPER_BACKTANK = Create.registrate()
|
||||||
.tileEntity("copper_backtank", CopperBacktankTileEntity::new)
|
.tileEntity("copper_backtank", CopperBacktankTileEntity::new)
|
||||||
.instance(() -> CopperBacktankInstance::new)
|
.instance(() -> CopperBacktankInstance::new)
|
||||||
|
@ -665,5 +668,15 @@ public class AllTileEntities {
|
||||||
.renderer(() -> CopperBacktankRenderer::new)
|
.renderer(() -> CopperBacktankRenderer::new)
|
||||||
.register();
|
.register();
|
||||||
|
|
||||||
|
public static final TileEntityEntry<PeculiarBellTileEntity> PECULIAR_BELL = Create.registrate()
|
||||||
|
.tileEntity("peculiar_bell", PeculiarBellTileEntity::new)
|
||||||
|
.validBlocks(AllBlocks.PECULIAR_BELL)
|
||||||
|
.register();
|
||||||
|
|
||||||
|
public static final TileEntityEntry<CursedBellTileEntity> CURSED_BELL = Create.registrate()
|
||||||
|
.tileEntity("cursed_bell", CursedBellTileEntity::new)
|
||||||
|
.validBlocks(AllBlocks.CURSED_BELL)
|
||||||
|
.register();
|
||||||
|
|
||||||
public static void register() {}
|
public static void register() {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,70 @@
|
||||||
|
package com.simibubi.create.content.curiosities.bell;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.simibubi.create.foundation.block.ITE;
|
||||||
|
|
||||||
|
import net.minecraft.block.BellBlock;
|
||||||
|
import net.minecraft.block.BlockState;
|
||||||
|
import net.minecraft.tileentity.TileEntity;
|
||||||
|
import net.minecraft.util.Direction;
|
||||||
|
import net.minecraft.util.SoundCategory;
|
||||||
|
import net.minecraft.util.SoundEvents;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.util.math.shapes.ISelectionContext;
|
||||||
|
import net.minecraft.util.math.shapes.VoxelShape;
|
||||||
|
import net.minecraft.util.math.shapes.VoxelShapes;
|
||||||
|
import net.minecraft.world.IBlockReader;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
|
public abstract class AbstractBellBlock<TE extends AbstractBellTileEntity> extends BellBlock implements ITE<TE> {
|
||||||
|
|
||||||
|
public AbstractBellBlock(Properties properties) {
|
||||||
|
super(properties);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Nullable
|
||||||
|
public TileEntity createNewTileEntity(IBlockReader block) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected VoxelShape getShape(BlockState state) {
|
||||||
|
return VoxelShapes.fullCube();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public VoxelShape getCollisionShape(BlockState state, IBlockReader reader, BlockPos pos, ISelectionContext selection) {
|
||||||
|
return this.getShape(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public VoxelShape getShape(BlockState state, IBlockReader reader, BlockPos pos, ISelectionContext selection) {
|
||||||
|
return this.getShape(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean ring(World world, BlockPos pos, @Nullable Direction direction) {
|
||||||
|
if (direction == null) {
|
||||||
|
direction = world.getBlockState(pos).get(field_220133_a);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ringInner(world, pos, direction))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (world.isRemote)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
playSound(world, pos, direction);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void playSound(World world, BlockPos pos, Direction direction) {
|
||||||
|
world.playSound(null, pos, SoundEvents.BLOCK_BELL_USE, SoundCategory.BLOCKS, 2.0F, 1.0F);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean ringInner(World world, BlockPos pos, Direction direction) {
|
||||||
|
TE te = getTileEntity(world, pos);
|
||||||
|
return te != null && te.ring(world, pos, direction);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
package com.simibubi.create.content.curiosities.bell;
|
||||||
|
|
||||||
|
import com.simibubi.create.foundation.tileEntity.SmartTileEntity;
|
||||||
|
|
||||||
|
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
|
||||||
|
|
||||||
|
import net.minecraft.tileentity.TileEntityType;
|
||||||
|
import net.minecraft.util.Direction;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public abstract class AbstractBellTileEntity extends SmartTileEntity {
|
||||||
|
|
||||||
|
public AbstractBellTileEntity(TileEntityType<?> type) {
|
||||||
|
super(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addBehaviours(List<TileEntityBehaviour> behaviours) { }
|
||||||
|
|
||||||
|
public abstract boolean ring(World world, BlockPos pos, Direction direction);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
package com.simibubi.create.content.curiosities.bell;
|
||||||
|
|
||||||
|
import com.simibubi.create.AllTileEntities;
|
||||||
|
|
||||||
|
import com.simibubi.create.foundation.block.ITE;
|
||||||
|
|
||||||
|
import net.minecraft.block.BlockState;
|
||||||
|
import net.minecraft.tileentity.TileEntity;
|
||||||
|
import net.minecraft.util.Direction;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.world.IBlockReader;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
|
public class CursedBellBlock extends AbstractBellBlock<CursedBellTileEntity> {
|
||||||
|
|
||||||
|
public CursedBellBlock(Properties properties) {
|
||||||
|
super(properties);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TileEntity createTileEntity(BlockState state, IBlockReader world) {
|
||||||
|
return AllTileEntities.CURSED_BELL.create();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<CursedBellTileEntity> getTileEntityClass() {
|
||||||
|
return CursedBellTileEntity.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,177 @@
|
||||||
|
package com.simibubi.create.content.curiosities.bell;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
|
||||||
|
import com.simibubi.create.foundation.utility.NBTHelper;
|
||||||
|
|
||||||
|
import net.minecraft.block.BlockState;
|
||||||
|
import net.minecraft.entity.EntitySpawnPlacementRegistry;
|
||||||
|
import net.minecraft.entity.EntityType;
|
||||||
|
import net.minecraft.nbt.CompoundNBT;
|
||||||
|
import net.minecraft.tileentity.TileEntityType;
|
||||||
|
import net.minecraft.util.Direction;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.util.math.vector.Vector3d;
|
||||||
|
import net.minecraft.world.LightType;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
import net.minecraft.world.spawner.WorldEntitySpawner;
|
||||||
|
|
||||||
|
public class CursedBellTileEntity extends AbstractBellTileEntity {
|
||||||
|
|
||||||
|
public static final int MAX_DISTANCE = 6;
|
||||||
|
private static final List<List<BlockPos>> LAYERS = genLayers();
|
||||||
|
|
||||||
|
public enum Mode {
|
||||||
|
RUNNING, RECHARGING
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final int RECHARGE_TICKS = 16;
|
||||||
|
public static final int TICKS_PER_LAYER = 3;
|
||||||
|
public int ticks;
|
||||||
|
public Mode mode = Mode.RECHARGING;
|
||||||
|
|
||||||
|
public CursedBellTileEntity(TileEntityType<?> type) {
|
||||||
|
super(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addBehaviours(List<TileEntityBehaviour> behaviours) { }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void fromTag(BlockState state, CompoundNBT compound, boolean clientPacket) {
|
||||||
|
ticks = compound.getInt("Ticks");
|
||||||
|
mode = NBTHelper.readEnum(compound, "Mode", Mode.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(CompoundNBT compound, boolean clientPacket) {
|
||||||
|
compound.putInt("Ticks", ticks);
|
||||||
|
NBTHelper.writeEnum(compound, "Mode", mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void tick() {
|
||||||
|
super.tick();
|
||||||
|
|
||||||
|
switch (mode) {
|
||||||
|
case RECHARGING:
|
||||||
|
if (ticks > 0)
|
||||||
|
ticks--;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RUNNING:
|
||||||
|
if (ticks <= 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
ticks--;
|
||||||
|
if (ticks % TICKS_PER_LAYER == 0) {
|
||||||
|
while (!trySpawnSouls(world, pos, MAX_DISTANCE - ticks / TICKS_PER_LAYER - 1)
|
||||||
|
&& ticks > 0) {
|
||||||
|
ticks -= TICKS_PER_LAYER;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ticks == 0) {
|
||||||
|
ticks = RECHARGE_TICKS;
|
||||||
|
mode = Mode.RECHARGING;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean tryStart() {
|
||||||
|
if (mode != Mode.RECHARGING || ticks > 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
ticks = TICKS_PER_LAYER*MAX_DISTANCE;
|
||||||
|
mode = Mode.RUNNING;
|
||||||
|
if (!world.isRemote)
|
||||||
|
sendData();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean ring(World world, BlockPos pos, Direction direction) {
|
||||||
|
return tryStart();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean trySpawnSouls(World world, BlockPos at, int layerIdx) {
|
||||||
|
if (world == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
boolean spawnedAny = false;
|
||||||
|
List<BlockPos> layer = LAYERS.get(layerIdx);
|
||||||
|
for (BlockPos candidate : layer) {
|
||||||
|
candidate = candidate.add(at);
|
||||||
|
|
||||||
|
if (!WorldEntitySpawner.canCreatureTypeSpawnAtLocation(
|
||||||
|
EntitySpawnPlacementRegistry.PlacementType.ON_GROUND,
|
||||||
|
world, candidate, EntityType.ZOMBIE))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (world.getLightLevel(LightType.BLOCK, candidate) >= 8)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!world.isRemote)
|
||||||
|
return true;
|
||||||
|
spawnedAny = true;
|
||||||
|
spawnParticles(world, candidate);
|
||||||
|
}
|
||||||
|
return spawnedAny;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void spawnParticles(World world, BlockPos at) {
|
||||||
|
if (world == null || !world.isRemote)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Vector3d p = Vector3d.of(at);
|
||||||
|
world.addParticle(new SoulParticle.Data(), p.x + 0.5, p.y + 0.5, p.z + 0.5, 0, 0, 0);
|
||||||
|
world.addParticle(new SoulBaseParticle.Data(), p.x + 0.5, p.y + 0.01, p.z + 0.5, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<List<BlockPos>> genLayers() {
|
||||||
|
List<List<BlockPos>> layers = new ArrayList<>();
|
||||||
|
for (int i = 0; i < MAX_DISTANCE; i++)
|
||||||
|
layers.add(new ArrayList<>());
|
||||||
|
|
||||||
|
for (int x = 0; x < MAX_DISTANCE; x++) {
|
||||||
|
for (int y = 0; y < MAX_DISTANCE; y++) {
|
||||||
|
for (int z = 0; z < MAX_DISTANCE; z++) {
|
||||||
|
BlockPos candidate = new BlockPos(x,y,z);
|
||||||
|
int dist = 1 + (int)Math.sqrt(candidate.distanceSq(0,0,0,false));
|
||||||
|
if (dist == 0 || dist > MAX_DISTANCE)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
List<BlockPos> layer = layers.get(dist - 1);
|
||||||
|
int start = layer.size(), end = start + 1;
|
||||||
|
layer.add(candidate);
|
||||||
|
|
||||||
|
if (candidate.getX() != 0) {
|
||||||
|
layer.add(new BlockPos(-candidate.getX(), candidate.getY(), candidate.getZ()));
|
||||||
|
end += 1;
|
||||||
|
}
|
||||||
|
if (candidate.getY() != 0) {
|
||||||
|
for (int i = start; i < end; i++) {
|
||||||
|
BlockPos prev = layer.get(i);
|
||||||
|
layer.add(new BlockPos(prev.getX(), -prev.getY(), prev.getZ()));
|
||||||
|
}
|
||||||
|
end += end - start;
|
||||||
|
}
|
||||||
|
if (candidate.getZ() != 0) {
|
||||||
|
for (int i = start; i < end; i++) {
|
||||||
|
BlockPos prev = layer.get(i);
|
||||||
|
layer.add(new BlockPos(prev.getX(), prev.getY(), -prev.getZ()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return layers;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
package com.simibubi.create.content.curiosities.bell;
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.vertex.IVertexBuilder;
|
||||||
|
|
||||||
|
import net.minecraft.client.particle.IAnimatedSprite;
|
||||||
|
import net.minecraft.client.particle.SimpleAnimatedParticle;
|
||||||
|
import net.minecraft.client.renderer.ActiveRenderInfo;
|
||||||
|
import net.minecraft.client.world.ClientWorld;
|
||||||
|
import net.minecraft.util.math.MathHelper;
|
||||||
|
import net.minecraft.util.math.vector.Quaternion;
|
||||||
|
import net.minecraft.util.math.vector.Vector3d;
|
||||||
|
import net.minecraft.util.math.vector.Vector3f;
|
||||||
|
|
||||||
|
public class CustomRotationParticle extends SimpleAnimatedParticle {
|
||||||
|
|
||||||
|
public CustomRotationParticle(ClientWorld worldIn, double x, double y, double z, IAnimatedSprite spriteSet, float yAccel) {
|
||||||
|
super(worldIn, x, y, z, spriteSet, yAccel);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Quaternion getCustomRotation(ActiveRenderInfo camera, float partialTicks) {
|
||||||
|
Quaternion quaternion = new Quaternion(camera.getRotation());
|
||||||
|
if (this.particleAngle != 0.0F) {
|
||||||
|
float angle = MathHelper.lerp(partialTicks, this.prevParticleAngle, this.particleAngle);
|
||||||
|
quaternion.multiply(Vector3f.POSITIVE_Z.getRadialQuaternion(angle));
|
||||||
|
}
|
||||||
|
return quaternion;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void buildGeometry(IVertexBuilder builder, ActiveRenderInfo camera, float partialTicks) {
|
||||||
|
Vector3d cameraPos = camera.getProjectedView();
|
||||||
|
float originX = (float)(MathHelper.lerp(partialTicks, this.prevPosX, this.posX) - cameraPos.getX());
|
||||||
|
float originY = (float)(MathHelper.lerp(partialTicks, this.prevPosY, this.posY) - cameraPos.getY());
|
||||||
|
float originZ = (float)(MathHelper.lerp(partialTicks, this.prevPosZ, this.posZ) - cameraPos.getZ());
|
||||||
|
|
||||||
|
Vector3f[] vertices = new Vector3f[]{new Vector3f(-1.0F, -1.0F, 0.0F), new Vector3f(-1.0F, 1.0F, 0.0F), new Vector3f(1.0F, 1.0F, 0.0F), new Vector3f(1.0F, -1.0F, 0.0F)};
|
||||||
|
float scale = this.getScale(partialTicks);
|
||||||
|
|
||||||
|
Quaternion rotation = getCustomRotation(camera, partialTicks);
|
||||||
|
for(int i = 0; i < 4; ++i) {
|
||||||
|
Vector3f vertex = vertices[i];
|
||||||
|
vertex.func_214905_a(rotation);
|
||||||
|
vertex.mul(scale);
|
||||||
|
vertex.add(originX, originY, originZ);
|
||||||
|
}
|
||||||
|
|
||||||
|
float minU = this.getMinU();
|
||||||
|
float maxU = this.getMaxU();
|
||||||
|
float minV = this.getMinV();
|
||||||
|
float maxV = this.getMaxV();
|
||||||
|
int brightness = this.getBrightnessForRender(partialTicks);
|
||||||
|
builder.vertex(vertices[0].getX(), vertices[0].getY(), vertices[0].getZ()).texture(maxU, maxV).color(this.particleRed, this.particleGreen, this.particleBlue, this.particleAlpha).light(brightness).endVertex();
|
||||||
|
builder.vertex(vertices[1].getX(), vertices[1].getY(), vertices[1].getZ()).texture(maxU, minV).color(this.particleRed, this.particleGreen, this.particleBlue, this.particleAlpha).light(brightness).endVertex();
|
||||||
|
builder.vertex(vertices[2].getX(), vertices[2].getY(), vertices[2].getZ()).texture(minU, minV).color(this.particleRed, this.particleGreen, this.particleBlue, this.particleAlpha).light(brightness).endVertex();
|
||||||
|
builder.vertex(vertices[3].getX(), vertices[3].getY(), vertices[3].getZ()).texture(minU, maxV).color(this.particleRed, this.particleGreen, this.particleBlue, this.particleAlpha).light(brightness).endVertex();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
package com.simibubi.create.content.curiosities.bell;
|
||||||
|
|
||||||
|
import com.simibubi.create.AllTileEntities;
|
||||||
|
import com.simibubi.create.foundation.block.ITE;
|
||||||
|
|
||||||
|
import net.minecraft.block.BlockState;
|
||||||
|
import net.minecraft.tileentity.TileEntity;
|
||||||
|
import net.minecraft.util.Direction;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.util.math.shapes.VoxelShape;
|
||||||
|
import net.minecraft.util.math.shapes.VoxelShapes;
|
||||||
|
import net.minecraft.world.IBlockReader;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
|
public class PeculiarBellBlock extends AbstractBellBlock<PeculiarBellTileEntity> {
|
||||||
|
|
||||||
|
public PeculiarBellBlock(Properties properties) {
|
||||||
|
super(properties);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TileEntity createTileEntity(BlockState state, IBlockReader world) {
|
||||||
|
return AllTileEntities.PECULIAR_BELL.create();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<PeculiarBellTileEntity> getTileEntityClass() { return PeculiarBellTileEntity.class; }
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
package com.simibubi.create.content.curiosities.bell;
|
||||||
|
|
||||||
|
import net.minecraft.tileentity.TileEntityType;
|
||||||
|
import net.minecraft.util.Direction;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
|
public class PeculiarBellTileEntity extends AbstractBellTileEntity {
|
||||||
|
|
||||||
|
public PeculiarBellTileEntity(TileEntityType<?> type) {
|
||||||
|
super(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean ring(World world, BlockPos pos, Direction direction) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
package com.simibubi.create.content.curiosities.bell;
|
||||||
|
|
||||||
|
import com.simibubi.create.AllParticleTypes;
|
||||||
|
import com.simibubi.create.foundation.data.BasicParticleData;
|
||||||
|
|
||||||
|
import net.minecraft.client.particle.IAnimatedSprite;
|
||||||
|
import net.minecraft.client.renderer.ActiveRenderInfo;
|
||||||
|
import net.minecraft.client.world.ClientWorld;
|
||||||
|
import net.minecraft.particles.ParticleType;
|
||||||
|
import net.minecraft.util.math.vector.Quaternion;
|
||||||
|
import net.minecraft.util.math.vector.Vector3f;
|
||||||
|
|
||||||
|
public class SoulBaseParticle extends CustomRotationParticle {
|
||||||
|
|
||||||
|
private final IAnimatedSprite animatedSprite;
|
||||||
|
|
||||||
|
public SoulBaseParticle(ClientWorld worldIn, double x, double y, double z, double vx, double vy, double vz,
|
||||||
|
IAnimatedSprite spriteSet) {
|
||||||
|
super(worldIn, x, y, z, spriteSet, 0);
|
||||||
|
this.animatedSprite = spriteSet;
|
||||||
|
this.particleScale = 0.5f;
|
||||||
|
this.setSize(this.particleScale,this.particleScale);
|
||||||
|
this.maxAge = (int)(16.0F / (this.rand.nextFloat() * 0.36F + 0.64F));
|
||||||
|
this.selectSpriteWithAge(animatedSprite);
|
||||||
|
this.field_21507 = true; // disable movement
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void tick() {
|
||||||
|
if (this.age++ >= this.maxAge) {
|
||||||
|
this.setExpired();
|
||||||
|
} else {
|
||||||
|
this.selectSpriteWithAge(animatedSprite);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Quaternion getCustomRotation(ActiveRenderInfo camera, float partialTicks) {
|
||||||
|
return Vector3f.POSITIVE_X.getDegreesQuaternion(90);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Data extends BasicParticleData<SoulBaseParticle> {
|
||||||
|
@Override
|
||||||
|
public IBasicParticleFactory<SoulBaseParticle> getBasicFactory() {
|
||||||
|
return SoulBaseParticle::new;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public ParticleType<?> getType() {
|
||||||
|
return AllParticleTypes.SOUL_BASE.get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
package com.simibubi.create.content.curiosities.bell;
|
||||||
|
|
||||||
|
import com.simibubi.create.AllParticleTypes;
|
||||||
|
import com.simibubi.create.foundation.data.BasicParticleData;
|
||||||
|
|
||||||
|
import net.minecraft.client.particle.IAnimatedSprite;
|
||||||
|
import net.minecraft.client.renderer.ActiveRenderInfo;
|
||||||
|
import net.minecraft.client.world.ClientWorld;
|
||||||
|
import net.minecraft.particles.ParticleType;
|
||||||
|
import net.minecraft.util.math.vector.Quaternion;
|
||||||
|
|
||||||
|
public class SoulParticle extends CustomRotationParticle {
|
||||||
|
|
||||||
|
private final IAnimatedSprite animatedSprite;
|
||||||
|
|
||||||
|
public SoulParticle(ClientWorld worldIn, double x, double y, double z, double vx, double vy, double vz,
|
||||||
|
IAnimatedSprite spriteSet) {
|
||||||
|
super(worldIn, x, y, z, spriteSet, 0);
|
||||||
|
this.animatedSprite = spriteSet;
|
||||||
|
this.particleScale = 0.5f;
|
||||||
|
this.setSize(this.particleScale,this.particleScale);
|
||||||
|
this.maxAge = (int)(16.0F / (this.rand.nextFloat() * 0.36F + 0.64F));
|
||||||
|
this.selectSpriteWithAge(animatedSprite);
|
||||||
|
this.field_21507 = true; // disable movement
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void tick() {
|
||||||
|
if (this.age++ >= this.maxAge) {
|
||||||
|
this.setExpired();
|
||||||
|
} else {
|
||||||
|
this.selectSpriteWithAge(animatedSprite);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Quaternion getCustomRotation(ActiveRenderInfo camera, float partialTicks) {
|
||||||
|
return new Quaternion(0, -camera.getYaw(), 0, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Data extends BasicParticleData<SoulParticle> {
|
||||||
|
@Override
|
||||||
|
public IBasicParticleFactory<SoulParticle> getBasicFactory() {
|
||||||
|
return SoulParticle::new;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public ParticleType<?> getType() {
|
||||||
|
return AllParticleTypes.SOUL.get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,71 @@
|
||||||
|
package com.simibubi.create.foundation.data;
|
||||||
|
|
||||||
|
import javax.annotation.ParametersAreNonnullByDefault;
|
||||||
|
|
||||||
|
import com.mojang.brigadier.StringReader;
|
||||||
|
import com.mojang.serialization.Codec;
|
||||||
|
import com.simibubi.create.content.contraptions.particle.ICustomParticleDataWithSprite;
|
||||||
|
|
||||||
|
import mcp.MethodsReturnNonnullByDefault;
|
||||||
|
import net.minecraft.client.particle.IAnimatedSprite;
|
||||||
|
import net.minecraft.client.particle.IParticleFactory;
|
||||||
|
import net.minecraft.client.particle.Particle;
|
||||||
|
import net.minecraft.client.particle.ParticleManager;
|
||||||
|
import net.minecraft.client.world.ClientWorld;
|
||||||
|
import net.minecraft.network.PacketBuffer;
|
||||||
|
import net.minecraft.particles.IParticleData;
|
||||||
|
import net.minecraft.particles.ParticleType;
|
||||||
|
import net.minecraft.util.registry.Registry;
|
||||||
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
|
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@ParametersAreNonnullByDefault
|
||||||
|
@MethodsReturnNonnullByDefault
|
||||||
|
public abstract class BasicParticleData<T extends Particle> implements IParticleData, ICustomParticleDataWithSprite<BasicParticleData<T>> {
|
||||||
|
|
||||||
|
public BasicParticleData() { }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IDeserializer<BasicParticleData<T>> getDeserializer() {
|
||||||
|
BasicParticleData<T> data = this;
|
||||||
|
return new IParticleData.IDeserializer<BasicParticleData<T>>() {
|
||||||
|
@Override
|
||||||
|
public BasicParticleData<T> deserialize(ParticleType<BasicParticleData<T>> arg0, StringReader reader) {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public BasicParticleData<T> read(ParticleType<BasicParticleData<T>> type, PacketBuffer buffer) {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Codec<BasicParticleData<T>> getCodec(ParticleType<BasicParticleData<T>> type) {
|
||||||
|
return Codec.unit(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface IBasicParticleFactory<U extends Particle> {
|
||||||
|
U makeParticle(ClientWorld worldIn, double x, double y, double z, double vx, double vy, double vz, IAnimatedSprite sprite);
|
||||||
|
}
|
||||||
|
|
||||||
|
@OnlyIn(Dist.CLIENT)
|
||||||
|
public abstract IBasicParticleFactory<T> getBasicFactory();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@OnlyIn(Dist.CLIENT)
|
||||||
|
public ParticleManager.IParticleMetaFactory<BasicParticleData<T>> getMetaFactory() {
|
||||||
|
return animatedSprite -> (data, worldIn, x, y, z, vx, vy, vz) ->
|
||||||
|
getBasicFactory().makeParticle(worldIn, x, y, z, vx, vy, vz, animatedSprite);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getParameters() {
|
||||||
|
return Registry.PARTICLE_TYPE.getKey(getType()).toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(PacketBuffer buffer) { }
|
||||||
|
}
|
20
src/main/resources/assets/create/particles/soul.json
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
{
|
||||||
|
"textures": [
|
||||||
|
"create:soul_particle_0",
|
||||||
|
"create:soul_particle_1",
|
||||||
|
"create:soul_particle_2",
|
||||||
|
"create:soul_particle_3",
|
||||||
|
"create:soul_particle_4",
|
||||||
|
"create:soul_particle_5",
|
||||||
|
"create:soul_particle_6",
|
||||||
|
"create:soul_particle_7",
|
||||||
|
"create:soul_particle_8",
|
||||||
|
"create:soul_particle_9",
|
||||||
|
"create:soul_particle_10",
|
||||||
|
"create:soul_particle_11",
|
||||||
|
"create:soul_particle_12",
|
||||||
|
"create:soul_particle_13",
|
||||||
|
"create:soul_particle_14",
|
||||||
|
"create:soul_particle_15"
|
||||||
|
]
|
||||||
|
}
|
12
src/main/resources/assets/create/particles/soul_base.json
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
"textures": [
|
||||||
|
"create:soul_base_0",
|
||||||
|
"create:soul_base_1",
|
||||||
|
"create:soul_base_2",
|
||||||
|
"create:soul_base_3",
|
||||||
|
"create:soul_base_4",
|
||||||
|
"create:soul_base_5",
|
||||||
|
"create:soul_base_6",
|
||||||
|
"create:soul_base_7"
|
||||||
|
]
|
||||||
|
}
|
After Width: | Height: | Size: 102 B |
After Width: | Height: | Size: 142 B |
After Width: | Height: | Size: 174 B |
After Width: | Height: | Size: 203 B |
After Width: | Height: | Size: 250 B |
After Width: | Height: | Size: 249 B |
After Width: | Height: | Size: 143 B |
After Width: | Height: | Size: 88 B |
After Width: | Height: | Size: 298 B |
After Width: | Height: | Size: 310 B |
After Width: | Height: | Size: 323 B |
After Width: | Height: | Size: 351 B |
After Width: | Height: | Size: 367 B |
After Width: | Height: | Size: 376 B |
After Width: | Height: | Size: 331 B |
After Width: | Height: | Size: 311 B |
After Width: | Height: | Size: 294 B |
After Width: | Height: | Size: 320 B |
After Width: | Height: | Size: 316 B |
After Width: | Height: | Size: 305 B |
After Width: | Height: | Size: 316 B |
After Width: | Height: | Size: 327 B |
After Width: | Height: | Size: 307 B |
After Width: | Height: | Size: 323 B |