Very Broken Structure Gen WIP
All checks were successful
EnergonRelics/pipeline/head This commit looks good

This commit is contained in:
TheBrokenRail 2020-07-19 15:12:39 -04:00
parent c938957dea
commit 6d51dee9c7
12 changed files with 527 additions and 12 deletions

View File

@ -1,6 +1,7 @@
package com.thebrokenrail.energonrelics;
import com.thebrokenrail.energonrelics.block.DefensiveLaserBlock;
import com.thebrokenrail.energonrelics.block.TestBlock;
import com.thebrokenrail.energonrelics.block.ThermalGlassBlock;
import com.thebrokenrail.energonrelics.block.battery.ActiveBatteryControllerBlock;
import com.thebrokenrail.energonrelics.block.reactor.ReactorControllerBlock;
@ -95,5 +96,7 @@ public class EnergonRelics implements ModInitializer {
Registry.register(Registry.ITEM, new Identifier(NAMESPACE, "defensive_laser_core"), DEFENSIVE_LASER_CORE_ITEM);
DEFENSIVE_LASER_BLOCK.register("defensive_laser");
new TestBlock().register("test_block");
}
}

View File

@ -0,0 +1,28 @@
package com.thebrokenrail.energonrelics.block;
import com.thebrokenrail.energonrelics.block.util.SimpleBlock;
import com.thebrokenrail.energonrelics.structure.StructurePlacer;
import com.thebrokenrail.energonrelics.structure.researchcomplex.ResearchComplexStartPart;
import com.thebrokenrail.energonrelics.structure.researchcomplex.ResearchComplexState;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
import net.minecraft.block.BlockState;
import net.minecraft.block.Material;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import java.util.Collections;
public class TestBlock extends SimpleBlock {
public TestBlock() {
super(FabricBlockSettings.of(Material.STONE));
}
@SuppressWarnings("deprecation")
@Override
public void onBlockAdded(BlockState state, World world, BlockPos pos, BlockState oldState, boolean notify) {
super.onBlockAdded(state, world, pos, oldState, notify);
if (!world.isClient()) {
new StructurePlacer(new ResearchComplexStartPart(new ResearchComplexState(world), Collections.emptyList())).place(world, pos);
}
}
}

View File

