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 LootContextType MULTIPART_LOOT_CONTEXT = createMultipartLootContextType();
public static final ContainerBlock containerBlock = new ContainerBlock(); 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<ContainerBlockEntity> containerBlockEntity = createBlockEntityType("container", ContainerBlockEntity::new);
public static final BlockEntityType<TickableContainerBlockEntity> tickableContainerBlockEntity = createBlockEntityType("tickable_container", TickableContainerBlockEntity::new); public static final BlockEntityType<TickableContainerBlockEntity> tickableContainerBlockEntity = createBlockEntityType("tickable_container", TickableContainerBlockEntity::new);
@Override @Override
public void onInitialize() { public void onInitialize() {
Registry.register(Registry.BLOCK, new Identifier(MODID, "container"), containerBlock); Registry.register(Registry.BLOCK, new Identifier(MODID, "container"), containerBlock);
Registry.register(Registry.BLOCK, new Identifier(MODID, "tickable_container"), tickableContainerBlock);
ContainerEventHandler.register(); 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 hasTickableParts = parts.stream().anyMatch(e -> e.getEntity() != null && e.getEntity() instanceof Tickable);
boolean currentlyTickable = this instanceof Tickable; boolean currentlyTickable = this instanceof Tickable;
if (hasTickableParts != currentlyTickable) { if (hasTickableParts != currentlyTickable) {
AbstractContainerBlockEntity newContainer = hasTickableParts ? new TickableContainerBlockEntity() : new ContainerBlockEntity(); Block newBlock = hasTickableParts ? SimpleMultipart.tickableContainerBlock : SimpleMultipart.containerBlock;
world.setBlockEntity(pos, newContainer); world.setBlockState(pos, newBlock.getDefaultState(), 3);
AbstractContainerBlockEntity newContainer = (AbstractContainerBlockEntity)world.getBlockEntity(pos);
newContainer.parts = parts.stream() newContainer.parts = parts.stream()
.map(e -> new Entry(newContainer, e.state, e.entity)) .map(e -> new Entry(newContainer, e.state, e.entity))
.collect(Collectors.toSet()); .collect(Collectors.toSet());
newContainer.parts.stream().filter(e -> e.entity != null).forEach(e -> e.entity.container = newContainer);
} }
world.markDirty(pos, world.getBlockEntity(pos)); world.markDirty(pos, world.getBlockEntity(pos));

View File

@ -1,77 +1,15 @@
package net.shadowfacts.simplemultipart.container; 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.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 * @author shadowfacts
*/ */
public class ContainerBlock extends Block implements BlockEntityProvider, RenderStateProvider { public class ContainerBlock extends AbstractContainerBlock {
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;
}
@Override @Override
public AbstractContainerBlockEntity createBlockEntity(BlockView world) { public AbstractContainerBlockEntity createBlockEntity(BlockView world) {
return new ContainerBlockEntity(); 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) { 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; 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")) @Inject(method = "<init>", at = @At("RETURN"))
public void addMultipartModel(ResourceManager manager, SpriteAtlasTexture texture, CallbackInfo info) { public void addMultipartModel(ResourceManager manager, SpriteAtlasTexture texture, CallbackInfo info) {
bakedModels.put(new ModelIdentifier("simplemultipart:container#"), new MultipartContainerBakedModel()); 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" }
}
}