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

179 lines
5.6 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 int getHeight();
protected abstract int getWidth();
protected abstract int getDepth();
protected abstract void build(StructureContext context);
private Vec3d getOffset() {
return new Vec3d(getWidth() / 2f, getHeight() / 2f, getDepth() / 2f);
}
private Vec3d transform(Vec3d pos) {
pos = pos.subtract(getOffset());
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) {
Vec3d offset = getOffset();
BlockPos offsetPos = new BlockPos(offset.getX(), offset.getY(), offset.getZ());
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()).add(offsetPos));
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;
}
}