@ -49,16 +49,6 @@ public abstract class EnergyProviderBlock extends SimpleBlockWithEntity {
return HighlightBlockEntityRenderer::new;
}
private void setEnergyProviderSource(World world, BlockPos pos, ItemStack stack, boolean remove) {
ServerWorld serverWorld = (ServerWorld) world;
NetworkComponent component = NetworkComponent.getInstance(serverWorld);
if (remove) {
component.removeSource(EnergonRelics.NETWORK_CHIP_ITEM.getID(stack), pos);
} else {
component.addSource(EnergonRelics.NETWORK_CHIP_ITEM.getID(stack), pos);
}
}
@Override
@SuppressWarnings("deprecation")
public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) {
@ -68,7 +58,6 @@ public abstract class EnergyProviderBlock extends SimpleBlockWithEntity {
if (stack.getItem() == EnergonRelics.NETWORK_CHIP_ITEM) {
if (!((EnergyProviderBlockEntity) entity).hasStack()) {
if (!world.isClient()) {
setEnergyProviderSource(world, pos, stack, false);
((EnergyProviderBlockEntity) entity).placeStack(stack);
stack.setCount(0);
}
@ -81,7 +70,6 @@ public abstract class EnergyProviderBlock extends SimpleBlockWithEntity {
if (!world.isClient()) {
ItemStack newStack = ((EnergyProviderBlockEntity) entity).takeStack();
player.setStackInHand(hand, newStack);
setEnergyProviderSource(world, pos, newStack, true);
}
return ActionResult.SUCCESS;
} else {

View File

@ -16,6 +16,7 @@ import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.Tickable;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
import java.util.ArrayList;
import java.util.Collections;
@ -113,14 +114,26 @@ public class EnergyProviderBlockEntity extends BlockEntity implements EnergyProv
}
}
private static void setEnergyProviderSource(World world, BlockPos pos, ItemStack stack, boolean remove) {
ServerWorld serverWorld = (ServerWorld) world;
NetworkComponent component = NetworkComponent.getInstance(serverWorld);
if (remove) {
component.removeSource(EnergonRelics.NETWORK_CHIP_ITEM.getID(stack), pos);
} else {
component.addSource(EnergonRelics.NETWORK_CHIP_ITEM.getID(stack), pos);
}
}
public ItemStack takeStack() {
ItemStack newStack = stack.copy();
setEnergyProviderSource(getWorld(), getPos(), newStack, true);
stack = ItemStack.EMPTY;
markDirty();
return newStack;
}
public void placeStack(ItemStack newStack) {
setEnergyProviderSource(getWorld(), getPos(), newStack, false);
stack = newStack.copy();
markDirty();
}

View File

@ -49,6 +49,12 @@ public class NetworkChipItem extends Item {
return id;
}
public ItemStack create(int id) {
ItemStack stack = new ItemStack(this);
setID(stack, id);
return stack;
}
@Override
public void inventoryTick(ItemStack stack, World world, Entity entity, int slot, boolean selected) {
super.inventoryTick(stack, world, entity, slot, selected);

View File

@ -0,0 +1,5 @@
package com.thebrokenrail.energonrelics.structure;
public interface StructureContext {
void addPart(int x, int y, int z, StructurePart<?> part);
}

View File

@ -0,0 +1,178 @@
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;
}
}

View File

@ -0,0 +1,60 @@
package com.thebrokenrail.energonrelics.structure;
import net.minecraft.block.Blocks;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import java.util.ArrayList;
import java.util.List;
public class StructurePlacer {
private static class StructurePos {
private final int x;
private final int y;
private final int z;
private final StructurePart<?> part;
private StructurePos(int x, int y, int z, StructurePart<?> part) {
this.x = x;
this.y = y;
this.z = z;
this.part = part;
}
}
private final List<StructurePos> pendingParts = new ArrayList<>();
private final List<StructurePos> parts = new ArrayList<>();
public StructurePlacer(StructurePart<?> firstPart) {
pendingParts.add(new StructurePos(0, 0, 0, firstPart));
run();
}
private void run() {
while (!pendingParts.isEmpty()) {
List<StructurePos> newPendingParts = new ArrayList<>();
for (StructurePos part : pendingParts) {
if (part.part != null) {
part.part.build((x, y, z, newPart) -> {
newPendingParts.add(new StructurePos(x + part.x, y + part.y, z + part.z, null));
//newPendingParts.add(new StructurePos(x + part.x, y + part.y, z + part.z, newPart));
});
}
parts.add(part);
}
pendingParts.clear();
pendingParts.addAll(newPendingParts);
}
}
public void place(World world, BlockPos pos) {
for (StructurePos part : parts) {
BlockPos newPos = pos.add(part.x, part.y, part.z);
if (part.part != null) {
part.part.place(world, newPos);
} else {
world.setBlockState(newPos, Blocks.DIORITE.getDefaultState());
}
}
}
}

View File

@ -0,0 +1,27 @@
package com.thebrokenrail.energonrelics.structure.researchcomplex;
import com.thebrokenrail.energonrelics.EnergonRelics;
import com.thebrokenrail.energonrelics.block.entity.EnergonLightBlockEntity;
import com.thebrokenrail.energonrelics.structure.StructurePart;
import net.minecraft.block.BlockState;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import java.util.List;
public abstract class BaseResearchComplexPart extends StructurePart<ResearchComplexState> {
public BaseResearchComplexPart(ResearchComplexState state, List<Transformation> list) {
super(state, list);
}
@Override
protected void handleBlockPlace(World world, BlockPos pos, BlockState state) {
if (state.getBlock() == EnergonRelics.ENERGON_LIGHT_BLOCK) {
BlockEntity entity = world.getBlockEntity(pos);
if (entity instanceof EnergonLightBlockEntity) {
((EnergonLightBlockEntity) entity).toggle(getState().getMainNetwork());
}
}
}
}

View File

@ -0,0 +1,42 @@
package com.thebrokenrail.energonrelics.structure.researchcomplex;
import com.thebrokenrail.energonrelics.structure.StructureContext;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import java.util.List;
public class ResearchComplexHallwayPart extends BaseResearchComplexPart {
public ResearchComplexHallwayPart(ResearchComplexState state, List<Transformation> list) {
super(state, list);
}
@Override
protected int getWidth() {
return 7;
}
@Override
protected int getHeight() {
return 6;
}
@Override
protected int getDepth() {
return 3;
}
@Override
protected void build(StructureContext context) {
BlockState bricks = Blocks.QUARTZ_BRICKS.getDefaultState();
BlockState air = Blocks.AIR.getDefaultState();
for (int y = 0; y < getHeight(); y++) {
boolean isBricks = y == 0 || y == getHeight() - 1;
BlockState state = isBricks ? bricks : air;
rect(2, y, 0, 3, 1, getDepth(), state);
if (y > 1 && y < getHeight() - 2) {
rect(0, y, 0, 1, 2, getDepth(), bricks);
}
}
}
}

View File

@ -0,0 +1,130 @@
package com.thebrokenrail.energonrelics.structure.researchcomplex;
import com.thebrokenrail.energonrelics.EnergonRelics;
import com.thebrokenrail.energonrelics.block.entity.reactor.ReactorControllerBlockEntity;
import com.thebrokenrail.energonrelics.config.HardcodedConfig;
import com.thebrokenrail.energonrelics.structure.StructureContext;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.LeverBlock;
import net.minecraft.block.StairsBlock;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.block.enums.BlockHalf;
import net.minecraft.block.enums.StairShape;
import net.minecraft.block.enums.WallMountLocation;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.world.World;
import java.util.List;
public class ResearchComplexStartPart extends BaseResearchComplexPart {
public ResearchComplexStartPart(ResearchComplexState state, List<Transformation> list) {
super(state, list);
}
private void setBlockOrAir(int x, int y, int z, BlockState stairs) {
if (y == 1 || y == 4) {
set(x, y, z, stairs);
} else {
BlockState air = Blocks.AIR.getDefaultState();
set(x, y, z, air);
}
}
private void buildBase(int yOffset) {
BlockState bricks = Blocks.QUARTZ_BRICKS.getDefaultState();
BlockState air = Blocks.AIR.getDefaultState();
BlockState state = yOffset == 0 || yOffset == 5 ? bricks : air;
rect(4, yOffset, 0, 3, 1, getDepth(), state);
rect(0, yOffset, 4, getWidth(), 1, 3, state);
set(2, yOffset, 3, state);
set(3, yOffset, 2, state);
set(3, yOffset, 3, state);
if (yOffset != 0 && yOffset != 5) {
BlockState stairs = Blocks.QUARTZ_STAIRS.getDefaultState();
BlockHalf half = yOffset == 1 ? BlockHalf.BOTTOM : BlockHalf.TOP;
stairs = stairs.with(StairsBlock.HALF, half);
BlockState westStairs = stairs.with(StairsBlock.FACING, Direction.WEST);
BlockState northStairs = stairs.with(StairsBlock.FACING, Direction.NORTH);
BlockState outerLeftStairs = northStairs.with(StairsBlock.SHAPE, StairShape.OUTER_LEFT);
BlockState innerLeftStairs = northStairs.with(StairsBlock.SHAPE, StairShape.INNER_LEFT);
BlockState innerRightStairs = westStairs.with(StairsBlock.SHAPE, StairShape.INNER_RIGHT);
BlockState outerRightStairs = westStairs.with(StairsBlock.SHAPE, StairShape.OUTER_RIGHT);
setBlockOrAir(3, yOffset, 0, westStairs);
setBlockOrAir(3, yOffset, 1, outerLeftStairs);
setBlockOrAir(2, yOffset, 1, innerRightStairs);
setBlockOrAir(2, yOffset, 2, outerLeftStairs);
setBlockOrAir(1, yOffset, 2, innerLeftStairs);
setBlockOrAir(1, yOffset, 3, outerRightStairs);
setBlockOrAir(0, yOffset, 3, northStairs);
if (yOffset != 1 && yOffset != 4) {
set(2, yOffset, 0, bricks);
set(1, yOffset, 1, bricks);
set(0, yOffset, 2, bricks);
}
}
if (yOffset == 5) {
set(3, yOffset, 3, EnergonRelics.ENERGON_LIGHT_BLOCK.getDefaultState());
}
}
private void buildReactor() {
set(5, 1, 5, EnergonRelics.THERMAL_CASING_BLOCK.getDefaultState());
set(6, 2, 5, EnergonRelics.THERMAL_CASING_BLOCK.getDefaultState());
set(5, 2, 5, EnergonRelics.REACTOR_CORE_BLOCK.getDefaultState());
set(4, 2, 5, EnergonRelics.THERMAL_CASING_BLOCK.getDefaultState());
set(5, 3, 5, EnergonRelics.REACTOR_INPUT_BLOCK.getDefaultState());
set(5, 2, 4, EnergonRelics.REACTOR_CONTROLLER_BLOCK.getDefaultState());
set(5, 1, 4, Blocks.LEVER.getDefaultState().with(LeverBlock.FACE, WallMountLocation.FLOOR));
set(5, 2, 6, EnergonRelics.THERMAL_GLASS_BLOCK.getDefaultState());
}
@Override
protected void build(StructureContext context) {
if (getState().hasEnergy(HardcodedConfig.ENERGON_LIGHT_ENERGY_REQUIRED * 4)) {
repeat(() -> {
for (int i = 0; i < 6; i++) {
buildBase(i);
}
part(context, 1, 0, getDepth(), new ResearchComplexHallwayPart(getState(), getTransformations()));
});
buildReactor();
}
}
@Override
protected int getWidth() {
return 10;
}
@Override
protected int getHeight() {
return 6;
}
@Override
protected int getDepth() {
return 10;
}
@Override
protected void handleBlockPlace(World world, BlockPos pos, BlockState state) {
super.handleBlockPlace(world, pos, state);
if (state.getBlock() == EnergonRelics.REACTOR_CONTROLLER_BLOCK) {
BlockEntity entity = world.getBlockEntity(pos);
if (entity instanceof ReactorControllerBlockEntity) {
((ReactorControllerBlockEntity) entity).placeStack(EnergonRelics.NETWORK_CHIP_ITEM.create(getState().getMainNetwork()));
}
}
}
}

View File

@ -0,0 +1,35 @@
package com.thebrokenrail.energonrelics.structure.researchcomplex;
import com.thebrokenrail.energonrelics.component.NetworkComponent;
import com.thebrokenrail.energonrelics.config.HardcodedConfig;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.BlockRotation;
import net.minecraft.world.World;
public class ResearchComplexState {
private final int baseID;
private long energyBudget = HardcodedConfig.REACTOR_ENERGY_OUTPUT;
public ResearchComplexState(World world) {
ServerWorld serverWorld = (ServerWorld) world;
NetworkComponent component = NetworkComponent.getInstance(serverWorld);
baseID = component.create();
}
private int getID(int id) {
return baseID + id;
}
int getMainNetwork() {
return getID(0);
}
boolean hasEnergy(long amount) {
if (amount <= energyBudget) {
energyBudget = energyBudget - amount;
return true;
} else {
return false;
}
}
}