Use separate blocks for ticking/non-ticking containers

This commit is contained in:
Shadowfacts 2018-12-27 21:44:50 -05:00
parent 42413ebfae
commit 6d0a8f22bf
Signed by: shadowfacts
GPG Key ID: 94A5AB95422746E5
8 changed files with 110 additions and 67 deletions

View File

@ -31,12 +31,14 @@ public class SimpleMultipart implements ModInitializer {
public static final LootContextType MULTIPART_LOOT_CONTEXT = createMultipartLootContextType();
public static final ContainerBlock containerBlock = new ContainerBlock();
public static final TickableContainerBlock tickableContainerBlock = new TickableContainerBlock();
public static final BlockEntityType<ContainerBlockEntity> containerBlockEntity = createBlockEntityType("container", ContainerBlockEntity::new);
public static final BlockEntityType<TickableContainerBlockEntity> tickableContainerBlockEntity = createBlockEntityType("tickable_container", TickableContainerBlockEntity::new);
@Override
public void onInitialize() {
Registry.register(Registry.BLOCK, new Identifier(MODID, "container"), containerBlock);
Registry.register(Registry.BLOCK, new Identifier(MODID, "tickable_container"), tickableContainerBlock);
ContainerEventHandler.register();
}

View File

@ -0,0 +1,75 @@
package net.shadowfacts.simplemultipart.container;
import net.fabricmc.fabric.block.FabricBlockSettings;
import net.minecraft.block.*;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.Hand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.util.shape.VoxelShapes;
import net.minecraft.world.BlockView;
import net.minecraft.world.ExtendedBlockView;
import net.minecraft.world.World;
import net.shadowfacts.simplemultipart.api.MultipartContainer;
import net.shadowfacts.simplemultipart.client.util.RenderStateProvider;
import net.shadowfacts.simplemultipart.util.MultipartHelper;
import net.shadowfacts.simplemultipart.util.MultipartHitResult;
import net.shadowfacts.simplemultipart.api.MultipartView;
import java.util.Set;
/**
* @author shadowfacts
*/
public abstract class AbstractContainerBlock extends Block implements BlockEntityProvider, RenderStateProvider {
public AbstractContainerBlock() {
super(FabricBlockSettings.of(Material.STONE).build());
}
@Override
public boolean activate(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, Direction side, float hitX, float hitY, float hitZ) {
MultipartContainer container = (MultipartContainer)world.getBlockEntity(pos);
if (container == null) {
return false;
}
MultipartHitResult hit = MultipartHelper.rayTrace(container, world, pos, player);
if (hit == null) {
return false;
}
return hit.view.getState().activate(hit.view, player, hand);
}
@Override
public BlockState getStateForRendering(BlockState state, BlockPos pos, ExtendedBlockView world) {
MultipartContainer container = (MultipartContainer)world.getBlockEntity(pos);
if (container == null) {
return state;
}
Set<MultipartView> parts = container.getParts();
return new ContainerBlockState(state, parts);
}
@Override
@Deprecated
public VoxelShape getBoundingShape(BlockState state, BlockView world, BlockPos pos) {
MultipartContainer container = (MultipartContainer)world.getBlockEntity(pos);
if (container == null) {
return VoxelShapes.empty();
}
VoxelShape shape = null;
for (MultipartView view : container.getParts()) {
VoxelShape partShape = view.getState().getBoundingShape(view);
shape = shape == null ? partShape : VoxelShapes.union(shape, partShape);
}
return shape == null ? VoxelShapes.empty() : shape;
}
@Override
public abstract AbstractContainerBlockEntity createBlockEntity(BlockView world);
}

View File

@ -118,11 +118,13 @@ public abstract class AbstractContainerBlockEntity extends BlockEntity implement
boolean hasTickableParts = parts.stream().anyMatch(e -> e.getEntity() != null && e.getEntity() instanceof Tickable);
boolean currentlyTickable = this instanceof Tickable;
if (hasTickableParts != currentlyTickable) {
AbstractContainerBlockEntity newContainer = hasTickableParts ? new TickableContainerBlockEntity() : new ContainerBlockEntity();
world.setBlockEntity(pos, newContainer);
Block newBlock = hasTickableParts ? SimpleMultipart.tickableContainerBlock : SimpleMultipart.containerBlock;
world.setBlockState(pos, newBlock.getDefaultState(), 3);
AbstractContainerBlockEntity newContainer = (AbstractContainerBlockEntity)world.getBlockEntity(pos);
newContainer.parts = parts.stream()
.map(e -> new Entry(newContainer, e.state, e.entity))
.collect(Collectors.toSet());
newContainer.parts.stream().filter(e -> e.entity != null).forEach(e -> e.entity.container = newContainer);
}
world.markDirty(pos, world.getBlockEntity(pos));

View File

@ -1,77 +1,15 @@
package net.shadowfacts.simplemultipart.container;
import net.fabricmc.fabric.block.FabricBlockSettings;
import net.minecraft.block.*;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.Hand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.util.shape.VoxelShapes;
import net.minecraft.world.BlockView;
import net.minecraft.world.ExtendedBlockView;
import net.minecraft.world.World;
import net.shadowfacts.simplemultipart.api.MultipartContainer;
import net.shadowfacts.simplemultipart.client.util.RenderStateProvider;
import net.shadowfacts.simplemultipart.util.MultipartHelper;
import net.shadowfacts.simplemultipart.util.MultipartHitResult;
import net.shadowfacts.simplemultipart.api.MultipartView;
import java.util.Set;
/**
* @author shadowfacts
*/
public class ContainerBlock extends Block implements BlockEntityProvider, RenderStateProvider {
public ContainerBlock() {
super(FabricBlockSettings.of(Material.STONE).build());
}
@Override
public boolean activate(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, Direction side, float hitX, float hitY, float hitZ) {
MultipartContainer container = (MultipartContainer)world.getBlockEntity(pos);
if (container == null) {
return false;
}
MultipartHitResult hit = MultipartHelper.rayTrace(container, world, pos, player);
if (hit == null) {
return false;
}
return hit.view.getState().activate(hit.view, player, hand);
}
@Override
public BlockState getStateForRendering(BlockState state, BlockPos pos, ExtendedBlockView world) {
MultipartContainer container = (MultipartContainer)world.getBlockEntity(pos);
if (container == null) {
return state;
}
Set<MultipartView> parts = container.getParts();
return new ContainerBlockState(state, parts);
}
@Override
@Deprecated
public VoxelShape getBoundingShape(BlockState state, BlockView world, BlockPos pos) {
MultipartContainer container = (MultipartContainer)world.getBlockEntity(pos);
if (container == null) {
return VoxelShapes.empty();
}
VoxelShape shape = null;
for (MultipartView view : container.getParts()) {
VoxelShape partShape = view.getState().getBoundingShape(view);
shape = shape == null ? partShape : VoxelShapes.union(shape, partShape);
}
return shape == null ? VoxelShapes.empty() : shape;
}
public class ContainerBlock extends AbstractContainerBlock {
@Override
public AbstractContainerBlockEntity createBlockEntity(BlockView world) {
return new ContainerBlockEntity();
}
}

View File

@ -23,7 +23,12 @@ public class ContainerEventHandler {
}
private static ActionResult handleBlockAttack(PlayerEntity player, World world, Hand hand, BlockPos pos, Direction direction) {
if (world.isClient || world.getBlockState(pos).getBlock() != SimpleMultipart.containerBlock) {
if (world.isClient) {
return ActionResult.PASS;
}
Block block = world.getBlockState(pos).getBlock();
if (block != SimpleMultipart.containerBlock && block != SimpleMultipart.tickableContainerBlock) {
return ActionResult.PASS;
}

View File

@ -0,0 +1,15 @@
package net.shadowfacts.simplemultipart.container;
import net.minecraft.world.BlockView;
/**
* @author shadowfacts
*/
public class TickableContainerBlock extends AbstractContainerBlock {
@Override
public AbstractContainerBlockEntity createBlockEntity(BlockView world) {
return new TickableContainerBlockEntity();
}
}

View File

@ -28,6 +28,7 @@ public abstract class MixinModelLoader {
@Inject(method = "<init>", at = @At("RETURN"))
public void addMultipartModel(ResourceManager manager, SpriteAtlasTexture texture, CallbackInfo info) {
bakedModels.put(new ModelIdentifier("simplemultipart:container#"), new MultipartContainerBakedModel());
bakedModels.put(new ModelIdentifier("simplemultipart:tickable_container#"), new MultipartContainerBakedModel());
}
}

View File

@ -0,0 +1,5 @@
{
"variants": {
"": { "model": "block/air" }
}
}