Initial implementation of container getPart(Direction)

This commit is contained in:
Shadowfacts 2018-12-29 18:33:16 -05:00
parent 6ade580e85
commit 7c465d01f4
Signed by: shadowfacts
GPG Key ID: 94A5AB95422746E5
4 changed files with 67 additions and 6 deletions

View File

@ -12,9 +12,14 @@ version = "0.1.0"
minecraft { minecraft {
} }
repositories {
mavenLocal()
}
dependencies { dependencies {
minecraft "com.mojang:minecraft:18w50a" minecraft "com.mojang:minecraft:18w50a"
mappings "net.fabricmc:yarn:18w50a.80" // mappings "net.fabricmc:yarn:18w50a.80"
mappings "net.fabricmc:yarn:18w50a.local" // temporary until yarn #369
modCompile "net.fabricmc:fabric-loader:0.3.1.80" modCompile "net.fabricmc:fabric-loader:0.3.1.80"
// Fabric API. This is technically optional, but you probably want it anyway. // Fabric API. This is technically optional, but you probably want it anyway.

View File

@ -15,6 +15,7 @@ import net.minecraft.nbt.Tag;
import net.minecraft.server.world.ServerWorld; import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.Tickable; import net.minecraft.util.Tickable;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
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.minecraft.world.loot.context.Parameters; import net.minecraft.world.loot.context.Parameters;
@ -35,6 +36,7 @@ import java.util.stream.Collectors;
public abstract class AbstractContainerBlockEntity extends BlockEntity implements MultipartContainer, ClientSerializable { public abstract class AbstractContainerBlockEntity extends BlockEntity implements MultipartContainer, ClientSerializable {
protected Set<Entry> parts = new HashSet<>(); protected Set<Entry> parts = new HashSet<>();
protected Map<Direction, Entry> sidePartCache = new WeakHashMap<>();
public AbstractContainerBlockEntity(BlockEntityType<?> type) { public AbstractContainerBlockEntity(BlockEntityType<?> type) {
super(type); super(type);
@ -50,6 +52,36 @@ public abstract class AbstractContainerBlockEntity extends BlockEntity implement
return !parts.isEmpty(); return !parts.isEmpty();
} }
@Override
public MultipartView getPart(Direction side) {
Entry existing = sidePartCache.get(side);
if (existing != null) {
return existing;
}
Optional<Entry> e = parts.stream()
.min((a, b) -> {
VoxelShape aShape = a.getState().getBoundingShape(a);
VoxelShape bShape = b.getState().getBoundingShape(b);
double aCoord = side.getDirection() == Direction.AxisDirection.POSITIVE ? aShape.getMaximum(side.getAxis()) : aShape.getMinimum(side.getAxis());
double bCoord = side.getDirection() == Direction.AxisDirection.POSITIVE ? bShape.getMaximum(side.getAxis()) : bShape.getMinimum(side.getAxis());
return Double.compare(bCoord, aCoord);
});
if (!e.isPresent()) {
return null;
}
sidePartCache.put(side, e.get());
return e.get();
}
@Override
public void invalidateSidePartCache() {
sidePartCache.clear();
}
@Override @Override
public boolean canInsert(MultipartState partState) { public boolean canInsert(MultipartState partState) {
VoxelShape newShape = partState.getBoundingShape(null); VoxelShape newShape = partState.getBoundingShape(null);
@ -77,6 +109,7 @@ public abstract class AbstractContainerBlockEntity extends BlockEntity implement
} }
parts.add(e); parts.add(e);
invalidateSidePartCache();
updateWorld(); updateWorld();
} }
@ -91,6 +124,7 @@ public abstract class AbstractContainerBlockEntity extends BlockEntity implement
if (parts.isEmpty()) { if (parts.isEmpty()) {
world.setBlockState(pos, Blocks.AIR.getDefaultState()); world.setBlockState(pos, Blocks.AIR.getDefaultState());
} else { } else {
invalidateSidePartCache();
updateWorld(); updateWorld();
} }
} }
@ -203,18 +237,18 @@ public abstract class AbstractContainerBlockEntity extends BlockEntity implement
} }
public static class Entry implements MultipartView { public static class Entry implements MultipartView {
public final MultipartContainer container; public final AbstractContainerBlockEntity container;
public MultipartState state; public MultipartState state;
public MultipartEntity entity; public MultipartEntity entity;
private Entry(MultipartContainer container, MultipartState state, MultipartEntity entity) { private Entry(AbstractContainerBlockEntity container, MultipartState state, MultipartEntity entity) {
this.container = container; this.container = container;
this.state = state; this.state = state;
this.entity = entity; this.entity = entity;
} }
@Override @Override
public MultipartContainer getContainer() { public AbstractContainerBlockEntity getContainer() {
return container; return container;
} }
@ -226,6 +260,7 @@ public abstract class AbstractContainerBlockEntity extends BlockEntity implement
@Override @Override
public void setState(MultipartState state) { public void setState(MultipartState state) {
this.state = state; this.state = state;
container.invalidateSidePartCache();
} }
@Override @Override
@ -236,6 +271,7 @@ public abstract class AbstractContainerBlockEntity extends BlockEntity implement
@Override @Override
public void setEntity(MultipartEntity entity) { public void setEntity(MultipartEntity entity) {
this.entity = entity; this.entity = entity;
container.invalidateSidePartCache();
} }
@Override @Override

View File

@ -1,5 +1,6 @@
package net.shadowfacts.simplemultipart.container; package net.shadowfacts.simplemultipart.container;
import net.minecraft.util.math.Direction;
import net.shadowfacts.simplemultipart.multipart.MultipartView; import net.shadowfacts.simplemultipart.multipart.MultipartView;
import net.shadowfacts.simplemultipart.multipart.MultipartState; import net.shadowfacts.simplemultipart.multipart.MultipartState;
@ -27,6 +28,26 @@ public interface MultipartContainer {
*/ */
boolean hasParts(); boolean hasParts();
/**
* Gets the part on the given side.
*
* Will return the part with the greatest/least min/max coordinate based on the direction's axis.
* For example, getting the part on the {@code NORTH} side will return the part with the smallest minimum Z coordinate.
* If multiple parts have the same min/max coordinate, which one will be returned is undefined.
*
* @param side The side to determine the part for.
* @return The part on the given side.
*/
MultipartView getPart(Direction side);
/**
* Containers store a cache of which part is on which side, calculated using the bounding box.
*
* If anything changes in your part that changes its bounding shape, this method should be called.
* The container {@code insert}, {@code breakPart}, and {@code remove} methods automatically call this.
*/
void invalidateSidePartCache();
/** /**
* Determines whether the given multipart state can be inserted into this container. * Determines whether the given multipart state can be inserted into this container.
* Checks that the bounding box of the new part does not intersect with any existing ones. * Checks that the bounding box of the new part does not intersect with any existing ones.

View File

@ -57,8 +57,7 @@ public class TestMultipart extends Multipart {
@Override @Override
@Deprecated @Deprecated
public boolean activate(MultipartView view, PlayerEntity player, Hand hand) { public boolean activate(MultipartView view, PlayerEntity player, Hand hand) {
Direction side = view.getState().get(Properties.FACING); System.out.println(view.getContainer().getPart(Direction.UP));
System.out.println("part activated on " + side);
return true; return true;
} }