This repository has been archived on 2023-11-26. You can view files and clone it, but cannot push or open issues or pull requests.
EnergonRelics/src/main/java/com/thebrokenrail/energonrelics/structure/StructurePart.java

218 lines
6.5 KiB
Java

package com.thebrokenrail.energonrelics.structure;
import com.thebrokenrail.energonrelics.util.MissingCaseException;
import net.minecraft.block.BlockState;
import net.minecraft.state.property.Properties;
import net.minecraft.util.BlockMirror;
import net.minecraft.util.BlockRotation;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
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> {
public interface Transformation {
BlockPos transform(BlockPos pos);
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 BlockPos transform(BlockPos pos) {
return pos;
}
@Override
public BlockState transform(BlockState state) {
return state;
}
};
protected static final Transformation CLOCKWISE_90 = new Transformation() {
@Override
public BlockPos transform(BlockPos pos) {
return new BlockPos(-pos.getZ(), pos.getY(), pos.getX());
}
@Override
public BlockState transform(BlockState state) {
return state.rotate(BlockRotation.CLOCKWISE_90);
}
};
protected static final Transformation CLOCKWISE_180 = new Transformation() {
@Override
public BlockPos transform(BlockPos pos) {
return new BlockPos(-pos.getX(), pos.getY(), -pos.getZ());
}
@Override
public BlockState transform(BlockState state) {
return state.rotate(BlockRotation.CLOCKWISE_180);
}
};
protected static final Transformation COUNTERCLOCKWISE_90 = new Transformation() {
@Override
public BlockPos transform(BlockPos pos) {
return new BlockPos(pos.getZ(), pos.getY(), -pos.getX());
}
@Override
public BlockState transform(BlockState state) {
return state.rotate(BlockRotation.COUNTERCLOCKWISE_90);
}
};
protected static final Transformation MIRROR_DEPTH = new Transformation() {
@Override
public BlockPos transform(BlockPos pos) {
return new BlockPos(pos.getX(), pos.getY(), -pos.getZ());
}
@Override
public BlockState transform(BlockState state) {
state = state.mirror(BlockMirror.LEFT_RIGHT);
if (state.contains(Properties.CHEST_TYPE)) {
state = state.with(Properties.CHEST_TYPE, state.get(Properties.CHEST_TYPE).getOpposite());
}
return state;
}
};
protected abstract void build(StructureContext context);
private BlockPos transform(BlockPos 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(BlockPos originalPos, BlockState state) {
BlockPos pos = transform(originalPos);
blocks.put(pos.asLong(), transform(state));
}
protected void rect(BlockPos pos, 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(pos.add(x, y, z), state);
}
}
}
}
protected void rotate(Transformation[] functions, Runnable action) {
for (Transformation function : functions) {
transformations.add(function);
action.run();
transformations.remove(transformations.size() - 1);
}
}
protected void rotate(Runnable action) {
rotate(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();
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 directionToTransformation(Direction direction) {
switch (direction) {
case NORTH: {
return NONE;
}
case EAST: {
return CLOCKWISE_90;
}
case SOUTH: {
return CLOCKWISE_180;
}
case WEST: {
return COUNTERCLOCKWISE_90;
}
default: {
throw new MissingCaseException(direction);
}
}
}
public static Direction blockRotationToDirection(BlockRotation rotation) {
switch (rotation) {
case NONE: {
return Direction.NORTH;
}
case CLOCKWISE_90: {
return Direction.EAST;
}
case CLOCKWISE_180: {
return Direction.SOUTH;
}
case COUNTERCLOCKWISE_90: {
return Direction.WEST;
}
default: {
throw new MissingCaseException(rotation);
}
}
}
protected void part(StructureContext context, BlockPos originalPos, StructurePart<?> part) {
BlockPos pos = transform(originalPos);
context.addPart(pos.getX(), pos.getY(), pos.getZ(), part);
}
protected List<Transformation> getTransformations() {
return transformations;
}
private BlockPos pos = null;
private BlockPos getPos() {
return pos;
}
protected BlockPos getPosFromOrigin(BlockPos pos) {
return transform(pos).add(getPos());
}
void setPos(BlockPos pos) {
this.pos = pos;
}
}