Initial MultipartEntity implementation
This commit is contained in:
parent
04c21b644c
commit
d167b53931
|
@ -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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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) {
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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);
|
||||||
|
|
||||||
|
}
|
|
@ -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());
|
||||||
|
|
|
@ -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 + '}';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
{
|
{
|
||||||
|
"parent": "simplemultipart:multipart/multipart",
|
||||||
"textures": {
|
"textures": {
|
||||||
"texture": "block/diamond_block"
|
"texture": "block/diamond_block"
|
||||||
},
|
},
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"parent": "multipart_test:multipart/center",
|
||||||
|
"textures": {
|
||||||
|
"texture": "block/prismarine"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"variants": {
|
||||||
|
"": { "model": "multipart_test:multipart/entity_test" },
|
||||||
|
"inventory": { "model": "multipart_test:multipart/entity_test" }
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue