Initial MultipartEntity implementation

This commit is contained in:
Shadowfacts 2018-12-25 10:20:44 -05:00
parent 04c21b644c
commit d167b53931
Signed by: shadowfacts
GPG Key ID: 94A5AB95422746E5
21 changed files with 251 additions and 72 deletions

View File

@ -0,0 +1,24 @@
package net.shadowfacts.simplemultipart.api;
import net.shadowfacts.simplemultipart.container.MultipartContainerBlockEntity;
import net.shadowfacts.simplemultipart.multipart.Multipart;
import net.shadowfacts.simplemultipart.multipart.MultipartState;
import net.shadowfacts.simplemultipart.multipart.entity.MultipartEntity;
/**
* @author shadowfacts
*/
// TODO: better name for this
public interface MultipartView {
MultipartContainerBlockEntity getContainer();
MultipartState getState();
MultipartEntity getEntity();
default Multipart getMultipart() {
return getState().getMultipart();
}
}

View File

@ -4,7 +4,7 @@ import net.minecraft.block.BlockState;
import net.minecraft.client.render.model.BakedModel; import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.render.model.BakedQuad; import net.minecraft.client.render.model.BakedQuad;
import net.minecraft.util.math.Direction; import net.minecraft.util.math.Direction;
import net.shadowfacts.simplemultipart.multipart.MultipartState; import net.shadowfacts.simplemultipart.api.MultipartView;
import java.util.List; import java.util.List;
import java.util.Random; import java.util.Random;
@ -14,7 +14,7 @@ import java.util.Random;
*/ */
public interface MultipartBakedModel extends BakedModel { public interface MultipartBakedModel extends BakedModel {
List<BakedQuad> getMultipartQuads(MultipartState state, Direction side, Random random); List<BakedQuad> getMultipartQuads(MultipartView view, Direction side, Random random);
@Override @Override
default List<BakedQuad> getQuads(BlockState state, Direction side, Random random) { default List<BakedQuad> getQuads(BlockState state, Direction side, Random random) {

View File

@ -31,13 +31,13 @@ public class MultipartContainerBakedModel implements BakedModel {
MultipartContainerBlockState containerState = (MultipartContainerBlockState)state; MultipartContainerBlockState containerState = (MultipartContainerBlockState)state;
// TODO: would manually building the list be more efficient? // TODO: would manually building the list be more efficient?
return containerState.getParts().stream() return containerState.getParts().stream()
.flatMap(partState -> { .flatMap(view -> {
Identifier partId = SimpleMultipart.MULTIPART.getId(partState.getMultipart()); Identifier partId = SimpleMultipart.MULTIPART.getId(view.getMultipart());
String variant = BlockModels.propertyMapToString(partState.getEntries()); String variant = BlockModels.propertyMapToString(view.getState().getEntries());
ModelIdentifier modelId = new ModelIdentifier(partId, variant); ModelIdentifier modelId = new ModelIdentifier(partId, variant);
BakedModel model = MinecraftClient.getInstance().getBakedModelManager().getModel(modelId); BakedModel model = MinecraftClient.getInstance().getBakedModelManager().getModel(modelId);
if (model instanceof MultipartBakedModel) { if (model instanceof MultipartBakedModel) {
return ((MultipartBakedModel)model).getMultipartQuads(partState, side, random).stream(); return ((MultipartBakedModel)model).getMultipartQuads(view, side, random).stream();
} else { } else {
BlockState fakeState = null; BlockState fakeState = null;
@ -45,7 +45,7 @@ public class MultipartContainerBakedModel implements BakedModel {
// otherwise MultipartBakedModel will return no quads for a null state // otherwise MultipartBakedModel will return no quads for a null state
MultipartFakeBlock fakeBlock = MultipartFakeBlock.fakeBlocks.get(partId); MultipartFakeBlock fakeBlock = MultipartFakeBlock.fakeBlocks.get(partId);
if (fakeBlock != null) { if (fakeBlock != null) {
fakeState = fakeBlock.getFakeState(partState); fakeState = fakeBlock.getFakeState(view.getState());
} }
return model.getQuads(fakeState, side, random).stream(); return model.getQuads(fakeState, side, random).stream();

View File

@ -12,11 +12,10 @@ import net.minecraft.world.BlockView;
import net.minecraft.world.ExtendedBlockView; import net.minecraft.world.ExtendedBlockView;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.shadowfacts.simplemultipart.client.util.RenderStateProvider; import net.shadowfacts.simplemultipart.client.util.RenderStateProvider;
import net.shadowfacts.simplemultipart.multipart.MultipartState;
import net.shadowfacts.simplemultipart.util.MultipartHelper; import net.shadowfacts.simplemultipart.util.MultipartHelper;
import net.shadowfacts.simplemultipart.util.MultipartHitResult; import net.shadowfacts.simplemultipart.util.MultipartHitResult;
import net.shadowfacts.simplemultipart.api.MultipartView;
import java.util.Map;
import java.util.Set; import java.util.Set;
/** /**
@ -40,7 +39,7 @@ public class MultipartContainerBlock extends Block implements BlockEntityProvide
return false; return false;
} }
return hit.partState.activate(container, player, hand); return hit.view.getState().activate(hit.view, player, hand);
} }
@Override @Override
@ -50,7 +49,7 @@ public class MultipartContainerBlock extends Block implements BlockEntityProvide
return state; return state;
} }
Set<MultipartState> parts = container.getParts(); Set<MultipartView> parts = container.getParts();
return new MultipartContainerBlockState(state, parts); return new MultipartContainerBlockState(state, parts);
} }
@ -62,8 +61,8 @@ public class MultipartContainerBlock extends Block implements BlockEntityProvide
} }
VoxelShape shape = null; VoxelShape shape = null;
for (MultipartState partState : container.getParts()) { for (MultipartView view : container.getParts()) {
VoxelShape partShape = partState.getBoundingShape(container); VoxelShape partShape = view.getState().getBoundingShape(view);
shape = shape == null ? partShape : VoxelShapes.union(shape, partShape); shape = shape == null ? partShape : VoxelShapes.union(shape, partShape);
} }
return shape == null ? VoxelShapes.empty() : shape; return shape == null ? VoxelShapes.empty() : shape;

View File

@ -12,10 +12,16 @@ import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag; import net.minecraft.nbt.ListTag;
import net.minecraft.nbt.Tag; import net.minecraft.nbt.Tag;
import net.minecraft.server.world.ServerWorld; import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.shape.VoxelShape; import net.minecraft.util.shape.VoxelShape;
import net.minecraft.world.loot.context.LootContext;
import net.minecraft.world.loot.context.Parameters;
import net.shadowfacts.simplemultipart.SimpleMultipart; import net.shadowfacts.simplemultipart.SimpleMultipart;
import net.shadowfacts.simplemultipart.multipart.MultipartState; import net.shadowfacts.simplemultipart.multipart.MultipartState;
import net.shadowfacts.simplemultipart.multipart.entity.MultipartEntity;
import net.shadowfacts.simplemultipart.multipart.entity.MultipartEntityProvider;
import net.shadowfacts.simplemultipart.util.MultipartHelper; import net.shadowfacts.simplemultipart.util.MultipartHelper;
import net.shadowfacts.simplemultipart.api.MultipartView;
import net.shadowfacts.simplemultipart.util.ShapeUtils; import net.shadowfacts.simplemultipart.util.ShapeUtils;
import java.util.*; import java.util.*;
@ -25,20 +31,20 @@ import java.util.*;
*/ */
public class MultipartContainerBlockEntity extends BlockEntity implements ClientSerializable { public class MultipartContainerBlockEntity extends BlockEntity implements ClientSerializable {
private Set<MultipartState> parts = new HashSet<>(); private Set<Entry> parts = new HashSet<>();
public MultipartContainerBlockEntity() { public MultipartContainerBlockEntity() {
super(SimpleMultipart.containerBlockEntity); super(SimpleMultipart.containerBlockEntity);
} }
public ImmutableSet<MultipartState> getParts() { public Set<MultipartView> getParts() {
return ImmutableSet.copyOf(parts); return ImmutableSet.copyOf(parts);
} }
public boolean canInsert(MultipartState partState) { public boolean canInsert(MultipartState partState) {
VoxelShape newShape = partState.getBoundingShape(null); VoxelShape newShape = partState.getBoundingShape(null);
for (MultipartState existing : parts) { for (Entry e : parts) {
VoxelShape existingShape = existing.getBoundingShape(this); VoxelShape existingShape = e.state.getBoundingShape(e);
if (ShapeUtils.intersect(newShape, existingShape)) { if (ShapeUtils.intersect(newShape, existingShape)) {
return false; return false;
} }
@ -48,13 +54,17 @@ public class MultipartContainerBlockEntity extends BlockEntity implements Client
} }
public void insert(MultipartState partState) { public void insert(MultipartState partState) {
parts.add(partState); MultipartEntity entity = null;
if (partState.getMultipart() instanceof MultipartEntityProvider) {
entity = ((MultipartEntityProvider)partState.getMultipart()).createMultipartEntity(partState, this);
}
parts.add(new Entry(partState, entity));
markDirty(); markDirty();
world.scheduleBlockRender(pos); world.scheduleBlockRender(pos);
} }
public void remove(MultipartState partState) { public void remove(MultipartState partState) {
parts.remove(partState); parts.removeIf(e -> e.state == partState);
if (parts.isEmpty()) { if (parts.isEmpty()) {
world.setBlockState(pos, Blocks.AIR.getDefaultState()); world.setBlockState(pos, Blocks.AIR.getDefaultState());
@ -62,8 +72,13 @@ public class MultipartContainerBlockEntity extends BlockEntity implements Client
} }
public boolean breakPart(MultipartState partState) { public boolean breakPart(MultipartState partState) {
Optional<Entry> entry = parts.stream().filter(e -> e.state == partState).findFirst();
if (!entry.isPresent()) {
return false;
}
if (world instanceof ServerWorld) { if (world instanceof ServerWorld) {
List<ItemStack> drops = MultipartHelper.getDroppedStacks(partState, (ServerWorld)world, pos); List<ItemStack> drops = getDroppedStacks(entry.get(), (ServerWorld)world, pos);
drops.forEach(stack -> Block.dropStack(world, pos, stack)); drops.forEach(stack -> Block.dropStack(world, pos, stack));
// TODO: don't drop if player is creative // TODO: don't drop if player is creative
} }
@ -78,22 +93,38 @@ public class MultipartContainerBlockEntity extends BlockEntity implements Client
return true; return true;
} }
private List<ItemStack> getDroppedStacks(MultipartContainerBlockEntity.Entry e, ServerWorld world, BlockPos pos) {
LootContext.Builder builder = new LootContext.Builder(world);
builder.setRandom(world.random);
builder.put(SimpleMultipart.MULTIPART_STATE_PARAMETER, e.state);
builder.put(Parameters.POSITION, pos);
return e.state.getDroppedStacks(e, builder);
}
private ListTag partsToTag() { private ListTag partsToTag() {
ListTag list = new ListTag(); ListTag list = new ListTag();
parts.forEach(state -> { for (Entry e : parts) {
if (state != null) { CompoundTag tag = new CompoundTag();
CompoundTag partStateTag = MultipartHelper.serializeMultipartState(state); tag.put("part", MultipartHelper.serializeMultipartState(e.state));
list.add(partStateTag); if (e.entity != null) {
tag.put("entity", e.entity.toTag(new CompoundTag()));
}
list.add(tag);
} }
});
return list; return list;
} }
private void partsFromTag(ListTag list) { private void partsFromTag(ListTag list) {
parts.clear(); parts.clear();
for (Tag tag : list) { for (Tag tag : list) {
MultipartState state = MultipartHelper.deserializeMultipartState((CompoundTag)tag); CompoundTag compound = (CompoundTag)tag;
parts.add(state); MultipartState state = MultipartHelper.deserializeMultipartState(compound.getCompound("part"));
MultipartEntity entity = null;
if (state.getMultipart() instanceof MultipartEntityProvider && compound.containsKey("entity", NbtType.COMPOUND)) {
entity = ((MultipartEntityProvider)state.getMultipart()).createMultipartEntity(state, this);
entity.fromTag(compound.getCompound("entity"));
}
parts.add(new Entry(state, entity));
} }
} }
@ -122,4 +153,30 @@ public class MultipartContainerBlockEntity extends BlockEntity implements Client
partsFromTag(list); partsFromTag(list);
world.scheduleBlockRender(pos); world.scheduleBlockRender(pos);
} }
public class Entry implements MultipartView {
public final MultipartState state;
public final MultipartEntity entity;
private Entry(MultipartState state, MultipartEntity entity) {
this.state = state;
this.entity = entity;
}
@Override
public MultipartContainerBlockEntity getContainer() {
return MultipartContainerBlockEntity.this; // TODO: is this bad?
}
@Override
public MultipartState getState() {
return state;
}
@Override
public MultipartEntity getEntity() {
return entity;
}
}
} }

View File

@ -1,9 +1,8 @@
package net.shadowfacts.simplemultipart.container; package net.shadowfacts.simplemultipart.container;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.shadowfacts.simplemultipart.multipart.MultipartState; import net.shadowfacts.simplemultipart.api.MultipartView;
import java.util.Map;
import java.util.Set; import java.util.Set;
/** /**
@ -11,14 +10,14 @@ import java.util.Set;
*/ */
public class MultipartContainerBlockState extends BlockState { public class MultipartContainerBlockState extends BlockState {
private Set<MultipartState> parts; private Set<MultipartView> parts;
public MultipartContainerBlockState(BlockState delegate, Set<MultipartState> parts) { public MultipartContainerBlockState(BlockState delegate, Set<MultipartView> parts) {
super(delegate.getBlock(), delegate.getEntries()); super(delegate.getBlock(), delegate.getEntries());
this.parts = parts; this.parts = parts;
} }
public Set<MultipartState> getParts() { public Set<MultipartView> getParts() {
return parts; return parts;
} }
} }

View File

@ -35,7 +35,7 @@ public class MultipartContainerEventHandler {
return ActionResult.FAILURE; return ActionResult.FAILURE;
} }
boolean success = container.breakPart(hit.partState); boolean success = container.breakPart(hit.view.getState());
return success ? ActionResult.SUCCESS : ActionResult.FAILURE; return success ? ActionResult.SUCCESS : ActionResult.FAILURE;
} }

View File

@ -5,17 +5,15 @@ import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.server.world.ServerWorld; import net.minecraft.server.world.ServerWorld;
import net.minecraft.state.StateFactory; import net.minecraft.state.StateFactory;
import net.minecraft.state.property.EnumProperty;
import net.minecraft.util.Hand; import net.minecraft.util.Hand;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import net.minecraft.util.math.Direction;
import net.minecraft.util.shape.VoxelShape; import net.minecraft.util.shape.VoxelShape;
import net.minecraft.world.loot.LootSupplier; import net.minecraft.world.loot.LootSupplier;
import net.minecraft.world.loot.LootTables; import net.minecraft.world.loot.LootTables;
import net.minecraft.world.loot.context.LootContext; import net.minecraft.world.loot.context.LootContext;
import net.shadowfacts.simplemultipart.SimpleMultipart; import net.shadowfacts.simplemultipart.SimpleMultipart;
import net.shadowfacts.simplemultipart.container.MultipartContainerBlockEntity;
import net.shadowfacts.simplemultipart.util.MultipartPlacementContext; import net.shadowfacts.simplemultipart.util.MultipartPlacementContext;
import net.shadowfacts.simplemultipart.api.MultipartView;
import java.util.List; import java.util.List;
@ -58,7 +56,7 @@ public abstract class Multipart {
* Can be overridden, should only be called via {@link MultipartState#getStateForRendering} * Can be overridden, should only be called via {@link MultipartState#getStateForRendering}
*/ */
@Deprecated @Deprecated
public MultipartState getStateForRendering(MultipartState state, MultipartContainerBlockEntity container) { public MultipartState getStateForRendering(MultipartState state, MultipartView view) {
return state; return state;
} }
@ -66,7 +64,7 @@ public abstract class Multipart {
* Can be overridden, should only be called via {@link MultipartState#getBoundingShape} * Can be overridden, should only be called via {@link MultipartState#getBoundingShape}
*/ */
@Deprecated @Deprecated
public abstract VoxelShape getBoundingShape(/*@Nullable*/ MultipartState state, MultipartContainerBlockEntity container); public abstract VoxelShape getBoundingShape(/*@Nullable*/ MultipartState state, MultipartView view);
public Identifier getDropTableId() { public Identifier getDropTableId() {
if (dropTableId == null) { if (dropTableId == null) {
@ -80,7 +78,7 @@ public abstract class Multipart {
* Can be overridden, should only be called via {@link MultipartState#getDroppedStacks)} * Can be overridden, should only be called via {@link MultipartState#getDroppedStacks)}
*/ */
@Deprecated @Deprecated
public List<ItemStack> getDroppedStacks(MultipartState state, LootContext.Builder builder) { public List<ItemStack> getDroppedStacks(MultipartState state, MultipartView view, LootContext.Builder builder) {
Identifier dropTableId = getDropTableId(); Identifier dropTableId = getDropTableId();
if (dropTableId == LootTables.EMPTY) { if (dropTableId == LootTables.EMPTY) {
return ImmutableList.of(); return ImmutableList.of();
@ -96,7 +94,7 @@ public abstract class Multipart {
* Can be overridden, should only be called via {@link MultipartState#activate} * Can be overridden, should only be called via {@link MultipartState#activate}
*/ */
@Deprecated @Deprecated
public boolean activate(MultipartState state, MultipartContainerBlockEntity container, PlayerEntity player, Hand hand) { public boolean activate(MultipartState state, MultipartView view, PlayerEntity player, Hand hand) {
return false; return false;
} }

View File

@ -8,7 +8,7 @@ import net.minecraft.state.property.Property;
import net.minecraft.util.Hand; import net.minecraft.util.Hand;
import net.minecraft.util.shape.VoxelShape; import net.minecraft.util.shape.VoxelShape;
import net.minecraft.world.loot.context.LootContext; import net.minecraft.world.loot.context.LootContext;
import net.shadowfacts.simplemultipart.container.MultipartContainerBlockEntity; import net.shadowfacts.simplemultipart.api.MultipartView;
import java.util.List; import java.util.List;
@ -25,24 +25,24 @@ public class MultipartState extends AbstractPropertyContainer<Multipart, Multipa
return owner; return owner;
} }
public MultipartState getStateForRendering(MultipartContainerBlockEntity container) { public MultipartState getStateForRendering(MultipartView view) {
//noinspection deprecation //noinspection deprecation
return owner.getStateForRendering(this, container); return owner.getStateForRendering(this, view);
} }
public VoxelShape getBoundingShape(/*@Nullable*/ MultipartContainerBlockEntity container) { public VoxelShape getBoundingShape(/*@Nullable*/ MultipartView view) {
//noinspection deprecation //noinspection deprecation
return owner.getBoundingShape(this, container); return owner.getBoundingShape(this, view);
} }
public List<ItemStack> getDroppedStacks(LootContext.Builder builder) { public List<ItemStack> getDroppedStacks(MultipartView view, LootContext.Builder builder) {
//noinspection deprecated //noinspection deprecated
return owner.getDroppedStacks(this, builder); return owner.getDroppedStacks(this, view, builder);
} }
public boolean activate(MultipartContainerBlockEntity container, PlayerEntity player, Hand hand) { public boolean activate(MultipartView view, PlayerEntity player, Hand hand) {
//noinspection deprecated //noinspection deprecated
return owner.activate(this, container, player, hand); return owner.activate(this, view, player, hand);
} }
} }

View File

@ -0,0 +1,28 @@
package net.shadowfacts.simplemultipart.multipart.entity;
import net.minecraft.nbt.CompoundTag;
import net.shadowfacts.simplemultipart.container.MultipartContainerBlockEntity;
/**
* @author shadowfacts
*/
public abstract class MultipartEntity {
public MultipartContainerBlockEntity container;
public MultipartEntity(MultipartContainerBlockEntity container) {
this.container = container;
}
protected void scheduleSave() {
container.markDirty(); // see yarn #360
}
public CompoundTag toTag(CompoundTag tag) {
return tag;
}
public void fromTag(CompoundTag tag) {
}
}

View File

@ -0,0 +1,14 @@
package net.shadowfacts.simplemultipart.multipart.entity;
import net.shadowfacts.simplemultipart.container.MultipartContainerBlockEntity;
import net.shadowfacts.simplemultipart.multipart.MultipartState;
/**
* @author shadowfacts
*/
public interface MultipartEntityProvider {
/*@Nullable*/
MultipartEntity createMultipartEntity(MultipartState state, MultipartContainerBlockEntity container);
}

View File

@ -51,24 +51,16 @@ public class MultipartHelper {
public static MultipartHitResult rayTrace(MultipartContainerBlockEntity container, World world, BlockPos pos, Vec3d start, Vec3d end) { public static MultipartHitResult rayTrace(MultipartContainerBlockEntity container, World world, BlockPos pos, Vec3d start, Vec3d end) {
return container.getParts().stream() return container.getParts().stream()
.map(partState -> { .map(view -> {
VoxelShape shape = partState.getBoundingShape(container); VoxelShape shape = view.getState().getBoundingShape(view);
HitResult result = shape.rayTrace(start, end, pos); HitResult result = shape.rayTrace(start, end, pos);
return result == null ? null : new MultipartHitResult(result, partState); return result == null ? null : new MultipartHitResult(result, view);
}) })
.filter(Objects::nonNull) .filter(Objects::nonNull)
.min(Comparator.comparingDouble(hit -> hit.pos.subtract(start).lengthSquared())) .min(Comparator.comparingDouble(hit -> hit.pos.subtract(start).lengthSquared()))
.orElse(null); .orElse(null);
} }
public static List<ItemStack> getDroppedStacks(MultipartState state, ServerWorld world, BlockPos pos) {
LootContext.Builder builder = new LootContext.Builder(world);
builder.setRandom(world.random);
builder.put(SimpleMultipart.MULTIPART_STATE_PARAMETER, state);
builder.put(Parameters.POSITION, pos);
return state.getDroppedStacks(builder);
}
public static CompoundTag serializeMultipartState(MultipartState state) { public static CompoundTag serializeMultipartState(MultipartState state) {
CompoundTag tag = new CompoundTag(); CompoundTag tag = new CompoundTag();
tag.putString("Name", SimpleMultipart.MULTIPART.getId(state.getMultipart()).toString()); tag.putString("Name", SimpleMultipart.MULTIPART.getId(state.getMultipart()).toString());

View File

@ -4,22 +4,22 @@ import net.minecraft.util.HitResult;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction; import net.minecraft.util.math.Direction;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
import net.shadowfacts.simplemultipart.multipart.MultipartState; import net.shadowfacts.simplemultipart.api.MultipartView;
/** /**
* @author shadowfacts * @author shadowfacts
*/ */
public class MultipartHitResult extends HitResult { public class MultipartHitResult extends HitResult {
public MultipartState partState; public MultipartView view;
public MultipartHitResult(Vec3d pos, Direction side, BlockPos blockPos, MultipartState partState) { public MultipartHitResult(Vec3d pos, Direction side, BlockPos blockPos, MultipartView view) {
super(pos, side, blockPos); super(pos, side, blockPos);
this.partState = partState; this.view = view;
} }
public MultipartHitResult(HitResult result, MultipartState partState) { public MultipartHitResult(HitResult result, MultipartView view) {
this(result.pos, result.side, result.getBlockPos(), partState); this(result.pos, result.side, result.getBlockPos(), view);
if (result.type != Type.BLOCK) { if (result.type != Type.BLOCK) {
throw new IllegalArgumentException("Can't create a MultipartHitResult from a non BLOCK-type HitResult"); throw new IllegalArgumentException("Can't create a MultipartHitResult from a non BLOCK-type HitResult");
} }
@ -27,6 +27,6 @@ public class MultipartHitResult extends HitResult {
@Override @Override
public String toString() { public String toString() {
return "HitResult{type=" + type + ", blockpos=" + getBlockPos() + ", f=" + side + ", pos=" + pos + ", partState=" + partState + '}'; return "HitResult{type=" + type + ", blockpos=" + getBlockPos() + ", f=" + side + ", pos=" + pos + ", view=" + view + '}';
} }
} }

View File

@ -10,6 +10,7 @@ import net.minecraft.util.shape.VoxelShapes;
public class ShapeUtils { public class ShapeUtils {
public static boolean intersect(VoxelShape a, VoxelShape b) { public static boolean intersect(VoxelShape a, VoxelShape b) {
// TODO: this seems very inefficient
VoxelShape overlap = VoxelShapes.combine(a, b, BooleanBiFunction.AND); VoxelShape overlap = VoxelShapes.combine(a, b, BooleanBiFunction.AND);
return !overlap.isEmpty(); return !overlap.isEmpty();
} }

View File

@ -0,0 +1,51 @@
package net.shadowfacts.simplemultipart.test;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.text.StringTextComponent;
import net.minecraft.util.Hand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.util.shape.VoxelShapes;
import net.shadowfacts.simplemultipart.container.MultipartContainerBlockEntity;
import net.shadowfacts.simplemultipart.multipart.Multipart;
import net.shadowfacts.simplemultipart.multipart.MultipartState;
import net.shadowfacts.simplemultipart.multipart.entity.MultipartEntity;
import net.shadowfacts.simplemultipart.multipart.entity.MultipartEntityProvider;
import net.shadowfacts.simplemultipart.api.MultipartView;
import java.util.function.Function;
/**
* @author shadowfacts
*/
public class EntityTestPart extends Multipart implements MultipartEntityProvider<EntityTestPart.Entity> {
@Override
public VoxelShape getBoundingShape(MultipartState state, MultipartView view) {
return VoxelShapes.cube(6/16f, 6/16f, 6/16f, 10/16f, 10/16f, 10/16f);
}
@Override
@Deprecated
public boolean activate(MultipartState state, MultipartView view, PlayerEntity player, Hand hand) {
BlockPos pos = ((Entity)view.getEntity()).getPos();
player.addChatMessage(new StringTextComponent("Clicked: " + pos), false);
return true;
}
@Override
public Function<MultipartContainerBlockEntity, Entity> getMultipartEntityFactory() {
return Entity::new;
}
public static class Entity extends MultipartEntity {
public Entity(MultipartContainerBlockEntity container) {
super(container);
}
public BlockPos getPos() {
return container.getPos();
}
}
}

View File

@ -18,16 +18,19 @@ public class MultipartTestMod implements ModInitializer {
public static final TestMultipart testPart = new TestMultipart(); public static final TestMultipart testPart = new TestMultipart();
public static final SlabMultipart ironSlab = new SlabMultipart(); public static final SlabMultipart ironSlab = new SlabMultipart();
public static final SlabMultipart goldSlab = new SlabMultipart(); public static final SlabMultipart goldSlab = new SlabMultipart();
public static final EntityTestPart entityTest = new EntityTestPart();
public static final ItemMultipart testItem = new ItemMultipart(testPart); public static final ItemMultipart testItem = new ItemMultipart(testPart);
public static final ItemMultipart ironSlabItem = new ItemMultipart(ironSlab); public static final ItemMultipart ironSlabItem = new ItemMultipart(ironSlab);
public static final ItemMultipart goldSlabItem = new ItemMultipart(goldSlab); public static final ItemMultipart goldSlabItem = new ItemMultipart(goldSlab);
public static final ItemMultipart entityTestItem = new ItemMultipart(entityTest);
@Override @Override
public void onInitialize() { public void onInitialize() {
registerPartAndItem("test_part", testPart, testItem); registerPartAndItem("test_part", testPart, testItem);
registerPartAndItem("iron_slab", ironSlab, ironSlabItem); registerPartAndItem("iron_slab", ironSlab, ironSlabItem);
registerPartAndItem("gold_slab", goldSlab, goldSlabItem); registerPartAndItem("gold_slab", goldSlab, goldSlabItem);
registerPartAndItem("entity_test", entityTest, entityTestItem);
} }
private void registerPartAndItem(String name, Multipart part, Item item) { private void registerPartAndItem(String name, Multipart part, Item item) {

View File

@ -6,10 +6,10 @@ import net.minecraft.state.property.EnumProperty;
import net.minecraft.util.math.Direction; import net.minecraft.util.math.Direction;
import net.minecraft.util.shape.VoxelShape; import net.minecraft.util.shape.VoxelShape;
import net.minecraft.util.shape.VoxelShapes; import net.minecraft.util.shape.VoxelShapes;
import net.shadowfacts.simplemultipart.container.MultipartContainerBlockEntity;
import net.shadowfacts.simplemultipart.multipart.Multipart; import net.shadowfacts.simplemultipart.multipart.Multipart;
import net.shadowfacts.simplemultipart.multipart.MultipartState; import net.shadowfacts.simplemultipart.multipart.MultipartState;
import net.shadowfacts.simplemultipart.util.MultipartPlacementContext; import net.shadowfacts.simplemultipart.util.MultipartPlacementContext;
import net.shadowfacts.simplemultipart.api.MultipartView;
/** /**
* @author shadowfacts * @author shadowfacts
@ -64,7 +64,7 @@ public class SlabMultipart extends Multipart {
} }
@Override @Override
public VoxelShape getBoundingShape(MultipartState state, MultipartContainerBlockEntity container) { public VoxelShape getBoundingShape(MultipartState state, MultipartView view) {
return state.get(HALF) == BlockHalf.UPPER ? UPPER_BOX : LOWER_BOX; return state.get(HALF) == BlockHalf.UPPER ? UPPER_BOX : LOWER_BOX;
} }
} }

View File

@ -7,10 +7,10 @@ import net.minecraft.util.Hand;
import net.minecraft.util.math.Direction; import net.minecraft.util.math.Direction;
import net.minecraft.util.shape.VoxelShape; import net.minecraft.util.shape.VoxelShape;
import net.minecraft.util.shape.VoxelShapes; import net.minecraft.util.shape.VoxelShapes;
import net.shadowfacts.simplemultipart.container.MultipartContainerBlockEntity;
import net.shadowfacts.simplemultipart.multipart.Multipart; import net.shadowfacts.simplemultipart.multipart.Multipart;
import net.shadowfacts.simplemultipart.multipart.MultipartState; import net.shadowfacts.simplemultipart.multipart.MultipartState;
import net.shadowfacts.simplemultipart.util.MultipartPlacementContext; import net.shadowfacts.simplemultipart.util.MultipartPlacementContext;
import net.shadowfacts.simplemultipart.api.MultipartView;
/** /**
* @author shadowfacts * @author shadowfacts
@ -35,7 +35,7 @@ public class TestMultipart extends Multipart {
@Override @Override
@Deprecated @Deprecated
public VoxelShape getBoundingShape(MultipartState state, MultipartContainerBlockEntity container) { public VoxelShape getBoundingShape(MultipartState state, MultipartView view) {
Direction side = state.get(Properties.FACING); Direction side = state.get(Properties.FACING);
switch (side) { switch (side) {
case UP: case UP:
@ -56,7 +56,7 @@ public class TestMultipart extends Multipart {
@Override @Override
@Deprecated @Deprecated
public boolean activate(MultipartState state, MultipartContainerBlockEntity container, PlayerEntity player, Hand hand) { public boolean activate(MultipartState state, MultipartView view, PlayerEntity player, Hand hand) {
Direction side = state.get(Properties.FACING); Direction side = state.get(Properties.FACING);
System.out.println("part activated on " + side); System.out.println("part activated on " + side);
return true; return true;

View File

@ -1,4 +1,5 @@
{ {
"parent": "simplemultipart:multipart/multipart",
"textures": { "textures": {
"texture": "block/diamond_block" "texture": "block/diamond_block"
}, },

View File

@ -0,0 +1,6 @@
{
"parent": "multipart_test:multipart/center",
"textures": {
"texture": "block/prismarine"
}
}

View File

@ -0,0 +1,6 @@
{
"variants": {
"": { "model": "multipart_test:multipart/entity_test" },
"inventory": { "model": "multipart_test:multipart/entity_test" }
}
}