168 lines
5.2 KiB
Java
168 lines
5.2 KiB
Java
package com.thebrokenrail.energonrelics.structure;
|
|
|
|
import com.thebrokenrail.energonrelics.util.MissingCaseException;
|
|
import net.minecraft.block.BlockState;
|
|
import net.minecraft.block.Blocks;
|
|
import net.minecraft.util.BlockRotation;
|
|
import net.minecraft.util.math.BlockPos;
|
|
import net.minecraft.util.math.Vec3d;
|
|
import net.minecraft.world.World;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.HashMap;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
|
|
public abstract class StructurePart<T> {
|
|
protected interface Transformation {
|
|
Vec3d transform(Vec3d vec);
|
|
BlockState transform(BlockState state);
|
|
}
|
|
|
|
private final T state;
|
|
|
|
protected T getState() {
|
|
return state;
|
|
}
|
|
|
|
public StructurePart(T state, List<Transformation> list) {
|
|
this.state = state;
|
|
transformations.addAll(list);
|
|
}
|
|
|
|
private final Map<Long, BlockState> blocks = new HashMap<>();
|
|
|
|
private final List<Transformation> transformations = new ArrayList<>();
|
|
|
|
protected static final Transformation NONE = new Transformation() {
|
|
@Override
|
|
public Vec3d transform(Vec3d vec) {
|
|
return vec;
|
|
}
|
|
|
|
@Override
|
|
public BlockState transform(BlockState state) {
|
|
return state;
|
|
}
|
|
};
|
|
protected static final Transformation CLOCKWISE_90 = new Transformation() {
|
|
@Override
|
|
public Vec3d transform(Vec3d vec) {
|
|
return new Vec3d(-vec.getZ(), vec.getY(), vec.getX());
|
|
}
|
|
|
|
@Override
|
|
public BlockState transform(BlockState state) {
|
|
return state.rotate(BlockRotation.CLOCKWISE_90);
|
|
}
|
|
};
|
|
protected static final Transformation CLOCKWISE_180 = new Transformation() {
|
|
@Override
|
|
public Vec3d transform(Vec3d vec) {
|
|
return new Vec3d(-vec.getX(), vec.getY(), -vec.getZ());
|
|
}
|
|
|
|
@Override
|
|
public BlockState transform(BlockState state) {
|
|
return state.rotate(BlockRotation.CLOCKWISE_180);
|
|
}
|
|
};
|
|
protected static final Transformation COUNTERCLOCKWISE_90 = new Transformation() {
|
|
@Override
|
|
public Vec3d transform(Vec3d vec) {
|
|
return new Vec3d(vec.getZ(), vec.getY(), -vec.getX());
|
|
}
|
|
|
|
@Override
|
|
public BlockState transform(BlockState state) {
|
|
return state.rotate(BlockRotation.COUNTERCLOCKWISE_90);
|
|
}
|
|
};
|
|
|
|
protected abstract void build(StructureContext context);
|
|
|
|
private Vec3d transform(Vec3d pos) {
|
|
for (Transformation transformation : transformations) {
|
|
pos = transformation.transform(pos);
|
|
}
|
|
return pos;
|
|
}
|
|
|
|
private BlockState transform(BlockState state) {
|
|
for (Transformation transformation : transformations) {
|
|
state = transformation.transform(state);
|
|
}
|
|
return state;
|
|
}
|
|
|
|
protected void set(int x, int y, int z, BlockState state) {
|
|
Vec3d vec = transform(new Vec3d(x, y, z));
|
|
blocks.put(new BlockPos(vec.getX(), vec.getY(), vec.getZ()).asLong(), transform(state));
|
|
}
|
|
|
|
protected void rect(int xPos, int yPos, int zPos, int width, int height, int depth, BlockState state) {
|
|
for (int x = 0; x < width; x++) {
|
|
for (int y = 0; y < height; y++) {
|
|
for (int z = 0; z < depth; z++) {
|
|
set(x + xPos, y + yPos, z + zPos, state);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
protected void repeat(Transformation[] functions, Runnable action) {
|
|
for (Transformation function : functions) {
|
|
transformations.add(function);
|
|
action.run();
|
|
transformations.remove(transformations.size() - 1);
|
|
}
|
|
}
|
|
|
|
protected void repeat(Runnable action) {
|
|
repeat(new Transformation[]{NONE, CLOCKWISE_90, CLOCKWISE_180, COUNTERCLOCKWISE_90}, action);
|
|
}
|
|
|
|
public void place(World world, BlockPos pos) {
|
|
for (Map.Entry<Long, BlockState> entry : blocks.entrySet()) {
|
|
BlockState state = entry.getValue();
|
|
if (state.getBlock() != Blocks.VOID_AIR) {
|
|
BlockPos newPos = pos.add(BlockPos.fromLong(entry.getKey()));
|
|
world.removeBlockEntity(newPos);
|
|
world.setBlockState(newPos, state);
|
|
handleBlockPlace(world, newPos, state);
|
|
}
|
|
}
|
|
}
|
|
|
|
protected abstract void handleBlockPlace(World world, BlockPos pos, BlockState state);
|
|
|
|
public static Transformation getTransformationFromBlockRotation(BlockRotation rotation) {
|
|
switch (rotation) {
|
|
case NONE: {
|
|
return NONE;
|
|
}
|
|
case CLOCKWISE_90: {
|
|
return CLOCKWISE_90;
|
|
}
|
|
case CLOCKWISE_180: {
|
|
return CLOCKWISE_180;
|
|
}
|
|
case COUNTERCLOCKWISE_90: {
|
|
return COUNTERCLOCKWISE_90;
|
|
}
|
|
default: {
|
|
throw new MissingCaseException(rotation);
|
|
}
|
|
}
|
|
}
|
|
|
|
protected void part(StructureContext context, int x, int y, int z, StructurePart<?> part) {
|
|
Vec3d vec = transform(new Vec3d(x, y, z));
|
|
context.addPart((int) vec.getX(), (int) vec.getY(), (int) vec.getZ(), part);
|
|
}
|
|
|
|
protected List<Transformation> getTransformations() {
|
|
return transformations;
|
|
}
|
|
}
|