Skip to content

Commit

Permalink
Fixes #6505: Added back the crank boy. Allows crafting a meteorite co…
Browse files Browse the repository at this point in the history
…mpass without using other mods for power, since vibration chambers already need quartz to craft.
  • Loading branch information
shartte committed Sep 10, 2022
1 parent 8ff33e0 commit 843d1df
Show file tree
Hide file tree
Showing 17 changed files with 612 additions and 37 deletions.
2 changes: 2 additions & 0 deletions src/main/java/appeng/api/ids/AEBlockIds.java
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,8 @@ public final class AEBlockIds {
public static final ResourceLocation CHISELED_QUARTZ_SLAB = id("chiseled_quartz_slab");
public static final ResourceLocation QUARTZ_PILLAR_SLAB = id("quartz_pillar_slab");

public static final ResourceLocation CRANK = id("crank");

private static ResourceLocation id(String id) {
return new ResourceLocation(AEConstants.MOD_ID, id);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2013 AlgorithmX2
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

package appeng.api.implementations.blockentities;

import org.jetbrains.annotations.Nullable;

import net.fabricmc.fabric.api.lookup.v1.block.BlockApiLookup;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.world.level.Level;

import appeng.core.AppEng;

/**
* Crank/Crankable API,
* <p>
* Blocks that expose this interface via Api lookup can receive power from the crank. A block can return this interface
* only on specific sides to control where it can attach to.
* <p>
* Cranks obtain this interface from a block using {@link #LOOKUP}.
*/
public interface ICrankable {
BlockApiLookup<ICrankable, Direction> LOOKUP = BlockApiLookup.get(AppEng.makeId("crankable"),
ICrankable.class, Direction.class);

/**
* Test if the crank can turn, return false if there is no work to be done.
*
* @return if crank should be allowed to turn on the given side.
*/
boolean canTurn();

/**
* The crank has completed one turn on the given side.
*/
void applyTurn();

@Nullable
static ICrankable get(Level level, BlockPos pos, Direction side) {
return LOOKUP.find(level, pos, null, null, side);
}
}
171 changes: 171 additions & 0 deletions src/main/java/appeng/block/grindstone/CrankBlock.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/

package appeng.block.grindstone;

import org.jetbrains.annotations.Nullable;

import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.RenderShape;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.phys.shapes.VoxelShape;

import appeng.api.implementations.blockentities.ICrankable;
import appeng.block.AEBaseEntityBlock;
import appeng.tile.grindstone.CrankBlockEntity;
import appeng.util.FakePlayer;

public class CrankBlock extends AEBaseEntityBlock<CrankBlockEntity> {

public CrankBlock(Properties props) {
super(props);
}

@Override
public InteractionResult onActivated(Level level, BlockPos pos, Player player, InteractionHand hand,
@Nullable ItemStack heldItem, BlockHitResult hit) {
if (player instanceof FakePlayer || player == null) {
this.dropCrank(level, pos);
return InteractionResult.sidedSuccess(level.isClientSide());
}

var crank = this.getBlockEntity(level, pos);
if (crank != null) {
crank.power();
return InteractionResult.sidedSuccess(level.isClientSide());
}

return InteractionResult.PASS;
}

private void dropCrank(Level level, BlockPos pos) {
level.destroyBlock(pos, true);
level.sendBlockUpdated(pos, defaultBlockState(), level.getBlockState(pos), 3);
}

@Override
public void setPlacedBy(Level level, BlockPos pos, BlockState state, LivingEntity placer, ItemStack is) {
super.setPlacedBy(level, pos, state, placer, is);

var be = getBlockEntity(level, pos);
if (be != null) {
var mnt = this.findCrankableDirection(level, pos);
if (mnt == null) {
dropCrank(level, pos);
return;
}

Direction forward = Direction.UP;
if (mnt == Direction.UP || mnt == Direction.DOWN) {
forward = Direction.SOUTH;
}
be.setOrientation(forward, mnt.getOpposite());
} else {
dropCrank(level, pos);
}
}

@Override
protected boolean isValidOrientation(LevelAccessor levelAccessor, BlockPos pos, Direction forward, Direction up) {
if (levelAccessor instanceof Level level) {
var be = level.getBlockEntity(pos);
return !(be instanceof CrankBlockEntity) || isCrankable(level, pos, up.getOpposite());
} else {
return true;
}
}

private Direction findCrankableDirection(Level level, BlockPos pos) {
for (var dir : Direction.values()) {
if (isCrankable(level, pos, dir)) {
return dir;
}
}
return null;
}

private boolean isCrankable(Level level, BlockPos pos, Direction offset) {
var o = pos.relative(offset);
return ICrankable.get(level, o, offset.getOpposite()) != null;
}

@SuppressWarnings("deprecation")
@Override
public RenderShape getRenderShape(BlockState state) {
return RenderShape.ENTITYBLOCK_ANIMATED;
}

@Override
public void neighborChanged(BlockState state, Level level, BlockPos pos, Block blockIn, BlockPos fromPos,
boolean isMoving) {
var be = this.getBlockEntity(level, pos);
if (be != null) {
if (!isCrankable(level, pos, be.getUp().getOpposite())) {
dropCrank(level, pos);
}
} else {
dropCrank(level, pos);
}
}

@Override
public boolean canSurvive(BlockState state, LevelReader levelReader, BlockPos pos) {
if (levelReader instanceof Level level) {
return findCrankableDirection(level, pos) != null;
} else {
return true;
}
}

private Direction getUp(BlockGetter level, BlockPos pos) {
var crank = getBlockEntity(level, pos);
return crank != null ? crank.getUp() : null;
}

@Override
public VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) {
Direction up = getUp(level, pos);

if (up == null) {
return Shapes.empty();
} else {
// FIXME: Cache per direction, and build it 'precise', not just from AABB
final double xOff = -0.15 * up.getStepX();
final double yOff = -0.15 * up.getStepY();
final double zOff = -0.15 * up.getStepZ();
return Shapes.create(
new AABB(xOff + 0.15, yOff + 0.15, zOff + 0.15, xOff + 0.85, yOff + 0.85, zOff + 0.85));
}

}
}
29 changes: 28 additions & 1 deletion src/main/java/appeng/blockentity/misc/ChargerBlockEntity.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
import java.util.List;
import java.util.Objects;

import org.jetbrains.annotations.Nullable;

import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.network.FriendlyByteBuf;
Expand All @@ -34,6 +36,7 @@
import appeng.api.config.Actionable;
import appeng.api.config.PowerMultiplier;
import appeng.api.config.PowerUnits;
import appeng.api.implementations.blockentities.ICrankable;
import appeng.api.implementations.items.IAEItemPowerStorage;
import appeng.api.inventories.InternalInventory;
import appeng.api.networking.IGridNode;
Expand All @@ -52,7 +55,7 @@

public class ChargerBlockEntity extends AENetworkPowerBlockEntity implements IGridTickable {
// TODO: show recipes in JEI/REI

private static final int POWER_PER_CRANK_TURN = 160;
private static final int POWER_MAXIMUM_AMOUNT = 1600;
private static final int POWER_THRESHOLD = POWER_MAXIMUM_AMOUNT - 1;
private boolean working;
Expand Down Expand Up @@ -240,6 +243,18 @@ public boolean isWorking() {
return working;
}

/**
* Allow cranking from the top or bottom.
*/
@Nullable
public ICrankable getCrankable(Direction direction) {
var up = getUp();
if (direction == up || direction == up.getOpposite()) {
return new Crankable();
}
return null;
}

private record ChargerInvFilter(ChargerBlockEntity chargerBlockEntity) implements IAEItemFilter {

@Override
Expand All @@ -261,4 +276,16 @@ public boolean allowExtract(InternalInventory inv, int slotIndex, int amount) {
return ChargerRecipes.allowExtract(chargerBlockEntity.level, extractedItem);
}
}

class Crankable implements ICrankable {
@Override
public boolean canTurn() {
return getInternalCurrentPower() < getInternalMaxPower();
}

@Override
public void applyTurn() {
injectExternalPower(PowerUnits.AE, POWER_PER_CRANK_TURN, Actionable.MODULATE);
}
}
}
74 changes: 74 additions & 0 deletions src/main/java/appeng/client/render/tesr/CrankRenderer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/

package appeng.client.render.tesr;

import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.math.Quaternion;

import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.block.BlockRenderDispatcher;
import net.minecraft.client.renderer.blockentity.BlockEntityRenderer;
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider;
import net.minecraft.util.RandomSource;

import appeng.client.render.FacingToRotation;
import appeng.tile.grindstone.CrankBlockEntity;

@Environment(EnvType.CLIENT)
public class CrankRenderer implements BlockEntityRenderer<CrankBlockEntity> {

private final BlockRenderDispatcher blockRenderer;

public CrankRenderer(BlockEntityRendererProvider.Context context) {
this.blockRenderer = context.getBlockRenderDispatcher();
}

@Override
public void render(CrankBlockEntity crank, float partialTick, PoseStack stack, MultiBufferSource buffers,
int packedLight, int packedOverlay) {

// Apply GL transformations relative to the center of the block: 1) TE rotation
// and 2) crank rotation
stack.pushPose();
stack.translate(0.5, 0.5, 0.5);
FacingToRotation.get(crank.getForward(), crank.getUp()).push(stack);
stack.mulPose(new Quaternion(0, crank.getVisibleRotation(), 0, true));
stack.translate(-0.5, -0.5, -0.5);

var blockState = crank.getBlockState();
var model = blockRenderer.getBlockModel(blockState);
var buffer = buffers.getBuffer(RenderType.cutout());
var pos = crank.getBlockPos();
blockRenderer.getModelRenderer().tesselateWithAO(
crank.getLevel(),
model,
blockState,
pos,
stack,
buffer,
false,
RandomSource.create(),
blockState.getSeed(pos),
packedOverlay);
stack.popPose();
}
}
4 changes: 4 additions & 0 deletions src/main/java/appeng/core/definitions/AEBlockEntities.java
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@
import appeng.debug.EnergyGeneratorBlockEntity;
import appeng.debug.ItemGenBlockEntity;
import appeng.debug.PhantomNodeBlockEntity;
import appeng.tile.grindstone.CrankBlockEntity;

@SuppressWarnings("unused")
public final class AEBlockEntities {
Expand Down Expand Up @@ -169,6 +170,9 @@ public final class AEBlockEntities {
public static final BlockEntityType<EnergyGeneratorBlockEntity> DEBUG_ENERGY_GEN = create("debug_energy_gen",
EnergyGeneratorBlockEntity.class, EnergyGeneratorBlockEntity::new, AEBlocks.DEBUG_ENERGY_GEN);

public static final BlockEntityType<CrankBlockEntity> CRANK = create("crank", CrankBlockEntity.class,
CrankBlockEntity::new, AEBlocks.CRANK);

private AEBlockEntities() {
}

Expand Down
Loading

0 comments on commit 843d1df

Please sign in to comment.