Merge pull request #40 from thedarkcolour/mechanical-hammer
Mechanical hammer
|
|
@ -1,4 +1,4 @@
|
||||||
// 1.20.1 2024-01-10T20:18:25.7260241 Loot Tables
|
// 1.20.1 2024-01-25T14:16:46.237861 Loot Tables
|
||||||
105d8a61ea7145d7798146d385d4aad24fd1588d data/exdeorum/loot_tables/blocks/acacia_barrel.json
|
105d8a61ea7145d7798146d385d4aad24fd1588d data/exdeorum/loot_tables/blocks/acacia_barrel.json
|
||||||
1e77127a82cbba0937bb02694f65cf1893aeffcb data/exdeorum/loot_tables/blocks/acacia_crucible.json
|
1e77127a82cbba0937bb02694f65cf1893aeffcb data/exdeorum/loot_tables/blocks/acacia_crucible.json
|
||||||
fcc00910a8cc94bed6339d6833fcec53c501a0d7 data/exdeorum/loot_tables/blocks/acacia_sieve.json
|
fcc00910a8cc94bed6339d6833fcec53c501a0d7 data/exdeorum/loot_tables/blocks/acacia_sieve.json
|
||||||
|
|
@ -73,6 +73,7 @@ b38104ee25127d9c65ad9e323ed879f76df7a048 data/exdeorum/loot_tables/blocks/mangro
|
||||||
475b89fd8f09834652f80c93d8a6d0964d708ead data/exdeorum/loot_tables/blocks/maple_barrel.json
|
475b89fd8f09834652f80c93d8a6d0964d708ead data/exdeorum/loot_tables/blocks/maple_barrel.json
|
||||||
54f36187d7fb97dedc4680d14e2ad7d70b5c64af data/exdeorum/loot_tables/blocks/maple_crucible.json
|
54f36187d7fb97dedc4680d14e2ad7d70b5c64af data/exdeorum/loot_tables/blocks/maple_crucible.json
|
||||||
7ffe80360af055f3977d05b5684a299886bcb756 data/exdeorum/loot_tables/blocks/maple_sieve.json
|
7ffe80360af055f3977d05b5684a299886bcb756 data/exdeorum/loot_tables/blocks/maple_sieve.json
|
||||||
|
926a9224e747bf53eb81448c1abb55d73fce5092 data/exdeorum/loot_tables/blocks/mechanical_hammer.json
|
||||||
a84508222cb36b07cb20ee31915d802bcc411149 data/exdeorum/loot_tables/blocks/mechanical_sieve.json
|
a84508222cb36b07cb20ee31915d802bcc411149 data/exdeorum/loot_tables/blocks/mechanical_sieve.json
|
||||||
cad973c873a2e50ccfac91e88eadb3c2462d39d1 data/exdeorum/loot_tables/blocks/oak_barrel.json
|
cad973c873a2e50ccfac91e88eadb3c2462d39d1 data/exdeorum/loot_tables/blocks/oak_barrel.json
|
||||||
f94bc97efbfd26ccf7dba32d414fb5e33decd5f6 data/exdeorum/loot_tables/blocks/oak_crucible.json
|
f94bc97efbfd26ccf7dba32d414fb5e33decd5f6 data/exdeorum/loot_tables/blocks/oak_crucible.json
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1,2 @@
|
||||||
// 1.20.1 2024-01-26T16:29:51.8613552 ModKit Language: en_us for mod 'exdeorum'
|
// 1.20.1 2024-01-25T14:16:46.2316734 ModKit Language: en_us for mod 'exdeorum'
|
||||||
2f38e208308fb2a7f506e2ce2b400970d1c27b57 assets/exdeorum/lang/en_us.json
|
248ab1a837b9857fb1928e826cb02f9f142e8d96 assets/exdeorum/lang/en_us.json
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// 1.20.1 2024-01-10T20:18:25.7240245 ModKit Item Models for mod 'exdeorum'
|
// 1.20.1 2024-01-25T14:16:46.2347562 ModKit Item Models for mod 'exdeorum'
|
||||||
4ba3bb2c6174ac3728a4b85e34681f118ec8eb34 assets/exdeorum/models/item/acacia_barrel.json
|
4ba3bb2c6174ac3728a4b85e34681f118ec8eb34 assets/exdeorum/models/item/acacia_barrel.json
|
||||||
c03ce41f7c071498fcbd5f5225e91dcb2f365fbb assets/exdeorum/models/item/acacia_crucible.json
|
c03ce41f7c071498fcbd5f5225e91dcb2f365fbb assets/exdeorum/models/item/acacia_crucible.json
|
||||||
3b4f1d45c0d9c4cd1d9a5cdf6ddc8d2c9791bca5 assets/exdeorum/models/item/acacia_sieve.json
|
3b4f1d45c0d9c4cd1d9a5cdf6ddc8d2c9791bca5 assets/exdeorum/models/item/acacia_sieve.json
|
||||||
|
|
@ -105,6 +105,7 @@ ff89dc05408074da0e9d41bfef91dfe975302403 assets/exdeorum/models/item/mahogany_cr
|
||||||
c3f2af2a88cd97148b05efbd6e24fc2558fcc0b8 assets/exdeorum/models/item/maple_barrel.json
|
c3f2af2a88cd97148b05efbd6e24fc2558fcc0b8 assets/exdeorum/models/item/maple_barrel.json
|
||||||
cc045825c562e9133858ce5cfe6e6f1dcb747d8e assets/exdeorum/models/item/maple_crucible.json
|
cc045825c562e9133858ce5cfe6e6f1dcb747d8e assets/exdeorum/models/item/maple_crucible.json
|
||||||
a64e9b9ce91ac6b2f36690a770afc52b8900a614 assets/exdeorum/models/item/maple_sieve.json
|
a64e9b9ce91ac6b2f36690a770afc52b8900a614 assets/exdeorum/models/item/maple_sieve.json
|
||||||
|
59cdfe2c26f9d4a16ab7e8e7a87c97403eafa562 assets/exdeorum/models/item/mechanical_hammer.json
|
||||||
1e2b482f5fc4d283f5ca12919b575f86dc4a9541 assets/exdeorum/models/item/mechanical_sieve.json
|
1e2b482f5fc4d283f5ca12919b575f86dc4a9541 assets/exdeorum/models/item/mechanical_sieve.json
|
||||||
d543d3e18bdcf2bf79a762b52cc61a4161124db1 assets/exdeorum/models/item/mycelium_spores.json
|
d543d3e18bdcf2bf79a762b52cc61a4161124db1 assets/exdeorum/models/item/mycelium_spores.json
|
||||||
1f48b2ce3452ce5d02142c9f663ae7bdb7d1d934 assets/exdeorum/models/item/netherite_hammer.json
|
1f48b2ce3452ce5d02142c9f663ae7bdb7d1d934 assets/exdeorum/models/item/netherite_hammer.json
|
||||||
|
|
|
||||||
|
|
@ -84,6 +84,7 @@
|
||||||
"block.exdeorum.maple_barrel": "Maple Barrel",
|
"block.exdeorum.maple_barrel": "Maple Barrel",
|
||||||
"block.exdeorum.maple_crucible": "Maple Crucible",
|
"block.exdeorum.maple_crucible": "Maple Crucible",
|
||||||
"block.exdeorum.maple_sieve": "Maple Sieve",
|
"block.exdeorum.maple_sieve": "Maple Sieve",
|
||||||
|
"block.exdeorum.mechanical_hammer": "Mechanical Hammer",
|
||||||
"block.exdeorum.mechanical_sieve": "Mechanical Sieve",
|
"block.exdeorum.mechanical_sieve": "Mechanical Sieve",
|
||||||
"block.exdeorum.oak_barrel": "Oak Barrel",
|
"block.exdeorum.oak_barrel": "Oak Barrel",
|
||||||
"block.exdeorum.oak_crucible": "Oak Crucible",
|
"block.exdeorum.oak_crucible": "Oak Crucible",
|
||||||
|
|
@ -118,6 +119,7 @@
|
||||||
"block.exdeorum.willow_crucible": "Willow Crucible",
|
"block.exdeorum.willow_crucible": "Willow Crucible",
|
||||||
"block.exdeorum.willow_sieve": "Willow Sieve",
|
"block.exdeorum.willow_sieve": "Willow Sieve",
|
||||||
"block.exdeorum.witch_water": "Witch Water",
|
"block.exdeorum.witch_water": "Witch Water",
|
||||||
|
"exdeorum.container.mechanical_hammer": "Mechanical Hammer",
|
||||||
"exdeorum.container.mechanical_sieve": "Mechanical Sieve",
|
"exdeorum.container.mechanical_sieve": "Mechanical Sieve",
|
||||||
"fluid_type.exdeorum.witch_water": "Witch Water",
|
"fluid_type.exdeorum.witch_water": "Witch Water",
|
||||||
"generator.exdeorum.void_world": "Void World",
|
"generator.exdeorum.void_world": "Void World",
|
||||||
|
|
@ -145,6 +147,7 @@
|
||||||
"gui.exdeorum.redstone_control.unpowered": "Unpowered",
|
"gui.exdeorum.redstone_control.unpowered": "Unpowered",
|
||||||
"info.exdeorum.crimson_nylium_spores": "Use on netherrack to turn it into a crimson nylium block.",
|
"info.exdeorum.crimson_nylium_spores": "Use on netherrack to turn it into a crimson nylium block.",
|
||||||
"info.exdeorum.grass_seeds": "Use on dirt to turn it into a grass block.",
|
"info.exdeorum.grass_seeds": "Use on dirt to turn it into a grass block.",
|
||||||
|
"info.exdeorum.mechanical_hammer": "The Mechanical Hammer is a machine that, when supplied with Forge Energy (FE), will hammer blocks without a player having to do it themselves. It can operate without a hammer, but adding any hammer will double the speed, and efficiency enchantments on the hammer will further increase speed. It also supports three different modes of redstone control. Since Ex Deorum does not provide a way to generate FE, you will need another mod to provide power.",
|
||||||
"info.exdeorum.mechanical_sieve": "The Mechanical Sieve is a machine that, when supplied with a mesh and Forge Energy (FE), will sift blocks without a player having to do it themselves. It also supports three different modes of redstone control. Since Ex Deorum does not provide a way to generate FE, you will need another mod to provide power.",
|
"info.exdeorum.mechanical_sieve": "The Mechanical Sieve is a machine that, when supplied with a mesh and Forge Energy (FE), will sift blocks without a player having to do it themselves. It also supports three different modes of redstone control. Since Ex Deorum does not provide a way to generate FE, you will need another mod to provide power.",
|
||||||
"info.exdeorum.mycelium_spores": "Use on dirt to turn it into mycelium.",
|
"info.exdeorum.mycelium_spores": "Use on dirt to turn it into mycelium.",
|
||||||
"info.exdeorum.sculk_core": "Use a sculk core on a Sculk Shrieker to enable it to spawn Wardens. Normally, Sculk Shriekers placed by players cannot spawn Wardens, so this item is useful for obtaining Sculk items in a SkyBlock world.",
|
"info.exdeorum.sculk_core": "Use a sculk core on a Sculk Shrieker to enable it to spawn Wardens. Normally, Sculk Shriekers placed by players cannot spawn Wardens, so this item is useful for obtaining Sculk items in a SkyBlock world.",
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"parent": "exdeorum:block/mechanical_hammer_off"
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
{
|
||||||
|
"parent": "minecraft:recipes/root",
|
||||||
|
"criteria": {
|
||||||
|
"has_item": {
|
||||||
|
"conditions": {
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"items": [
|
||||||
|
"minecraft:hopper"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"trigger": "minecraft:inventory_changed"
|
||||||
|
},
|
||||||
|
"has_the_recipe": {
|
||||||
|
"conditions": {
|
||||||
|
"recipe": "exdeorum:mechanical_hammer"
|
||||||
|
},
|
||||||
|
"trigger": "minecraft:recipe_unlocked"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"requirements": [
|
||||||
|
[
|
||||||
|
"has_item",
|
||||||
|
"has_the_recipe"
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"rewards": {
|
||||||
|
"recipes": [
|
||||||
|
"exdeorum:mechanical_hammer"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"sends_telemetry_event": true
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
{
|
||||||
|
"type": "minecraft:block",
|
||||||
|
"pools": [
|
||||||
|
{
|
||||||
|
"bonus_rolls": 0.0,
|
||||||
|
"conditions": [
|
||||||
|
{
|
||||||
|
"condition": "minecraft:survives_explosion"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"entries": [
|
||||||
|
{
|
||||||
|
"type": "minecraft:item",
|
||||||
|
"functions": [
|
||||||
|
{
|
||||||
|
"function": "exdeorum:machine"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "exdeorum:mechanical_hammer"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"rolls": 1.0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"random_sequence": "exdeorum:blocks/mechanical_hammer"
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
{
|
||||||
|
"type": "minecraft:crafting_shaped",
|
||||||
|
"category": "misc",
|
||||||
|
"key": {
|
||||||
|
"#": {
|
||||||
|
"item": "minecraft:iron_block"
|
||||||
|
},
|
||||||
|
"H": {
|
||||||
|
"item": "minecraft:hopper"
|
||||||
|
},
|
||||||
|
"I": {
|
||||||
|
"item": "minecraft:iron_ingot"
|
||||||
|
},
|
||||||
|
"T": {
|
||||||
|
"tag": "exdeorum:hammers"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"pattern": [
|
||||||
|
"III",
|
||||||
|
"ITI",
|
||||||
|
"#H#"
|
||||||
|
],
|
||||||
|
"result": {
|
||||||
|
"item": "exdeorum:mechanical_hammer"
|
||||||
|
},
|
||||||
|
"show_notification": true
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,133 @@
|
||||||
|
/*
|
||||||
|
* Ex Deorum
|
||||||
|
* Copyright (c) 2024 thedarkcolour
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program 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 General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package thedarkcolour.exdeorum.block;
|
||||||
|
|
||||||
|
import net.minecraft.ChatFormatting;
|
||||||
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.network.chat.Component;
|
||||||
|
import net.minecraft.world.entity.item.ItemEntity;
|
||||||
|
import net.minecraft.world.entity.player.Player;
|
||||||
|
import net.minecraft.world.item.BlockItem;
|
||||||
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
import net.minecraft.world.item.TooltipFlag;
|
||||||
|
import net.minecraft.world.item.context.BlockPlaceContext;
|
||||||
|
import net.minecraft.world.level.BlockGetter;
|
||||||
|
import net.minecraft.world.level.GameRules;
|
||||||
|
import net.minecraft.world.level.Level;
|
||||||
|
import net.minecraft.world.level.block.Block;
|
||||||
|
import net.minecraft.world.level.block.HorizontalDirectionalBlock;
|
||||||
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
|
import net.minecraft.world.level.block.entity.BlockEntityTicker;
|
||||||
|
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||||
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
|
import net.minecraft.world.level.block.state.StateDefinition;
|
||||||
|
import net.minecraft.world.level.block.state.properties.BooleanProperty;
|
||||||
|
import net.minecraft.world.level.block.state.properties.DirectionProperty;
|
||||||
|
import net.minecraftforge.items.ItemStackHandler;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import thedarkcolour.exdeorum.blockentity.MechanicalHammerBlockEntity;
|
||||||
|
import thedarkcolour.exdeorum.blockentity.MechanicalSieveBlockEntity;
|
||||||
|
import thedarkcolour.exdeorum.config.EConfig;
|
||||||
|
import thedarkcolour.exdeorum.data.TranslationKeys;
|
||||||
|
import thedarkcolour.exdeorum.registry.EBlockEntities;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class MechanicalHammerBlock extends EBlock {
|
||||||
|
public static final BooleanProperty RUNNING = BooleanProperty.create("running");
|
||||||
|
public static final DirectionProperty FACING = HorizontalDirectionalBlock.FACING;
|
||||||
|
|
||||||
|
public MechanicalHammerBlock(Properties properties) {
|
||||||
|
super(properties, EBlockEntities.MECHANICAL_HAMMER);
|
||||||
|
|
||||||
|
registerDefaultState(defaultBlockState().setValue(RUNNING, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
|
||||||
|
builder.add(RUNNING, FACING);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public <T extends BlockEntity> BlockEntityTicker<T> getTicker(Level level, BlockState state, BlockEntityType<T> type) {
|
||||||
|
return type == EBlockEntities.MECHANICAL_HAMMER.get() && !level.isClientSide ? (BlockEntityTicker<T>) new MechanicalHammerBlockEntity.ServerTicker<>() : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void appendHoverText(ItemStack stack, @Nullable BlockGetter level, List<Component> tooltip, TooltipFlag flag) {
|
||||||
|
var nbt = BlockItem.getBlockEntityData(stack);
|
||||||
|
if (nbt != null) {
|
||||||
|
var inventoryNbt = nbt.getCompound("inventory");
|
||||||
|
var inventory = new ItemStackHandler();
|
||||||
|
inventory.deserializeNBT(inventoryNbt);
|
||||||
|
var hammer = inventory.getStackInSlot(MechanicalHammerBlockEntity.HAMMER_SLOT);
|
||||||
|
if (!hammer.isEmpty()) {
|
||||||
|
tooltip.add(Component.translatable(TranslationKeys.MECHANICAL_HAMMER_HAMMER_LABEL).withStyle(ChatFormatting.GRAY).append(Component.translatable(hammer.getDescriptionId())));
|
||||||
|
}
|
||||||
|
var energy = nbt.getInt("energy");
|
||||||
|
tooltip.add(Component.translatable(TranslationKeys.ENERGY).withStyle(ChatFormatting.GRAY).append(Component.translatable(TranslationKeys.FRACTION_DISPLAY, energy, EConfig.SERVER.mechanicalSieveEnergyStorage.get())).append(" FE"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void playerWillDestroy(Level level, BlockPos pos, BlockState pState, Player player) {
|
||||||
|
if (!level.isClientSide && player.isCreative() && level.getGameRules().getBoolean(GameRules.RULE_DOBLOCKDROPS)) {
|
||||||
|
if (level.getBlockEntity(pos) instanceof MechanicalHammerBlockEntity sieve) {
|
||||||
|
if (!sieve.inventory.getStackInSlot(MechanicalHammerBlockEntity.HAMMER_SLOT).isEmpty()) {
|
||||||
|
var stack = new ItemStack(this);
|
||||||
|
BlockItem.setBlockEntityData(stack, EBlockEntities.MECHANICAL_HAMMER.get(), sieve.saveWithoutMetadata());
|
||||||
|
var itemEntity = new ItemEntity(level, pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5, stack);
|
||||||
|
itemEntity.setDefaultPickUpDelay();
|
||||||
|
level.addFreshEntity(itemEntity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
super.playerWillDestroy(level, pos, pState, player);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlockState getStateForPlacement(BlockPlaceContext context) {
|
||||||
|
var nbt = BlockItem.getBlockEntityData(context.getItemInHand());
|
||||||
|
var state = defaultBlockState();
|
||||||
|
if (nbt != null && nbt.contains("progress") && nbt.getInt("progress") != MechanicalHammerBlockEntity.NOT_RUNNING) {
|
||||||
|
state = state.setValue(RUNNING, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return state.setValue(FACING, context.getHorizontalDirection().getOpposite());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPlace(BlockState state, Level level, BlockPos pos, BlockState oldState, boolean isMoving) {
|
||||||
|
if (!oldState.is(state.getBlock())) {
|
||||||
|
if (level.getBlockEntity(pos) instanceof MechanicalHammerBlockEntity hammer) {
|
||||||
|
hammer.checkPoweredState(level, pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void neighborChanged(BlockState state, Level level, BlockPos pos, Block block, BlockPos fromPos, boolean isMoving) {
|
||||||
|
if (level.getBlockEntity(pos) instanceof MechanicalHammerBlockEntity hammer) {
|
||||||
|
hammer.checkPoweredState(level, pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -69,7 +69,7 @@ public class MechanicalSieveBlock extends EBlock {
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public <T extends BlockEntity> BlockEntityTicker<T> getTicker(Level level, BlockState pState, BlockEntityType<T> type) {
|
public <T extends BlockEntity> BlockEntityTicker<T> getTicker(Level level, BlockState pState, BlockEntityType<T> type) {
|
||||||
return type == EBlockEntities.MECHANICAL_SIEVE.get() && !level.isClientSide ? (BlockEntityTicker<T>) new MechanicalSieveBlockEntity.ServerTicker() : null;
|
return type == EBlockEntities.MECHANICAL_SIEVE.get() && !level.isClientSide ? (BlockEntityTicker<T>) new MechanicalSieveBlockEntity.ServerTicker<>() : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -93,7 +93,7 @@ public class MechanicalSieveBlock extends EBlock {
|
||||||
public void playerWillDestroy(Level level, BlockPos pos, BlockState pState, Player player) {
|
public void playerWillDestroy(Level level, BlockPos pos, BlockState pState, Player player) {
|
||||||
if (!level.isClientSide && player.isCreative() && level.getGameRules().getBoolean(GameRules.RULE_DOBLOCKDROPS)) {
|
if (!level.isClientSide && player.isCreative() && level.getGameRules().getBoolean(GameRules.RULE_DOBLOCKDROPS)) {
|
||||||
if (level.getBlockEntity(pos) instanceof MechanicalSieveBlockEntity sieve) {
|
if (level.getBlockEntity(pos) instanceof MechanicalSieveBlockEntity sieve) {
|
||||||
if (!sieve.getMesh().isEmpty()) {
|
if (!sieve.getLogic().getMesh().isEmpty()) {
|
||||||
var stack = new ItemStack(this);
|
var stack = new ItemStack(this);
|
||||||
BlockItem.setBlockEntityData(stack, EBlockEntities.MECHANICAL_SIEVE.get(), sieve.saveWithoutMetadata());
|
BlockItem.setBlockEntityData(stack, EBlockEntities.MECHANICAL_SIEVE.get(), sieve.saveWithoutMetadata());
|
||||||
var itemEntity = new ItemEntity(level, pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5, stack);
|
var itemEntity = new ItemEntity(level, pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5, stack);
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,7 @@ public class SieveBlock extends EBlock {
|
||||||
if (!level.isClientSide) {
|
if (!level.isClientSide) {
|
||||||
if (!state.is(newState.getBlock())) {
|
if (!state.is(newState.getBlock())) {
|
||||||
if (level.getBlockEntity(pos) instanceof SieveBlockEntity sieve) {
|
if (level.getBlockEntity(pos) instanceof SieveBlockEntity sieve) {
|
||||||
var mesh = sieve.getMesh();
|
var mesh = sieve.getLogic().getMesh();
|
||||||
|
|
||||||
if (!mesh.isEmpty()) {
|
if (!mesh.isEmpty()) {
|
||||||
dropItem(level, pos, mesh);
|
dropItem(level, pos, mesh);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,174 @@
|
||||||
|
/*
|
||||||
|
* Ex Deorum
|
||||||
|
* Copyright (c) 2024 thedarkcolour
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program 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 General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package thedarkcolour.exdeorum.blockentity;
|
||||||
|
|
||||||
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.core.Direction;
|
||||||
|
import net.minecraft.nbt.CompoundTag;
|
||||||
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
|
import net.minecraft.util.Mth;
|
||||||
|
import net.minecraft.world.InteractionHand;
|
||||||
|
import net.minecraft.world.InteractionResult;
|
||||||
|
import net.minecraft.world.MenuProvider;
|
||||||
|
import net.minecraft.world.entity.player.Player;
|
||||||
|
import net.minecraft.world.level.Level;
|
||||||
|
import net.minecraft.world.level.block.entity.BlockEntityTicker;
|
||||||
|
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||||
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
|
import net.minecraftforge.common.capabilities.Capability;
|
||||||
|
import net.minecraftforge.common.capabilities.ForgeCapabilities;
|
||||||
|
import net.minecraftforge.common.util.LazyOptional;
|
||||||
|
import net.minecraftforge.energy.EnergyStorage;
|
||||||
|
import net.minecraftforge.network.NetworkHooks;
|
||||||
|
import thedarkcolour.exdeorum.blockentity.helper.EnergyHelper;
|
||||||
|
import thedarkcolour.exdeorum.blockentity.helper.ItemHelper;
|
||||||
|
import thedarkcolour.exdeorum.client.screen.RedstoneControlWidget;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
public abstract class AbstractMachineBlockEntity<M extends AbstractMachineBlockEntity<M>> extends EBlockEntity implements MenuProvider {
|
||||||
|
public final ItemHelper inventory;
|
||||||
|
public final EnergyHelper energy;
|
||||||
|
protected int redstoneMode;
|
||||||
|
// not saved to NBT
|
||||||
|
protected boolean hasRedstonePower;
|
||||||
|
|
||||||
|
private final LazyOptional<ItemHelper> capabilityInventory;
|
||||||
|
private final LazyOptional<EnergyStorage> capabilityEnergy;
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public AbstractMachineBlockEntity(BlockEntityType<?> type, BlockPos pos, BlockState state, Function<M, ItemHelper> inventory, int maxEnergy) {
|
||||||
|
super(type, pos, state);
|
||||||
|
|
||||||
|
this.inventory = inventory.apply((M) this);
|
||||||
|
this.energy = new EnergyHelper(maxEnergy);
|
||||||
|
|
||||||
|
this.capabilityInventory = LazyOptional.of(() -> this.inventory);
|
||||||
|
this.capabilityEnergy = LazyOptional.of(() -> this.energy);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void saveAdditional(CompoundTag nbt) {
|
||||||
|
super.saveAdditional(nbt);
|
||||||
|
|
||||||
|
nbt.put("inventory", this.inventory.serializeNBT());
|
||||||
|
nbt.putInt("energy", this.energy.getEnergyStored());
|
||||||
|
nbt.putInt("redstoneMode", this.redstoneMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void load(CompoundTag nbt) {
|
||||||
|
super.load(nbt);
|
||||||
|
|
||||||
|
this.inventory.deserializeNBT(nbt.getCompound("inventory"));
|
||||||
|
this.energy.setStoredEnergy(nbt.getInt("energy"));
|
||||||
|
this.redstoneMode = Mth.clamp(nbt.getInt("redstoneMode"), 0, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLoad() {
|
||||||
|
checkPoweredState(this.level, this.worldPosition);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void checkPoweredState(Level level, BlockPos pos) {
|
||||||
|
this.hasRedstonePower = level.hasNeighborSignal(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRedstoneMode(int redstoneMode) {
|
||||||
|
this.redstoneMode = redstoneMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getRedstoneMode() {
|
||||||
|
return this.redstoneMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@SuppressWarnings("NullableProblems")
|
||||||
|
@Override
|
||||||
|
public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> cap, @javax.annotation.Nullable Direction side) {
|
||||||
|
if (cap == ForgeCapabilities.ENERGY) {
|
||||||
|
return this.capabilityEnergy.cast();
|
||||||
|
} else if (cap == ForgeCapabilities.ITEM_HANDLER) {
|
||||||
|
return this.capabilityInventory.cast();
|
||||||
|
}
|
||||||
|
|
||||||
|
return super.getCapability(cap, side);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void invalidateCaps() {
|
||||||
|
super.invalidateCaps();
|
||||||
|
|
||||||
|
this.capabilityEnergy.invalidate();
|
||||||
|
this.capabilityInventory.invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InteractionResult use(Level level, Player player, InteractionHand hand) {
|
||||||
|
if (player instanceof ServerPlayer serverPlayer) {
|
||||||
|
NetworkHooks.openScreen(serverPlayer, this, buffer -> {
|
||||||
|
buffer.writeBlockPos(getBlockPos());
|
||||||
|
buffer.writeByte(this.redstoneMode);
|
||||||
|
});
|
||||||
|
return InteractionResult.CONSUME;
|
||||||
|
} else {
|
||||||
|
return InteractionResult.SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean stillValid(Player player) {
|
||||||
|
if (this.level.getBlockEntity(this.worldPosition) != this) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
return player.distanceToSqr(this.worldPosition.getX() + 0.5, this.worldPosition.getY() + 0.5, this.worldPosition.getZ() + 0.5) <= 64.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
protected abstract boolean isRunning();
|
||||||
|
|
||||||
|
protected abstract void tryStartRunning();
|
||||||
|
|
||||||
|
// Only called serverside
|
||||||
|
protected abstract void runMachineTick();
|
||||||
|
|
||||||
|
protected abstract int getEnergyConsumption();
|
||||||
|
|
||||||
|
protected void noEnergyTick() {}
|
||||||
|
|
||||||
|
public static class ServerTicker<M extends AbstractMachineBlockEntity<M>> implements BlockEntityTicker<M> {
|
||||||
|
@Override
|
||||||
|
public void tick(Level level, BlockPos pos, BlockState state, M machine) {
|
||||||
|
if (machine.redstoneMode == RedstoneControlWidget.REDSTONE_MODE_IGNORED || ((machine.redstoneMode == RedstoneControlWidget.REDSTONE_MODE_UNPOWERED)) != machine.hasRedstonePower) {
|
||||||
|
var energyConsumption = machine.getEnergyConsumption();
|
||||||
|
|
||||||
|
if (machine.energy.getEnergyStored() >= energyConsumption) {
|
||||||
|
if (!machine.isRunning()) {
|
||||||
|
machine.tryStartRunning();
|
||||||
|
}
|
||||||
|
if (machine.isRunning()) {
|
||||||
|
machine.energy.extractEnergy(energyConsumption, false);
|
||||||
|
machine.runMachineTick();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
machine.noEnergyTick();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -63,19 +63,9 @@ public abstract class AbstractSieveBlockEntity extends EBlockEntity implements S
|
||||||
this.logic.loadNbt(nbt);
|
this.logic.loadNbt(nbt);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Used for rendering and for TOP
|
@Override
|
||||||
public ItemStack getMesh() {
|
public SieveLogic getLogic() {
|
||||||
return this.logic.getMesh();
|
return this.logic;
|
||||||
}
|
|
||||||
|
|
||||||
// Used for rendering
|
|
||||||
public float getProgress() {
|
|
||||||
return this.logic.getProgress();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Used for rendering
|
|
||||||
public ItemStack getContents() {
|
|
||||||
return this.logic.getContents();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,263 @@
|
||||||
|
/*
|
||||||
|
* Ex Deorum
|
||||||
|
* Copyright (c) 2024 thedarkcolour
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program 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 General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package thedarkcolour.exdeorum.blockentity;
|
||||||
|
|
||||||
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.nbt.CompoundTag;
|
||||||
|
import net.minecraft.network.chat.Component;
|
||||||
|
import net.minecraft.server.level.ServerLevel;
|
||||||
|
import net.minecraft.util.RandomSource;
|
||||||
|
import net.minecraft.world.entity.player.Inventory;
|
||||||
|
import net.minecraft.world.entity.player.Player;
|
||||||
|
import net.minecraft.world.inventory.AbstractContainerMenu;
|
||||||
|
import net.minecraft.world.item.Item;
|
||||||
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
import net.minecraft.world.item.enchantment.Enchantments;
|
||||||
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
|
import net.minecraft.world.level.storage.loot.LootContext;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import thedarkcolour.exdeorum.block.MechanicalHammerBlock;
|
||||||
|
import thedarkcolour.exdeorum.blockentity.helper.ItemHelper;
|
||||||
|
import thedarkcolour.exdeorum.config.EConfig;
|
||||||
|
import thedarkcolour.exdeorum.data.TranslationKeys;
|
||||||
|
import thedarkcolour.exdeorum.loot.HammerLootModifier;
|
||||||
|
import thedarkcolour.exdeorum.recipe.RecipeUtil;
|
||||||
|
import thedarkcolour.exdeorum.recipe.hammer.HammerRecipe;
|
||||||
|
import thedarkcolour.exdeorum.registry.EBlockEntities;
|
||||||
|
import thedarkcolour.exdeorum.tag.EItemTags;
|
||||||
|
|
||||||
|
public class MechanicalHammerBlockEntity extends AbstractMachineBlockEntity<MechanicalHammerBlockEntity> {
|
||||||
|
private static final Component TITLE = Component.translatable(TranslationKeys.MECHANICAL_HAMMER_SCREEN_TITLE);
|
||||||
|
private static final int INPUT_SLOT = 0;
|
||||||
|
public static final int HAMMER_SLOT = 1;
|
||||||
|
private static final int OUTPUT_SLOT = 2;
|
||||||
|
public static final int TOTAL_PROGRESS = 10_000_000;
|
||||||
|
// process should take 200 ticks or 10 seconds with no efficiency
|
||||||
|
private static final int PROGRESS_INTERVAL = TOTAL_PROGRESS / 200;
|
||||||
|
public static final int NOT_RUNNING = -1;
|
||||||
|
|
||||||
|
// an integer from 0 to 10,000,000 instead of a decimal number which is inaccurate and buggy
|
||||||
|
private int progress = NOT_RUNNING;
|
||||||
|
private float efficiency;
|
||||||
|
|
||||||
|
public MechanicalHammerBlockEntity(BlockPos pos, BlockState state) {
|
||||||
|
super(EBlockEntities.MECHANICAL_HAMMER.get(), pos, state, ItemHandler::new, EConfig.SERVER.mechanicalHammerEnergyStorage.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isValidInput(ItemStack stack) {
|
||||||
|
return RecipeUtil.getHammerRecipe(stack.getItem()) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void saveAdditional(CompoundTag nbt) {
|
||||||
|
super.saveAdditional(nbt);
|
||||||
|
|
||||||
|
nbt.putInt("progress", this.progress);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void load(CompoundTag nbt) {
|
||||||
|
super.load(nbt);
|
||||||
|
|
||||||
|
this.progress = nbt.getInt("progress");
|
||||||
|
onHammerChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Component getDisplayName() {
|
||||||
|
return TITLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AbstractContainerMenu createMenu(int containerId, Inventory playerInventory, Player pPlayer) {
|
||||||
|
return new MechanicalHammerMenu(containerId, playerInventory, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean isRunning() {
|
||||||
|
return this.progress != NOT_RUNNING;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void tryStartRunning() {
|
||||||
|
var input = this.inventory.getStackInSlot(INPUT_SLOT);
|
||||||
|
|
||||||
|
if (!input.isEmpty()) {
|
||||||
|
if (canFitResultIntoOutput(input) != null) {
|
||||||
|
this.progress = 0;
|
||||||
|
this.level.setBlock(this.worldPosition, this.getBlockState().setValue(MechanicalHammerBlock.RUNNING, true), 3);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.level.setBlock(this.worldPosition, this.getBlockState().setValue(MechanicalHammerBlock.RUNNING, false), 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void noEnergyTick() {
|
||||||
|
if (getBlockState().getValue(MechanicalHammerBlock.RUNNING)) {
|
||||||
|
this.level.setBlock(this.worldPosition, this.getBlockState().setValue(MechanicalHammerBlock.RUNNING, false), 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private HammerRecipe canFitResultIntoOutput(ItemStack input) {
|
||||||
|
var output = this.inventory.getStackInSlot(OUTPUT_SLOT);
|
||||||
|
|
||||||
|
if (output.isEmpty() || output.getCount() < output.getMaxStackSize()) {
|
||||||
|
var recipe = RecipeUtil.getHammerRecipe(input.getItem());
|
||||||
|
|
||||||
|
if (recipe != null && (output.isEmpty() || matchesStack(recipe.result, output))) {
|
||||||
|
return recipe;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean matchesStack(Item item, ItemStack stack) {
|
||||||
|
return !stack.hasTag() && item == stack.getItem();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void runMachineTick() {
|
||||||
|
var input = this.inventory.getStackInSlot(INPUT_SLOT);
|
||||||
|
|
||||||
|
if (!input.isEmpty()) {
|
||||||
|
this.progress += PROGRESS_INTERVAL * this.efficiency;
|
||||||
|
|
||||||
|
if (this.progress >= TOTAL_PROGRESS) {
|
||||||
|
var recipe = canFitResultIntoOutput(input);
|
||||||
|
|
||||||
|
if (recipe != null) {
|
||||||
|
@SuppressWarnings("DataFlowIssue")
|
||||||
|
LootContext ctx = RecipeUtil.emptyLootContext((ServerLevel) this.level);
|
||||||
|
var resultCount = recipe.resultAmount.getInt(ctx);
|
||||||
|
resultCount += HammerLootModifier.calculateFortuneBonus(this.inventory.getStackInSlot(HAMMER_SLOT), ctx.getRandom(), resultCount == 0);
|
||||||
|
var output = this.inventory.getStackInSlot(OUTPUT_SLOT);
|
||||||
|
if (output.isEmpty()) {
|
||||||
|
this.inventory.setStackInSlot(OUTPUT_SLOT, new ItemStack(recipe.result, resultCount));
|
||||||
|
} else {
|
||||||
|
output.setCount(Math.min(output.getMaxStackSize(), resultCount + output.getCount()));
|
||||||
|
}
|
||||||
|
input.shrink(1);
|
||||||
|
damageHammer(ctx.getRandom());
|
||||||
|
|
||||||
|
setChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.progress = NOT_RUNNING;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.level.setBlock(this.worldPosition, this.getBlockState().setValue(MechanicalHammerBlock.RUNNING, false), 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void damageHammer(RandomSource rand) {
|
||||||
|
var hammer = this.inventory.getStackInSlot(HAMMER_SLOT);
|
||||||
|
|
||||||
|
if (hammer.isDamageableItem()) {
|
||||||
|
|
||||||
|
if (hammer.hurt(1, rand, null)) {
|
||||||
|
hammer.shrink(1);
|
||||||
|
|
||||||
|
if (hammer.isEmpty()) {
|
||||||
|
this.inventory.setStackInSlot(HAMMER_SLOT, ItemStack.EMPTY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onHammerChanged() {
|
||||||
|
var hammer = this.inventory.getStackInSlot(HAMMER_SLOT);
|
||||||
|
if (hammer.isEmpty()) {
|
||||||
|
this.efficiency = 1f;
|
||||||
|
} else {
|
||||||
|
// This timing allows full efficiency hammer to match full efficiency sieve (55 ticks/craft
|
||||||
|
// Rewards player for using hammer by doubling speed right off the bat, before efficiency
|
||||||
|
// although not as fast as Mekanism's crusher, still pretty fast and much cheaper
|
||||||
|
this.efficiency = 2f + hammer.getEnchantmentLevel(Enchantments.BLOCK_EFFICIENCY) * 0.33f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getEnergyConsumption() {
|
||||||
|
return EConfig.SERVER.mechanicalHammerEnergyConsumption.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
// The value synced to the client for rendering the arrow in GUI
|
||||||
|
public int getGuiProgress() {
|
||||||
|
return Math.round((float)(24 * this.progress) / TOTAL_PROGRESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGuiProgress(int guiProgress) {
|
||||||
|
this.progress = (guiProgress * TOTAL_PROGRESS) / 24;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getProgress() {
|
||||||
|
return this.progress;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setProgress(int progress) {
|
||||||
|
this.progress = progress;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class ItemHandler extends ItemHelper {
|
||||||
|
private final MechanicalHammerBlockEntity hammer;
|
||||||
|
|
||||||
|
public ItemHandler(MechanicalHammerBlockEntity hammer) {
|
||||||
|
super(3);
|
||||||
|
this.hammer = hammer;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isItemValid(int slot, @NotNull ItemStack stack) {
|
||||||
|
if (slot == INPUT_SLOT) {
|
||||||
|
return RecipeUtil.getHammerRecipe(stack.getItem()) != null;
|
||||||
|
} else if (slot == HAMMER_SLOT) {
|
||||||
|
return stack.is(EItemTags.HAMMERS);
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getSlotLimit(int slot) {
|
||||||
|
return slot == HAMMER_SLOT ? 1 : super.getSlotLimit(slot);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canMachineExtract(int slot) {
|
||||||
|
return slot == OUTPUT_SLOT;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onContentsChanged(int slot) {
|
||||||
|
if (slot == HAMMER_SLOT) {
|
||||||
|
this.hammer.onHammerChanged();
|
||||||
|
} else if (slot == INPUT_SLOT) {
|
||||||
|
if (getStackInSlot(INPUT_SLOT).isEmpty()) {
|
||||||
|
this.hammer.progress = NOT_RUNNING;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,116 @@
|
||||||
|
/*
|
||||||
|
* Ex Deorum
|
||||||
|
* Copyright (c) 2024 thedarkcolour
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program 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 General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package thedarkcolour.exdeorum.blockentity;
|
||||||
|
|
||||||
|
import net.minecraft.network.FriendlyByteBuf;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
import net.minecraft.world.entity.player.Inventory;
|
||||||
|
import net.minecraft.world.entity.player.Player;
|
||||||
|
import net.minecraft.world.inventory.DataSlot;
|
||||||
|
import net.minecraft.world.inventory.InventoryMenu;
|
||||||
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
import thedarkcolour.exdeorum.ExDeorum;
|
||||||
|
import thedarkcolour.exdeorum.menu.AbstractMachineMenu;
|
||||||
|
import thedarkcolour.exdeorum.registry.EMenus;
|
||||||
|
import thedarkcolour.exdeorum.tag.EItemTags;
|
||||||
|
|
||||||
|
public class MechanicalHammerMenu extends AbstractMachineMenu<MechanicalHammerBlockEntity> {
|
||||||
|
private static final ResourceLocation EMPTY_SLOT_HAMMER = new ResourceLocation(ExDeorum.ID, "item/empty_slot_hammer");
|
||||||
|
private static final int NUM_SLOTS = 3;
|
||||||
|
|
||||||
|
public MechanicalHammerMenu(int containerId, Inventory playerInventory, FriendlyByteBuf data) {
|
||||||
|
this(containerId, playerInventory, (MechanicalHammerBlockEntity) readPayload(playerInventory, data));
|
||||||
|
}
|
||||||
|
|
||||||
|
public MechanicalHammerMenu(int containerId, Inventory playerInventory, MechanicalHammerBlockEntity machine) {
|
||||||
|
super(EMenus.MECHANICAL_HAMMER.get(), containerId, playerInventory, machine);
|
||||||
|
|
||||||
|
// input slot
|
||||||
|
addSlot(machine.inventory.createSlot(0, 32, 35));
|
||||||
|
// hammer slot
|
||||||
|
addSlot(machine.inventory.createSlot(1, 56, 35).setBackground(InventoryMenu.BLOCK_ATLAS, EMPTY_SLOT_HAMMER));
|
||||||
|
// output slot
|
||||||
|
addSlot(machine.inventory.createSlot(2, 116, 35));
|
||||||
|
|
||||||
|
addPlayerSlots(playerInventory, 84);
|
||||||
|
|
||||||
|
addDataSlot(new ProgressDataSlot());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ItemStack quickMoveStack(Player player, int clickedSlot) {
|
||||||
|
var stack = ItemStack.EMPTY;
|
||||||
|
var slot = this.slots.get(clickedSlot);
|
||||||
|
|
||||||
|
if (slot.hasItem()) {
|
||||||
|
var clickedStack = slot.getItem();
|
||||||
|
stack = clickedStack.copy();
|
||||||
|
|
||||||
|
if (clickedSlot > 1 && clickedSlot <= NUM_SLOTS) { // moving out of output slots
|
||||||
|
if (!moveItemStackTo(clickedStack, NUM_SLOTS, PLAYER_SLOTS + NUM_SLOTS, true)) {
|
||||||
|
return ItemStack.EMPTY;
|
||||||
|
}
|
||||||
|
} else if (clickedSlot < 2) { // moving out of input/mesh slot
|
||||||
|
if (!moveItemStackTo(clickedStack, NUM_SLOTS, NUM_SLOTS + PLAYER_SLOTS, false)) {
|
||||||
|
return ItemStack.EMPTY;
|
||||||
|
}
|
||||||
|
} else if (MechanicalHammerBlockEntity.isValidInput(clickedStack)) { // attempting to move into input slot
|
||||||
|
if (!moveItemStackTo(clickedStack, 0, 1, false)) {
|
||||||
|
return ItemStack.EMPTY;
|
||||||
|
}
|
||||||
|
} else if (clickedStack.is(EItemTags.HAMMERS)) { // attempting to move into mesh slot
|
||||||
|
if (!moveItemStackTo(clickedStack, 1, 2, false)) {
|
||||||
|
return ItemStack.EMPTY;
|
||||||
|
}
|
||||||
|
} else if (clickedSlot < NUM_SLOTS + 27) { // attempting to move from inventory to hotbar
|
||||||
|
if (!moveItemStackTo(clickedStack, NUM_SLOTS + 27, NUM_SLOTS + PLAYER_SLOTS, false)) {
|
||||||
|
return ItemStack.EMPTY;
|
||||||
|
}
|
||||||
|
} else if (clickedSlot < NUM_SLOTS + PLAYER_SLOTS) { // attempting to move from hotbar to inventory
|
||||||
|
if (!moveItemStackTo(clickedStack, NUM_SLOTS, NUM_SLOTS + 27, false)) {
|
||||||
|
return ItemStack.EMPTY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clickedStack.isEmpty()) {
|
||||||
|
slot.set(ItemStack.EMPTY);
|
||||||
|
}
|
||||||
|
slot.setChanged();
|
||||||
|
if (clickedStack.getCount() == stack.getCount()) {
|
||||||
|
return ItemStack.EMPTY;
|
||||||
|
}
|
||||||
|
slot.onTake(player, clickedStack);
|
||||||
|
broadcastChanges();
|
||||||
|
}
|
||||||
|
|
||||||
|
return stack;
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ProgressDataSlot extends DataSlot {
|
||||||
|
@Override
|
||||||
|
public int get() {
|
||||||
|
return MechanicalHammerMenu.this.machine.getGuiProgress();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void set(int value) {
|
||||||
|
MechanicalHammerMenu.this.machine.setGuiProgress(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -19,35 +19,19 @@
|
||||||
package thedarkcolour.exdeorum.blockentity;
|
package thedarkcolour.exdeorum.blockentity;
|
||||||
|
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.core.Direction;
|
|
||||||
import net.minecraft.nbt.CompoundTag;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
|
import net.minecraft.network.FriendlyByteBuf;
|
||||||
import net.minecraft.network.chat.Component;
|
import net.minecraft.network.chat.Component;
|
||||||
import net.minecraft.server.level.ServerLevel;
|
import net.minecraft.server.level.ServerLevel;
|
||||||
import net.minecraft.server.level.ServerPlayer;
|
|
||||||
import net.minecraft.util.Mth;
|
|
||||||
import net.minecraft.util.RandomSource;
|
import net.minecraft.util.RandomSource;
|
||||||
import net.minecraft.world.InteractionHand;
|
|
||||||
import net.minecraft.world.InteractionResult;
|
|
||||||
import net.minecraft.world.MenuProvider;
|
|
||||||
import net.minecraft.world.entity.player.Inventory;
|
import net.minecraft.world.entity.player.Inventory;
|
||||||
import net.minecraft.world.entity.player.Player;
|
import net.minecraft.world.entity.player.Player;
|
||||||
import net.minecraft.world.inventory.AbstractContainerMenu;
|
import net.minecraft.world.inventory.AbstractContainerMenu;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
import net.minecraft.world.level.Level;
|
|
||||||
import net.minecraft.world.level.block.entity.BlockEntityTicker;
|
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
import net.minecraftforge.common.capabilities.Capability;
|
|
||||||
import net.minecraftforge.common.capabilities.ForgeCapabilities;
|
|
||||||
import net.minecraftforge.common.util.LazyOptional;
|
|
||||||
import net.minecraftforge.energy.EnergyStorage;
|
|
||||||
import net.minecraftforge.items.ItemHandlerHelper;
|
import net.minecraftforge.items.ItemHandlerHelper;
|
||||||
import net.minecraftforge.network.NetworkHooks;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
import thedarkcolour.exdeorum.blockentity.helper.EnergyHelper;
|
|
||||||
import thedarkcolour.exdeorum.blockentity.helper.ItemHelper;
|
import thedarkcolour.exdeorum.blockentity.helper.ItemHelper;
|
||||||
import thedarkcolour.exdeorum.blockentity.logic.SieveLogic;
|
import thedarkcolour.exdeorum.blockentity.logic.SieveLogic;
|
||||||
import thedarkcolour.exdeorum.client.screen.RedstoneControlWidget;
|
|
||||||
import thedarkcolour.exdeorum.config.EConfig;
|
import thedarkcolour.exdeorum.config.EConfig;
|
||||||
import thedarkcolour.exdeorum.data.TranslationKeys;
|
import thedarkcolour.exdeorum.data.TranslationKeys;
|
||||||
import thedarkcolour.exdeorum.menu.MechanicalSieveMenu;
|
import thedarkcolour.exdeorum.menu.MechanicalSieveMenu;
|
||||||
|
|
@ -55,107 +39,70 @@ import thedarkcolour.exdeorum.recipe.RecipeUtil;
|
||||||
import thedarkcolour.exdeorum.registry.EBlockEntities;
|
import thedarkcolour.exdeorum.registry.EBlockEntities;
|
||||||
import thedarkcolour.exdeorum.tag.EItemTags;
|
import thedarkcolour.exdeorum.tag.EItemTags;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
public class MechanicalSieveBlockEntity extends AbstractMachineBlockEntity<MechanicalSieveBlockEntity> implements SieveLogic.Owner {
|
||||||
|
|
||||||
public class MechanicalSieveBlockEntity extends AbstractSieveBlockEntity implements MenuProvider {
|
|
||||||
private static final Component TITLE = Component.translatable(TranslationKeys.MECHANICAL_SIEVE_SCREEN_TITLE);
|
private static final Component TITLE = Component.translatable(TranslationKeys.MECHANICAL_SIEVE_SCREEN_TITLE);
|
||||||
private static final int INPUT_SLOT = 0;
|
private static final int INPUT_SLOT = 0;
|
||||||
public static final int MESH_SLOT = 1;
|
public static final int MESH_SLOT = 1;
|
||||||
|
|
||||||
public final ItemHelper inventory;
|
private final SieveLogic logic;
|
||||||
public final EnergyHelper energy;
|
|
||||||
private int redstoneMode;
|
|
||||||
// not saved to NBT
|
|
||||||
public boolean hasRedstonePower;
|
|
||||||
|
|
||||||
private final LazyOptional<ItemHelper> capabilityInventory;
|
|
||||||
private final LazyOptional<EnergyStorage> capabilityEnergy;
|
|
||||||
|
|
||||||
public MechanicalSieveBlockEntity(BlockPos pos, BlockState state) {
|
public MechanicalSieveBlockEntity(BlockPos pos, BlockState state) {
|
||||||
super(EBlockEntities.MECHANICAL_SIEVE.get(), pos, state, owner -> new SieveLogic(owner, false, true));
|
super(EBlockEntities.MECHANICAL_SIEVE.get(), pos, state, ItemHandler::new, EConfig.SERVER.mechanicalSieveEnergyStorage.get());
|
||||||
|
|
||||||
this.inventory = new ItemHandler(22);
|
this.logic = new SieveLogic(this, false, true);
|
||||||
this.energy = new EnergyHelper(40000);
|
|
||||||
|
|
||||||
this.capabilityInventory = LazyOptional.of(() -> this.inventory);
|
|
||||||
this.capabilityEnergy = LazyOptional.of(() -> this.energy);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void saveAdditional(CompoundTag nbt) {
|
protected void saveAdditional(CompoundTag nbt) {
|
||||||
super.saveAdditional(nbt);
|
super.saveAdditional(nbt);
|
||||||
|
|
||||||
nbt.put("inventory", this.inventory.serializeNBT());
|
this.logic.saveNbt(nbt);
|
||||||
nbt.putInt("energy", this.energy.getEnergyStored());
|
|
||||||
nbt.putInt("redstoneMode", this.redstoneMode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void load(CompoundTag nbt) {
|
public void load(CompoundTag nbt) {
|
||||||
super.load(nbt);
|
super.load(nbt);
|
||||||
|
|
||||||
this.inventory.deserializeNBT(nbt.getCompound("inventory"));
|
this.logic.loadNbt(nbt);
|
||||||
this.energy.setStoredEnergy(nbt.getInt("energy"));
|
|
||||||
this.redstoneMode = Mth.clamp(nbt.getInt("redstoneMode"), 0, 2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onLoad() {
|
protected boolean isRunning() {
|
||||||
checkPoweredState(this.level, this.worldPosition);
|
return !this.logic.getContents().isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public InteractionResult use(Level level, Player player, InteractionHand hand) {
|
protected void tryStartRunning() {
|
||||||
if (player instanceof ServerPlayer serverPlayer) {
|
var input = this.inventory.getStackInSlot(INPUT_SLOT);
|
||||||
NetworkHooks.openScreen(serverPlayer, this, buffer -> {
|
|
||||||
buffer.writeBlockPos(getBlockPos());
|
if (this.logic.isValidInput(input)) {
|
||||||
buffer.writeByte(this.redstoneMode);
|
this.logic.startSifting(AbstractSieveBlockEntity.singleCopy(input));
|
||||||
});
|
input.shrink(1);
|
||||||
return InteractionResult.CONSUME;
|
|
||||||
} else {
|
|
||||||
return InteractionResult.SUCCESS;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
|
||||||
@Override
|
@Override
|
||||||
public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> cap, @javax.annotation.Nullable Direction side) {
|
protected void runMachineTick() {
|
||||||
if (cap == ForgeCapabilities.ENERGY) {
|
this.logic.sift(0.01f);
|
||||||
return this.capabilityEnergy.cast();
|
|
||||||
} else if (cap == ForgeCapabilities.ITEM_HANDLER) {
|
|
||||||
return this.capabilityInventory.cast();
|
|
||||||
}
|
|
||||||
|
|
||||||
return super.getCapability(cap, side);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void invalidateCaps() {
|
protected int getEnergyConsumption() {
|
||||||
super.invalidateCaps();
|
return EConfig.SERVER.mechanicalSieveEnergyConsumption.get();
|
||||||
|
|
||||||
this.capabilityEnergy.invalidate();
|
|
||||||
this.capabilityInventory.invalidate();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void serverTick() {
|
@Override
|
||||||
if (this.redstoneMode == RedstoneControlWidget.REDSTONE_MODE_IGNORED || ((this.redstoneMode == RedstoneControlWidget.REDSTONE_MODE_UNPOWERED)) != this.hasRedstonePower) {
|
public void writeVisualData(FriendlyByteBuf buffer) {
|
||||||
var energyConsumption = EConfig.SERVER.mechanicalSieveEnergyConsumption.get();
|
buffer.writeItem(this.logic.getMesh());
|
||||||
|
buffer.writeFloat(this.logic.getProgress());
|
||||||
|
buffer.writeItem(this.logic.getContents());
|
||||||
|
}
|
||||||
|
|
||||||
if (this.energy.getEnergyStored() >= energyConsumption) {
|
@Override
|
||||||
if (this.logic.getContents().isEmpty()) {
|
public void readVisualData(FriendlyByteBuf buffer) {
|
||||||
var input = this.inventory.getStackInSlot(INPUT_SLOT);
|
this.logic.setMesh(buffer.readItem(), false);
|
||||||
|
this.logic.setProgress(buffer.readFloat());
|
||||||
if (this.logic.isValidInput(input)) {
|
this.logic.setContents(buffer.readItem());
|
||||||
this.logic.startSifting(AbstractSieveBlockEntity.singleCopy(input));
|
|
||||||
input.shrink(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!this.logic.getContents().isEmpty()) {
|
|
||||||
this.energy.extractEnergy(energyConsumption, false);
|
|
||||||
this.logic.sift(0.01f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -205,43 +152,32 @@ public class MechanicalSieveBlockEntity extends AbstractSieveBlockEntity impleme
|
||||||
return TITLE;
|
return TITLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@Override
|
@Override
|
||||||
public AbstractContainerMenu createMenu(int containerId, Inventory playerInventory, Player pPlayer) {
|
public AbstractContainerMenu createMenu(int containerId, Inventory playerInventory, Player pPlayer) {
|
||||||
return new MechanicalSieveMenu(containerId, playerInventory, this);
|
return new MechanicalSieveMenu(containerId, playerInventory, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean stillValid(Player player) {
|
@Override
|
||||||
if (this.level.getBlockEntity(this.worldPosition) != this) {
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
return player.distanceToSqr(this.worldPosition.getX() + 0.5, this.worldPosition.getY() + 0.5, this.worldPosition.getZ() + 0.5) <= 64.0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public SieveLogic getLogic() {
|
public SieveLogic getLogic() {
|
||||||
return this.logic;
|
return this.logic;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setRedstoneMode(int redstoneMode) {
|
@SuppressWarnings("DataFlowIssue")
|
||||||
this.redstoneMode = redstoneMode;
|
@Override
|
||||||
|
public ServerLevel getServerLevel() {
|
||||||
|
return (ServerLevel) this.level;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getRedstoneMode() {
|
private static class ItemHandler extends ItemHelper {
|
||||||
return this.redstoneMode;
|
private final MechanicalSieveBlockEntity sieve;
|
||||||
}
|
|
||||||
|
|
||||||
public void checkPoweredState(Level level, BlockPos pos) {
|
public ItemHandler(MechanicalSieveBlockEntity sieve) {
|
||||||
this.hasRedstonePower = level.hasNeighborSignal(pos);
|
super(22);
|
||||||
}
|
this.sieve = sieve;
|
||||||
|
|
||||||
private class ItemHandler extends ItemHelper {
|
|
||||||
public ItemHandler(int size) {
|
|
||||||
super(size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isItemValid(int slot, @NotNull ItemStack stack) {
|
public boolean isItemValid(int slot, ItemStack stack) {
|
||||||
if (slot == INPUT_SLOT) {
|
if (slot == INPUT_SLOT) {
|
||||||
return !RecipeUtil.getSieveRecipes(getStackInSlot(1).getItem(), stack).isEmpty();
|
return !RecipeUtil.getSieveRecipes(getStackInSlot(1).getItem(), stack).isEmpty();
|
||||||
} else if (slot == MESH_SLOT) {
|
} else if (slot == MESH_SLOT) {
|
||||||
|
|
@ -264,20 +200,13 @@ public class MechanicalSieveBlockEntity extends AbstractSieveBlockEntity impleme
|
||||||
@Override
|
@Override
|
||||||
protected void onContentsChanged(int slot) {
|
protected void onContentsChanged(int slot) {
|
||||||
if (slot == MESH_SLOT) {
|
if (slot == MESH_SLOT) {
|
||||||
MechanicalSieveBlockEntity.this.logic.setMesh(MechanicalSieveBlockEntity.this.inventory.getStackInSlot(MESH_SLOT));
|
this.sieve.logic.setMesh(this.sieve.inventory.getStackInSlot(MESH_SLOT));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onLoad() {
|
protected void onLoad() {
|
||||||
MechanicalSieveBlockEntity.this.logic.setMesh(MechanicalSieveBlockEntity.this.inventory.getStackInSlot(MESH_SLOT), false);
|
this.sieve.logic.setMesh(this.sieve.inventory.getStackInSlot(MESH_SLOT), false);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class ServerTicker implements BlockEntityTicker<MechanicalSieveBlockEntity> {
|
|
||||||
@Override
|
|
||||||
public void tick(Level level, BlockPos pos, BlockState state, MechanicalSieveBlockEntity sieve) {
|
|
||||||
sieve.serverTick();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,14 +27,11 @@ import net.minecraft.world.item.ItemStack;
|
||||||
import net.minecraft.world.item.Items;
|
import net.minecraft.world.item.Items;
|
||||||
import net.minecraft.world.item.enchantment.Enchantments;
|
import net.minecraft.world.item.enchantment.Enchantments;
|
||||||
import net.minecraft.world.level.storage.loot.LootContext;
|
import net.minecraft.world.level.storage.loot.LootContext;
|
||||||
import net.minecraft.world.level.storage.loot.LootParams;
|
|
||||||
import thedarkcolour.exdeorum.config.EConfig;
|
import thedarkcolour.exdeorum.config.EConfig;
|
||||||
import thedarkcolour.exdeorum.recipe.RecipeUtil;
|
import thedarkcolour.exdeorum.recipe.RecipeUtil;
|
||||||
import thedarkcolour.exdeorum.recipe.sieve.SieveRecipe;
|
import thedarkcolour.exdeorum.recipe.sieve.SieveRecipe;
|
||||||
import thedarkcolour.exdeorum.tag.EItemTags;
|
import thedarkcolour.exdeorum.tag.EItemTags;
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public class SieveLogic {
|
public class SieveLogic {
|
||||||
private final Owner owner;
|
private final Owner owner;
|
||||||
private final boolean saveMesh;
|
private final boolean saveMesh;
|
||||||
|
|
@ -80,7 +77,7 @@ public class SieveLogic {
|
||||||
// Need epsilon because floating point decimals suck
|
// Need epsilon because floating point decimals suck
|
||||||
if (this.progress >= 1.0f - Mth.EPSILON) {
|
if (this.progress >= 1.0f - Mth.EPSILON) {
|
||||||
var level = this.owner.getServerLevel();
|
var level = this.owner.getServerLevel();
|
||||||
var context = new LootContext.Builder(new LootParams(level, Map.of(), Map.of(), 0)).create(null);
|
var context = RecipeUtil.emptyLootContext(level);
|
||||||
var rand = level.random;
|
var rand = level.random;
|
||||||
var limitDrops = this.contents.getItem() == Items.MOSS_BLOCK && EConfig.SERVER.limitMossSieveDrops.get();
|
var limitDrops = this.contents.getItem() == Items.MOSS_BLOCK && EConfig.SERVER.limitMossSieveDrops.get();
|
||||||
var handledAnyDrops = false;
|
var handledAnyDrops = false;
|
||||||
|
|
@ -207,5 +204,7 @@ public class SieveLogic {
|
||||||
boolean handleResultItem(ItemStack result, ServerLevel level, RandomSource rand);
|
boolean handleResultItem(ItemStack result, ServerLevel level, RandomSource rand);
|
||||||
|
|
||||||
void markUpdated();
|
void markUpdated();
|
||||||
|
|
||||||
|
SieveLogic getLogic();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,7 @@ import net.minecraftforge.fml.event.config.ModConfigEvent;
|
||||||
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
|
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
|
||||||
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
|
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
|
||||||
import thedarkcolour.exdeorum.ExDeorum;
|
import thedarkcolour.exdeorum.ExDeorum;
|
||||||
|
import thedarkcolour.exdeorum.client.screen.MechanicalHammerScreen;
|
||||||
import thedarkcolour.exdeorum.client.screen.MechanicalSieveScreen;
|
import thedarkcolour.exdeorum.client.screen.MechanicalSieveScreen;
|
||||||
import thedarkcolour.exdeorum.client.ter.BarrelRenderer;
|
import thedarkcolour.exdeorum.client.ter.BarrelRenderer;
|
||||||
import thedarkcolour.exdeorum.client.ter.CrucibleRenderer;
|
import thedarkcolour.exdeorum.client.ter.CrucibleRenderer;
|
||||||
|
|
@ -101,6 +102,7 @@ public class ClientHandler {
|
||||||
event.enqueueWork(() -> {
|
event.enqueueWork(() -> {
|
||||||
setRenderLayers();
|
setRenderLayers();
|
||||||
MenuScreens.register(EMenus.MECHANICAL_SIEVE.get(), MechanicalSieveScreen::new);
|
MenuScreens.register(EMenus.MECHANICAL_SIEVE.get(), MechanicalSieveScreen::new);
|
||||||
|
MenuScreens.register(EMenus.MECHANICAL_HAMMER.get(), MechanicalHammerScreen::new);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,94 @@
|
||||||
|
/*
|
||||||
|
* Ex Deorum
|
||||||
|
* Copyright (c) 2024 thedarkcolour
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program 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 General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package thedarkcolour.exdeorum.client.screen;
|
||||||
|
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.gui.GuiGraphics;
|
||||||
|
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
|
||||||
|
import net.minecraft.network.chat.Component;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
import net.minecraft.util.Mth;
|
||||||
|
import net.minecraft.world.entity.player.Inventory;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import thedarkcolour.exdeorum.ExDeorum;
|
||||||
|
import thedarkcolour.exdeorum.blockentity.MechanicalHammerMenu;
|
||||||
|
import thedarkcolour.exdeorum.config.EConfig;
|
||||||
|
import thedarkcolour.exdeorum.data.TranslationKeys;
|
||||||
|
|
||||||
|
public class MechanicalHammerScreen extends AbstractContainerScreen<MechanicalHammerMenu> {
|
||||||
|
private static final ResourceLocation BACKGROUND_TEXTURE = new ResourceLocation(ExDeorum.ID, "textures/gui/container/mechanical_hammer.png");
|
||||||
|
|
||||||
|
public static final int RECIPE_CLICK_AREA_POS_X = 80;
|
||||||
|
public static final int RECIPE_CLICK_AREA_POS_Y = 34;
|
||||||
|
public static final int RECIPE_CLICK_AREA_WIDTH = 23;
|
||||||
|
public static final int RECIPE_CLICK_AREA_HEIGHT = 16;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private RedstoneControlWidget redstoneControlWidget;
|
||||||
|
|
||||||
|
public MechanicalHammerScreen(MechanicalHammerMenu menu, Inventory playerInventory, Component title) {
|
||||||
|
super(menu, playerInventory, title);
|
||||||
|
|
||||||
|
this.imageWidth = 176;
|
||||||
|
this.imageHeight = 166;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void init() {
|
||||||
|
super.init();
|
||||||
|
|
||||||
|
this.redstoneControlWidget = new RedstoneControlWidget(this.menu, BACKGROUND_TEXTURE, this.leftPos + this.imageWidth, this.topPos + 3);
|
||||||
|
addRenderableWidget(this.redstoneControlWidget);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public RedstoneControlWidget getRedstoneControlWidget() {
|
||||||
|
return this.redstoneControlWidget;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void renderBg(GuiGraphics graphics, float pPartialTick, int pMouseX, int pMouseY) {
|
||||||
|
int left = this.leftPos;
|
||||||
|
int top = this.topPos;
|
||||||
|
graphics.blit(BACKGROUND_TEXTURE, left, top, 0, 0, this.imageWidth, this.imageHeight);
|
||||||
|
|
||||||
|
// energy bar
|
||||||
|
int energy = Mth.floor(54 * ((float) this.menu.prevEnergy / EConfig.SERVER.mechanicalSieveEnergyStorage.get()));
|
||||||
|
graphics.blit(BACKGROUND_TEXTURE, left + 10, top + 15 + 54 - energy, this.imageWidth, 16 + 54 - energy, 12, energy);
|
||||||
|
|
||||||
|
// progress arrow
|
||||||
|
int progress = Math.min(23, this.menu.machine.getGuiProgress());
|
||||||
|
graphics.blit(BACKGROUND_TEXTURE, left + RECIPE_CLICK_AREA_POS_X, top + RECIPE_CLICK_AREA_POS_Y, this.imageWidth, 0, progress, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render(GuiGraphics graphics, int mx, int my, float pPartialTick) {
|
||||||
|
renderBackground(graphics);
|
||||||
|
super.render(graphics, mx, my, pPartialTick);
|
||||||
|
renderTooltip(graphics, mx, my);
|
||||||
|
|
||||||
|
int rx = mx - this.leftPos;
|
||||||
|
int ry = my - this.topPos;
|
||||||
|
|
||||||
|
if (9 <= rx && rx < 23 && 14 <= ry && ry < 70) {
|
||||||
|
var energyTooltip = Component.translatable(TranslationKeys.ENERGY).append(Component.translatable(TranslationKeys.FRACTION_DISPLAY, this.menu.prevEnergy, EConfig.SERVER.mechanicalSieveEnergyStorage.get())).append(" FE");
|
||||||
|
graphics.renderTooltip(Minecraft.getInstance().font, energyTooltip, mx, my);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -40,14 +40,12 @@ public class MechanicalSieveScreen extends AbstractContainerScreen<MechanicalSie
|
||||||
public static final int RECIPE_CLICK_AREA_WIDTH = 21;
|
public static final int RECIPE_CLICK_AREA_WIDTH = 21;
|
||||||
public static final int RECIPE_CLICK_AREA_HEIGHT = 14;
|
public static final int RECIPE_CLICK_AREA_HEIGHT = 14;
|
||||||
|
|
||||||
private final MechanicalSieveMenu menu;
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private RedstoneControlWidget redstoneControlWidget;
|
private RedstoneControlWidget redstoneControlWidget;
|
||||||
|
|
||||||
public MechanicalSieveScreen(MechanicalSieveMenu menu, Inventory playerInventory, Component title) {
|
public MechanicalSieveScreen(MechanicalSieveMenu menu, Inventory playerInventory, Component title) {
|
||||||
super(menu, playerInventory, title);
|
super(menu, playerInventory, title);
|
||||||
|
|
||||||
this.menu = menu;
|
|
||||||
this.imageWidth = 176;
|
this.imageWidth = 176;
|
||||||
this.imageHeight = 173;
|
this.imageHeight = 173;
|
||||||
this.inventoryLabelY += 7;
|
this.inventoryLabelY += 7;
|
||||||
|
|
@ -57,7 +55,7 @@ public class MechanicalSieveScreen extends AbstractContainerScreen<MechanicalSie
|
||||||
protected void init() {
|
protected void init() {
|
||||||
super.init();
|
super.init();
|
||||||
|
|
||||||
this.redstoneControlWidget = new RedstoneControlWidget(this, BACKGROUND_TEXTURE, this.leftPos + 176, this.topPos + 3);
|
this.redstoneControlWidget = new RedstoneControlWidget(this.menu, BACKGROUND_TEXTURE, this.leftPos + this.imageWidth, this.topPos + 3);
|
||||||
addRenderableWidget(this.redstoneControlWidget);
|
addRenderableWidget(this.redstoneControlWidget);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -73,12 +71,12 @@ public class MechanicalSieveScreen extends AbstractContainerScreen<MechanicalSie
|
||||||
graphics.blit(BACKGROUND_TEXTURE, left, top, 0, 0, this.imageWidth, this.imageHeight);
|
graphics.blit(BACKGROUND_TEXTURE, left, top, 0, 0, this.imageWidth, this.imageHeight);
|
||||||
|
|
||||||
// energy bar
|
// energy bar
|
||||||
int energy = Mth.floor(54 * ((float) this.menu.prevSieveEnergy / EConfig.SERVER.mechanicalSieveEnergyStorage.get()));
|
int energy = Mth.floor(54 * ((float) this.menu.prevEnergy / EConfig.SERVER.mechanicalSieveEnergyStorage.get()));
|
||||||
graphics.blit(BACKGROUND_TEXTURE, left + 10, top + 22 + 54 - energy, this.imageWidth, 14 + 54 - energy, 12, energy);
|
graphics.blit(BACKGROUND_TEXTURE, left + 10, top + 22 + 54 - energy, this.imageWidth, 14 + 54 - energy, 12, energy);
|
||||||
|
|
||||||
// progress arrow
|
// progress arrow
|
||||||
int progress = Math.min(21, (int) (this.menu.sieve.getProgress() * 22));
|
int progress = Math.min(21, (int) (this.menu.machine.getLogic().getProgress() * 22));
|
||||||
graphics.blit(BACKGROUND_TEXTURE, left + 51, top + 42, this.imageWidth, 0, progress, 14);
|
graphics.blit(BACKGROUND_TEXTURE, left + RECIPE_CLICK_AREA_POS_X, top + RECIPE_CLICK_AREA_POS_Y, this.imageWidth, 0, progress, 14);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -91,7 +89,7 @@ public class MechanicalSieveScreen extends AbstractContainerScreen<MechanicalSie
|
||||||
int ry = my - this.topPos;
|
int ry = my - this.topPos;
|
||||||
|
|
||||||
if (9 <= rx && rx < 23 && 21 <= ry && ry < 77) {
|
if (9 <= rx && rx < 23 && 21 <= ry && ry < 77) {
|
||||||
var energyTooltip = Component.translatable(TranslationKeys.ENERGY).append(Component.translatable(TranslationKeys.FRACTION_DISPLAY, this.menu.prevSieveEnergy, EConfig.SERVER.mechanicalSieveEnergyStorage.get())).append(" FE");
|
var energyTooltip = Component.translatable(TranslationKeys.ENERGY).append(Component.translatable(TranslationKeys.FRACTION_DISPLAY, this.menu.prevEnergy, EConfig.SERVER.mechanicalSieveEnergyStorage.get())).append(" FE");
|
||||||
graphics.renderTooltip(Minecraft.getInstance().font, energyTooltip, mx, my);
|
graphics.renderTooltip(Minecraft.getInstance().font, energyTooltip, mx, my);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ import net.minecraft.network.chat.Component;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.sounds.SoundEvents;
|
import net.minecraft.sounds.SoundEvents;
|
||||||
import thedarkcolour.exdeorum.data.TranslationKeys;
|
import thedarkcolour.exdeorum.data.TranslationKeys;
|
||||||
|
import thedarkcolour.exdeorum.menu.AbstractMachineMenu;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
|
@ -46,7 +47,7 @@ public class RedstoneControlWidget implements GuiEventListener, NarratableEntry,
|
||||||
};
|
};
|
||||||
private static final Component REDSTONE_CONTROL_LABEL = Component.translatable(TranslationKeys.REDSTONE_CONTROL_LABEL);
|
private static final Component REDSTONE_CONTROL_LABEL = Component.translatable(TranslationKeys.REDSTONE_CONTROL_LABEL);
|
||||||
|
|
||||||
private final MechanicalSieveScreen screen;
|
private final AbstractMachineMenu<?> screen;
|
||||||
private final ResourceLocation texture;
|
private final ResourceLocation texture;
|
||||||
private final int posX;
|
private final int posX;
|
||||||
private final int posY;
|
private final int posY;
|
||||||
|
|
@ -68,7 +69,7 @@ public class RedstoneControlWidget implements GuiEventListener, NarratableEntry,
|
||||||
// Last time (from currentTimeMillis) this button was clicked, used in animation lerp
|
// Last time (from currentTimeMillis) this button was clicked, used in animation lerp
|
||||||
private long lastClicked = -1L;
|
private long lastClicked = -1L;
|
||||||
|
|
||||||
public RedstoneControlWidget(MechanicalSieveScreen screen, ResourceLocation texture, int posX, int posY) {
|
public RedstoneControlWidget(AbstractMachineMenu<?> screen, ResourceLocation texture, int posX, int posY) {
|
||||||
this.screen = screen;
|
this.screen = screen;
|
||||||
this.texture = texture;
|
this.texture = texture;
|
||||||
this.posX = posX;
|
this.posX = posX;
|
||||||
|
|
@ -106,7 +107,7 @@ public class RedstoneControlWidget implements GuiEventListener, NarratableEntry,
|
||||||
var font = Minecraft.getInstance().font;
|
var font = Minecraft.getInstance().font;
|
||||||
|
|
||||||
if (this.expanded) {
|
if (this.expanded) {
|
||||||
var redstoneMode = this.screen.getMenu().sieve.getRedstoneMode();
|
var redstoneMode = this.screen.machine.getRedstoneMode();
|
||||||
graphics.blit(this.texture, this.posX, this.posY, this.expandedU, this.expandedV, this.expandedWidth, this.expandedHeight);
|
graphics.blit(this.texture, this.posX, this.posY, this.expandedU, this.expandedV, this.expandedWidth, this.expandedHeight);
|
||||||
for (int i = 0; i < 3; ++i) {
|
for (int i = 0; i < 3; ++i) {
|
||||||
graphics.blit(this.texture, this.buttonsPosX + (i * 19), this.buttonsPosY, (redstoneMode == i ? this.tabU + 16 : this.tabU), this.tabV + this.tabHeight, 16, 16);
|
graphics.blit(this.texture, this.buttonsPosX + (i * 19), this.buttonsPosY, (redstoneMode == i ? this.tabU + 16 : this.tabU), this.tabV + this.tabHeight, 16, 16);
|
||||||
|
|
@ -157,9 +158,10 @@ public class RedstoneControlWidget implements GuiEventListener, NarratableEntry,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("DataFlowIssue")
|
||||||
private void setRedstoneMode(int redstoneMode) {
|
private void setRedstoneMode(int redstoneMode) {
|
||||||
this.screen.getMenu().clickMenuButton(Minecraft.getInstance().player, redstoneMode);
|
this.screen.clickMenuButton(Minecraft.getInstance().player, redstoneMode);
|
||||||
Minecraft.getInstance().gameMode.handleInventoryButtonClick(this.screen.getMenu().containerId, redstoneMode);
|
Minecraft.getInstance().gameMode.handleInventoryButtonClick(this.screen.containerId, redstoneMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void drawPartialConfig(GuiGraphics graphics) {
|
private void drawPartialConfig(GuiGraphics graphics) {
|
||||||
|
|
|
||||||
|
|
@ -23,31 +23,33 @@ import net.minecraft.client.renderer.MultiBufferSource;
|
||||||
import net.minecraft.client.renderer.RenderType;
|
import net.minecraft.client.renderer.RenderType;
|
||||||
import net.minecraft.client.renderer.blockentity.BlockEntityRenderer;
|
import net.minecraft.client.renderer.blockentity.BlockEntityRenderer;
|
||||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||||
|
import net.minecraft.core.registries.BuiltInRegistries;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.world.item.BlockItem;
|
import net.minecraft.world.item.BlockItem;
|
||||||
import net.minecraft.world.item.Item;
|
import net.minecraft.world.item.Item;
|
||||||
import net.minecraftforge.registries.ForgeRegistries;
|
import thedarkcolour.exdeorum.blockentity.EBlockEntity;
|
||||||
import thedarkcolour.exdeorum.blockentity.AbstractSieveBlockEntity;
|
import thedarkcolour.exdeorum.blockentity.logic.SieveLogic;
|
||||||
import thedarkcolour.exdeorum.client.RenderUtil;
|
import thedarkcolour.exdeorum.client.RenderUtil;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public class SieveRenderer<T extends AbstractSieveBlockEntity> implements BlockEntityRenderer<T> {
|
public class SieveRenderer<T extends EBlockEntity & SieveLogic.Owner> implements BlockEntityRenderer<T> {
|
||||||
public static final Map<Item, TextureAtlasSprite> MESH_TEXTURES = new HashMap<>();
|
public static final Map<Item, TextureAtlasSprite> MESH_TEXTURES = new HashMap<>();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void render(T sieve, float partialTicks, PoseStack stack, MultiBufferSource buffers, int light, int overlay) {
|
public void render(T sieve, float partialTicks, PoseStack stack, MultiBufferSource buffers, int light, int overlay) {
|
||||||
var contents = sieve.getContents();
|
var logic = sieve.getLogic();
|
||||||
|
var contents = logic.getContents();
|
||||||
|
|
||||||
if (!contents.isEmpty() && contents.getItem() instanceof BlockItem blockItem) {
|
if (!contents.isEmpty() && contents.getItem() instanceof BlockItem blockItem) {
|
||||||
var block = blockItem.getBlock();
|
var block = blockItem.getBlock();
|
||||||
var percentage = sieve.getProgress();
|
var percentage = logic.getProgress();
|
||||||
var face = RenderUtil.getTopFace(block);
|
var face = RenderUtil.getTopFace(block);
|
||||||
face.renderFlatSpriteLerp(buffers, stack, percentage, 0xff, 0xff, 0xff, light, 1.0f, 15f, 13f);
|
face.renderFlatSpriteLerp(buffers, stack, percentage, 0xff, 0xff, 0xff, light, 1.0f, 15f, 13f);
|
||||||
}
|
}
|
||||||
|
|
||||||
var mesh = sieve.getMesh();
|
var mesh = logic.getMesh();
|
||||||
|
|
||||||
if (!mesh.isEmpty()) {
|
if (!mesh.isEmpty()) {
|
||||||
var builder = buffers.getBuffer(RenderType.cutoutMipped());
|
var builder = buffers.getBuffer(RenderType.cutoutMipped());
|
||||||
|
|
@ -57,7 +59,8 @@ public class SieveRenderer<T extends AbstractSieveBlockEntity> implements BlockE
|
||||||
if (MESH_TEXTURES.containsKey(meshItem)) {
|
if (MESH_TEXTURES.containsKey(meshItem)) {
|
||||||
meshSprite = MESH_TEXTURES.get(meshItem);
|
meshSprite = MESH_TEXTURES.get(meshItem);
|
||||||
} else {
|
} else {
|
||||||
ResourceLocation registryName = ForgeRegistries.ITEMS.getKey(meshItem);
|
@SuppressWarnings("deprecation")
|
||||||
|
ResourceLocation registryName = BuiltInRegistries.ITEM.getKey(meshItem);
|
||||||
ResourceLocation textureLoc = registryName.withPrefix("item/mesh/");
|
ResourceLocation textureLoc = registryName.withPrefix("item/mesh/");
|
||||||
meshSprite = RenderUtil.blockAtlas.getSprite(textureLoc);
|
meshSprite = RenderUtil.blockAtlas.getSprite(textureLoc);
|
||||||
MESH_TEXTURES.put(meshItem, meshSprite);
|
MESH_TEXTURES.put(meshItem, meshSprite);
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,7 @@ import net.minecraftforge.fluids.FluidStack;
|
||||||
import net.minecraftforge.fml.ModList;
|
import net.minecraftforge.fml.ModList;
|
||||||
import thedarkcolour.exdeorum.ExDeorum;
|
import thedarkcolour.exdeorum.ExDeorum;
|
||||||
import thedarkcolour.exdeorum.blockentity.LavaCrucibleBlockEntity;
|
import thedarkcolour.exdeorum.blockentity.LavaCrucibleBlockEntity;
|
||||||
|
import thedarkcolour.exdeorum.client.screen.MechanicalHammerScreen;
|
||||||
import thedarkcolour.exdeorum.client.screen.MechanicalSieveScreen;
|
import thedarkcolour.exdeorum.client.screen.MechanicalSieveScreen;
|
||||||
import thedarkcolour.exdeorum.compat.GroupedSieveRecipe;
|
import thedarkcolour.exdeorum.compat.GroupedSieveRecipe;
|
||||||
import thedarkcolour.exdeorum.compat.ModIds;
|
import thedarkcolour.exdeorum.compat.ModIds;
|
||||||
|
|
@ -214,6 +215,7 @@ public class ExDeorumJeiPlugin implements IModPlugin {
|
||||||
registration.addRecipeCatalyst(new ItemStack(EItems.IRON_HAMMER.get()), HAMMER);
|
registration.addRecipeCatalyst(new ItemStack(EItems.IRON_HAMMER.get()), HAMMER);
|
||||||
registration.addRecipeCatalyst(new ItemStack(EItems.DIAMOND_HAMMER.get()), HAMMER);
|
registration.addRecipeCatalyst(new ItemStack(EItems.DIAMOND_HAMMER.get()), HAMMER);
|
||||||
registration.addRecipeCatalyst(new ItemStack(EItems.NETHERITE_HAMMER.get()), HAMMER);
|
registration.addRecipeCatalyst(new ItemStack(EItems.NETHERITE_HAMMER.get()), HAMMER);
|
||||||
|
registration.addRecipeCatalyst(new ItemStack(EItems.MECHANICAL_HAMMER.get()), HAMMER);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -231,6 +233,7 @@ public class ExDeorumJeiPlugin implements IModPlugin {
|
||||||
registration.addItemStackInfo(new ItemStack(EItems.CRIMSON_NYLIUM_SPORES.get()), Component.translatable(TranslationKeys.CRIMSON_NYLIUM_SPORES_JEI_INFO));
|
registration.addItemStackInfo(new ItemStack(EItems.CRIMSON_NYLIUM_SPORES.get()), Component.translatable(TranslationKeys.CRIMSON_NYLIUM_SPORES_JEI_INFO));
|
||||||
registration.addItemStackInfo(new ItemStack(EItems.SCULK_CORE.get()), Component.translatable(TranslationKeys.SCULK_CORE_JEI_INFO));
|
registration.addItemStackInfo(new ItemStack(EItems.SCULK_CORE.get()), Component.translatable(TranslationKeys.SCULK_CORE_JEI_INFO));
|
||||||
registration.addItemStackInfo(new ItemStack(EItems.MECHANICAL_SIEVE.get()), Component.translatable(TranslationKeys.MECHANICAL_SIEVE_JEI_INFO));
|
registration.addItemStackInfo(new ItemStack(EItems.MECHANICAL_SIEVE.get()), Component.translatable(TranslationKeys.MECHANICAL_SIEVE_JEI_INFO));
|
||||||
|
registration.addItemStackInfo(new ItemStack(EItems.MECHANICAL_HAMMER.get()), Component.translatable(TranslationKeys.MECHANICAL_HAMMER_JEI_INFO));
|
||||||
|
|
||||||
var toRemove = new ArrayList<ItemStack>();
|
var toRemove = new ArrayList<ItemStack>();
|
||||||
|
|
||||||
|
|
@ -322,6 +325,22 @@ public class ExDeorumJeiPlugin implements IModPlugin {
|
||||||
return List.of();
|
return List.of();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
registration.addGuiContainerHandler(MechanicalHammerScreen.class, new IGuiContainerHandler<>() {
|
||||||
|
@Override
|
||||||
|
public Collection<IGuiClickableArea> getGuiClickableAreas(MechanicalHammerScreen containerScreen, double mouseX, double mouseY) {
|
||||||
|
IGuiClickableArea clickableArea = IGuiClickableArea.createBasic(MechanicalHammerScreen.RECIPE_CLICK_AREA_POS_X, MechanicalHammerScreen.RECIPE_CLICK_AREA_POS_Y, MechanicalHammerScreen.RECIPE_CLICK_AREA_WIDTH, MechanicalHammerScreen.RECIPE_CLICK_AREA_HEIGHT, HAMMER);
|
||||||
|
return List.of(clickableArea);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Rect2i> getGuiExtraAreas(MechanicalHammerScreen containerScreen) {
|
||||||
|
var widget = containerScreen.getRedstoneControlWidget();
|
||||||
|
if (widget != null) {
|
||||||
|
return widget.getJeiBounds();
|
||||||
|
}
|
||||||
|
return List.of();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private static <C extends Container, T extends Recipe<C>> void addRecipes(IRecipeRegistration registration, RecipeType<T> category, Supplier<net.minecraft.world.item.crafting.RecipeType<T>> type) {
|
private static <C extends Container, T extends Recipe<C>> void addRecipes(IRecipeRegistration registration, RecipeType<T> category, Supplier<net.minecraft.world.item.crafting.RecipeType<T>> type) {
|
||||||
|
|
|
||||||
|
|
@ -80,14 +80,15 @@ public class ExDeorumInfoProvider implements IProbeInfoProvider {
|
||||||
info.tank(crucible.getTank());
|
info.tank(crucible.getTank());
|
||||||
}
|
}
|
||||||
} else if (te instanceof SieveBlockEntity sieve) {
|
} else if (te instanceof SieveBlockEntity sieve) {
|
||||||
if (!sieve.getContents().isEmpty()) {
|
var logic = sieve.getLogic();
|
||||||
info.text(CompoundText.create().style(TextStyleClass.LABEL).text("Progress: ").style(TextStyleClass.WARNING).text((Math.round(1000 * sieve.getProgress()) / 10) + "%"));
|
if (!logic.getContents().isEmpty()) {
|
||||||
|
info.text(CompoundText.create().style(TextStyleClass.LABEL).text("Progress: ").style(TextStyleClass.WARNING).text((Math.round(1000 * logic.getProgress()) / 10) + "%"));
|
||||||
}
|
}
|
||||||
if (playerEntity.isShiftKeyDown()) {
|
if (playerEntity.isShiftKeyDown()) {
|
||||||
var mesh = sieve.getMesh();
|
var mesh = logic.getMesh();
|
||||||
info.horizontal(info.defaultLayoutStyle().spacing(10).alignment(ElementAlignment.ALIGN_CENTER))
|
info.horizontal(info.defaultLayoutStyle().spacing(10).alignment(ElementAlignment.ALIGN_CENTER))
|
||||||
.item(sieve.getMesh(), info.defaultItemStyle().width(16).height(16))
|
.item(mesh, info.defaultItemStyle().width(16).height(16))
|
||||||
.text(CompoundText.create().info(sieve.getMesh().getDescriptionId()));
|
.text(CompoundText.create().info(mesh.getDescriptionId()));
|
||||||
if (mesh.isEnchanted()) {
|
if (mesh.isEnchanted()) {
|
||||||
var list = new ObjectArrayList<Component>();
|
var list = new ObjectArrayList<Component>();
|
||||||
var style = info.defaultTextStyle().height(10);
|
var style = info.defaultTextStyle().height(10);
|
||||||
|
|
|
||||||
|
|
@ -133,6 +133,8 @@ public class EConfig {
|
||||||
public final BooleanValue allowWitchWaterEntityConversion;
|
public final BooleanValue allowWitchWaterEntityConversion;
|
||||||
public final IntValue mechanicalSieveEnergyStorage;
|
public final IntValue mechanicalSieveEnergyStorage;
|
||||||
public final IntValue mechanicalSieveEnergyConsumption;
|
public final IntValue mechanicalSieveEnergyConsumption;
|
||||||
|
public final IntValue mechanicalHammerEnergyStorage;
|
||||||
|
public final IntValue mechanicalHammerEnergyConsumption;
|
||||||
|
|
||||||
public Server(ForgeConfigSpec.Builder builder) {
|
public Server(ForgeConfigSpec.Builder builder) {
|
||||||
builder.comment("Server configuration for Ex Deorum").push("server");
|
builder.comment("Server configuration for Ex Deorum").push("server");
|
||||||
|
|
@ -179,6 +181,12 @@ public class EConfig {
|
||||||
this.mechanicalSieveEnergyConsumption = builder
|
this.mechanicalSieveEnergyConsumption = builder
|
||||||
.comment("The amount of FE/t a tick consumed by the mechanical sieve when sifting a block.")
|
.comment("The amount of FE/t a tick consumed by the mechanical sieve when sifting a block.")
|
||||||
.defineInRange("mechanical_sieve_energy_consumption", 40, 0, Integer.MAX_VALUE);
|
.defineInRange("mechanical_sieve_energy_consumption", 40, 0, Integer.MAX_VALUE);
|
||||||
|
this.mechanicalHammerEnergyStorage = builder
|
||||||
|
.comment("The maximum amount of FE the mechanical hammer can have in its energy storage.")
|
||||||
|
.defineInRange("mechanical_hammer_energy_storage", 40_000, 0, Integer.MAX_VALUE);
|
||||||
|
this.mechanicalHammerEnergyConsumption = builder
|
||||||
|
.comment("The amount of FE/t a tick consumed by the mechanical hammer when crushing a block.")
|
||||||
|
.defineInRange("mechanical_hammer_energy_consumption", 20, 0, Integer.MAX_VALUE);
|
||||||
|
|
||||||
builder.pop();
|
builder.pop();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -65,6 +65,11 @@ class BlockLoot extends BlockLootSubProvider {
|
||||||
.setRolls(ConstantValue.exactly(1.0F))
|
.setRolls(ConstantValue.exactly(1.0F))
|
||||||
.add(LootItem.lootTableItem(EItems.MECHANICAL_SIEVE.get())
|
.add(LootItem.lootTableItem(EItems.MECHANICAL_SIEVE.get())
|
||||||
.apply(MachineLootFunction.machineLoot())))));
|
.apply(MachineLootFunction.machineLoot())))));
|
||||||
|
add(EBlocks.MECHANICAL_HAMMER.get(), LootTable.lootTable()
|
||||||
|
.withPool(applyExplosionCondition(EItems.MECHANICAL_HAMMER.get(), LootPool.lootPool()
|
||||||
|
.setRolls(ConstantValue.exactly(1.0F))
|
||||||
|
.add(LootItem.lootTableItem(EItems.MECHANICAL_HAMMER.get())
|
||||||
|
.apply(MachineLootFunction.machineLoot())))));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ class English {
|
||||||
english.add(TranslationKeys.VOID_WORLD_TYPE, "Void World");
|
english.add(TranslationKeys.VOID_WORLD_TYPE, "Void World");
|
||||||
english.add(TranslationKeys.FRACTION_DISPLAY, ": %s / %s");
|
english.add(TranslationKeys.FRACTION_DISPLAY, ": %s / %s");
|
||||||
english.add(TranslationKeys.MECHANICAL_SIEVE_MESH_LABEL, "Mesh: ");
|
english.add(TranslationKeys.MECHANICAL_SIEVE_MESH_LABEL, "Mesh: ");
|
||||||
|
english.add(TranslationKeys.MECHANICAL_HAMMER_HAMMER_LABEL, "Hammer: ");
|
||||||
english.add(TranslationKeys.ENERGY, "Energy");
|
english.add(TranslationKeys.ENERGY, "Energy");
|
||||||
|
|
||||||
english.add(TranslationKeys.ROOT_ADVANCEMENT_TITLE, "Don't Look Down...");
|
english.add(TranslationKeys.ROOT_ADVANCEMENT_TITLE, "Don't Look Down...");
|
||||||
|
|
@ -55,6 +56,7 @@ class English {
|
||||||
english.add(TranslationKeys.CRIMSON_NYLIUM_SPORES_JEI_INFO, "Use on netherrack to turn it into a crimson nylium block.");
|
english.add(TranslationKeys.CRIMSON_NYLIUM_SPORES_JEI_INFO, "Use on netherrack to turn it into a crimson nylium block.");
|
||||||
english.add(TranslationKeys.SCULK_CORE_JEI_INFO, "Use a sculk core on a Sculk Shrieker to enable it to spawn Wardens. Normally, Sculk Shriekers placed by players cannot spawn Wardens, so this item is useful for obtaining Sculk items in a SkyBlock world.");
|
english.add(TranslationKeys.SCULK_CORE_JEI_INFO, "Use a sculk core on a Sculk Shrieker to enable it to spawn Wardens. Normally, Sculk Shriekers placed by players cannot spawn Wardens, so this item is useful for obtaining Sculk items in a SkyBlock world.");
|
||||||
english.add(TranslationKeys.MECHANICAL_SIEVE_JEI_INFO, "The Mechanical Sieve is a machine that, when supplied with a mesh and Forge Energy (FE), will sift blocks without a player having to do it themselves. It also supports three different modes of redstone control. Since Ex Deorum does not provide a way to generate FE, you will need another mod to provide power.");
|
english.add(TranslationKeys.MECHANICAL_SIEVE_JEI_INFO, "The Mechanical Sieve is a machine that, when supplied with a mesh and Forge Energy (FE), will sift blocks without a player having to do it themselves. It also supports three different modes of redstone control. Since Ex Deorum does not provide a way to generate FE, you will need another mod to provide power.");
|
||||||
|
english.add(TranslationKeys.MECHANICAL_HAMMER_JEI_INFO, "The Mechanical Hammer is a machine that, when supplied with Forge Energy (FE), will hammer blocks without a player having to do it themselves. It can operate without a hammer, but adding any hammer will double the speed, and efficiency enchantments on the hammer will further increase speed. It also supports three different modes of redstone control. Since Ex Deorum does not provide a way to generate FE, you will need another mod to provide power.");
|
||||||
|
|
||||||
english.add(TranslationKeys.BARREL_COMPOST_CATEGORY_TITLE, "Barrel Compost");
|
english.add(TranslationKeys.BARREL_COMPOST_CATEGORY_TITLE, "Barrel Compost");
|
||||||
english.add(TranslationKeys.BARREL_COMPOST_RECIPE_VOLUME, "Compost: %s");
|
english.add(TranslationKeys.BARREL_COMPOST_RECIPE_VOLUME, "Compost: %s");
|
||||||
|
|
@ -79,6 +81,7 @@ class English {
|
||||||
english.add(TranslationKeys.REDSTONE_CONTROL_MODES[RedstoneControlWidget.REDSTONE_MODE_POWERED], "Powered");
|
english.add(TranslationKeys.REDSTONE_CONTROL_MODES[RedstoneControlWidget.REDSTONE_MODE_POWERED], "Powered");
|
||||||
english.add(TranslationKeys.REDSTONE_CONTROL_LABEL, "Redstone Mode");
|
english.add(TranslationKeys.REDSTONE_CONTROL_LABEL, "Redstone Mode");
|
||||||
english.add(TranslationKeys.REDSTONE_CONTROL_MODE, "Mode: ");
|
english.add(TranslationKeys.REDSTONE_CONTROL_MODE, "Mode: ");
|
||||||
|
english.add(TranslationKeys.MECHANICAL_HAMMER_SCREEN_TITLE, "Mechanical Hammer");
|
||||||
|
|
||||||
english.addBlock(EBlocks.VEXING_ARCHWOOD_CRUCIBLE, "Vexing Archwood Crucible");
|
english.addBlock(EBlocks.VEXING_ARCHWOOD_CRUCIBLE, "Vexing Archwood Crucible");
|
||||||
english.addBlock(EBlocks.CASCADING_ARCHWOOD_CRUCIBLE, "Cascading Archwood Crucible");
|
english.addBlock(EBlocks.CASCADING_ARCHWOOD_CRUCIBLE, "Cascading Archwood Crucible");
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ public class TranslationKeys {
|
||||||
// ": %s / %s"
|
// ": %s / %s"
|
||||||
public static final String FRACTION_DISPLAY = "item." + ExDeorum.ID + ".watering_can_fluid_display";
|
public static final String FRACTION_DISPLAY = "item." + ExDeorum.ID + ".watering_can_fluid_display";
|
||||||
public static final String MECHANICAL_SIEVE_MESH_LABEL = "item." + ExDeorum.ID + ".mechanical_sieve.mesh_label";
|
public static final String MECHANICAL_SIEVE_MESH_LABEL = "item." + ExDeorum.ID + ".mechanical_sieve.mesh_label";
|
||||||
|
public static final String MECHANICAL_HAMMER_HAMMER_LABEL = "item." + ExDeorum.ID + ".mechanical_hammer.hammer_label";
|
||||||
public static final String ENERGY = "gui." + ExDeorum.ID + ".energy_label";
|
public static final String ENERGY = "gui." + ExDeorum.ID + ".energy_label";
|
||||||
|
|
||||||
// Advancements
|
// Advancements
|
||||||
|
|
@ -53,6 +54,7 @@ public class TranslationKeys {
|
||||||
public static final String CRIMSON_NYLIUM_SPORES_JEI_INFO = "info." + ExDeorum.ID + ".crimson_nylium_spores";
|
public static final String CRIMSON_NYLIUM_SPORES_JEI_INFO = "info." + ExDeorum.ID + ".crimson_nylium_spores";
|
||||||
public static final String SCULK_CORE_JEI_INFO = "info." + ExDeorum.ID + ".sculk_core";
|
public static final String SCULK_CORE_JEI_INFO = "info." + ExDeorum.ID + ".sculk_core";
|
||||||
public static final String MECHANICAL_SIEVE_JEI_INFO = "info." + ExDeorum.ID + ".mechanical_sieve";
|
public static final String MECHANICAL_SIEVE_JEI_INFO = "info." + ExDeorum.ID + ".mechanical_sieve";
|
||||||
|
public static final String MECHANICAL_HAMMER_JEI_INFO = "info." + ExDeorum.ID + ".mechanical_hammer";
|
||||||
|
|
||||||
// JEI recipe categories
|
// JEI recipe categories
|
||||||
public static final String BARREL_COMPOST_CATEGORY_TITLE = "gui." + ExDeorum.ID + ".category.barrel_compost";
|
public static final String BARREL_COMPOST_CATEGORY_TITLE = "gui." + ExDeorum.ID + ".category.barrel_compost";
|
||||||
|
|
@ -81,4 +83,5 @@ public class TranslationKeys {
|
||||||
};
|
};
|
||||||
public static final String REDSTONE_CONTROL_LABEL = "gui." + ExDeorum.ID + ".redstone_control.label";
|
public static final String REDSTONE_CONTROL_LABEL = "gui." + ExDeorum.ID + ".redstone_control.label";
|
||||||
public static final String REDSTONE_CONTROL_MODE = "gui." + ExDeorum.ID + ".redstone_control.mode";
|
public static final String REDSTONE_CONTROL_MODE = "gui." + ExDeorum.ID + ".redstone_control.mode";
|
||||||
|
public static final String MECHANICAL_HAMMER_SCREEN_TITLE = ExDeorum.ID + ".container.mechanical_hammer";
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -293,6 +293,16 @@ public class Recipes {
|
||||||
recipe.pattern("I I");
|
recipe.pattern("I I");
|
||||||
MKRecipeProvider.unlockedByHaving(recipe, Items.HOPPER);
|
MKRecipeProvider.unlockedByHaving(recipe, Items.HOPPER);
|
||||||
});
|
});
|
||||||
|
recipes.shapedCrafting(RecipeCategory.MISC, EItems.MECHANICAL_HAMMER.get(), recipe -> {
|
||||||
|
recipe.define('#', Items.IRON_BLOCK);
|
||||||
|
recipe.define('H', Items.HOPPER);
|
||||||
|
recipe.define('T', EItemTags.HAMMERS);
|
||||||
|
recipe.define('I', Items.IRON_INGOT);
|
||||||
|
recipe.pattern("III");
|
||||||
|
recipe.pattern("ITI");
|
||||||
|
recipe.pattern("#H#");
|
||||||
|
MKRecipeProvider.unlockedByHaving(recipe, Items.HOPPER);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void modUShaped(MKRecipeProvider recipes, String modid, RegistryObject<? extends Item> sides, RegistryObject<? extends Item> middle, RegistryObject<? extends Item> result) {
|
private static void modUShaped(MKRecipeProvider recipes, String modid, RegistryObject<? extends Item> sides, RegistryObject<? extends Item> middle, RegistryObject<? extends Item> result) {
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ package thedarkcolour.exdeorum.loot;
|
||||||
import com.mojang.serialization.Codec;
|
import com.mojang.serialization.Codec;
|
||||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||||
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
||||||
|
import net.minecraft.util.RandomSource;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
import net.minecraft.world.item.Items;
|
import net.minecraft.world.item.Items;
|
||||||
import net.minecraft.world.item.enchantment.Enchantments;
|
import net.minecraft.world.item.enchantment.Enchantments;
|
||||||
|
|
@ -56,22 +57,8 @@ public class HammerLootModifier extends LootModifier {
|
||||||
|
|
||||||
// fortune handling; more likely to boost drops if there are none to begin with
|
// fortune handling; more likely to boost drops if there are none to begin with
|
||||||
if (context.hasParam(LootContextParams.TOOL)) {
|
if (context.hasParam(LootContextParams.TOOL)) {
|
||||||
var stack = context.getParam(LootContextParams.TOOL);
|
var hammer = context.getParam(LootContextParams.TOOL);
|
||||||
var fortune = stack.getEnchantmentLevel(Enchantments.BLOCK_FORTUNE);
|
resultAmount += calculateFortuneBonus(hammer, context.getRandom(), resultAmount == 0);
|
||||||
|
|
||||||
if (fortune != 0) {
|
|
||||||
var chance = context.getRandom().nextFloat();
|
|
||||||
|
|
||||||
if (resultAmount == 0) {
|
|
||||||
if (chance < 0.06 * fortune) {
|
|
||||||
resultAmount++;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (chance < 0.03 * fortune) {
|
|
||||||
resultAmount++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (resultAmount > 0) {
|
if (resultAmount > 0) {
|
||||||
|
|
@ -89,5 +76,32 @@ public class HammerLootModifier extends LootModifier {
|
||||||
public Codec<? extends IGlobalLootModifier> codec() {
|
public Codec<? extends IGlobalLootModifier> codec() {
|
||||||
return CODEC;
|
return CODEC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the bonus number of drops for a hammer enchanted with fortune.
|
||||||
|
* @param hammer The hammer in question
|
||||||
|
* @param rand RNG
|
||||||
|
* @param zeroBaseDrops Whether there were no drops to begin with
|
||||||
|
* @return The additional number of drops, to be added to the number of base drops
|
||||||
|
*/
|
||||||
|
public static int calculateFortuneBonus(ItemStack hammer, RandomSource rand, boolean zeroBaseDrops) {
|
||||||
|
var fortune = hammer.getEnchantmentLevel(Enchantments.BLOCK_FORTUNE);
|
||||||
|
|
||||||
|
if (fortune != 0) {
|
||||||
|
var chance = rand.nextFloat();
|
||||||
|
|
||||||
|
if (zeroBaseDrops) {
|
||||||
|
if (chance < 0.06f * fortune) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (chance < 0.03f * fortune) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,121 @@
|
||||||
|
/*
|
||||||
|
* Ex Deorum
|
||||||
|
* Copyright (c) 2024 thedarkcolour
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program 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 General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package thedarkcolour.exdeorum.menu;
|
||||||
|
|
||||||
|
import net.minecraft.network.FriendlyByteBuf;
|
||||||
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
|
import net.minecraft.world.entity.player.Inventory;
|
||||||
|
import net.minecraft.world.entity.player.Player;
|
||||||
|
import net.minecraft.world.inventory.AbstractContainerMenu;
|
||||||
|
import net.minecraft.world.inventory.MenuType;
|
||||||
|
import net.minecraft.world.inventory.Slot;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import thedarkcolour.exdeorum.blockentity.AbstractMachineBlockEntity;
|
||||||
|
import thedarkcolour.exdeorum.network.NetworkHandler;
|
||||||
|
|
||||||
|
public abstract class AbstractMachineMenu<M extends AbstractMachineBlockEntity<M>> extends AbstractContainerMenu {
|
||||||
|
protected static final int PLAYER_SLOTS = 36; // hotbar + inventory
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private final ServerPlayer player;
|
||||||
|
public final M machine;
|
||||||
|
|
||||||
|
public int prevEnergy;
|
||||||
|
|
||||||
|
protected AbstractMachineMenu(MenuType<?> pMenuType, int pContainerId, Inventory playerInventory, M machine) {
|
||||||
|
super(pMenuType, pContainerId);
|
||||||
|
|
||||||
|
this.machine = machine;
|
||||||
|
|
||||||
|
if (playerInventory.player instanceof ServerPlayer serverPlayer) {
|
||||||
|
this.player = serverPlayer;
|
||||||
|
} else {
|
||||||
|
this.player = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// todo find a better way to do this
|
||||||
|
@SuppressWarnings({"DataFlowIssue", "unchecked"})
|
||||||
|
protected static <M extends AbstractMachineBlockEntity<M>> M readPayload(Inventory playerInventory, FriendlyByteBuf data) {
|
||||||
|
var machine = (M) playerInventory.player.level().getBlockEntity(data.readBlockPos());
|
||||||
|
machine.setRedstoneMode(data.readByte());
|
||||||
|
return machine;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call after own slots have been added
|
||||||
|
protected final void addPlayerSlots(Inventory playerInventory, int startY) {
|
||||||
|
// Inventory
|
||||||
|
for (int i = 0; i < 3; ++i) {
|
||||||
|
for (int j = 0; j < 9; ++j) {
|
||||||
|
addSlot(new Slot(playerInventory, j + i * 9 + 9, 8 + j * 18, startY + i * 18));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Hotbar
|
||||||
|
for (int k = 0; k < 9; ++k) {
|
||||||
|
addSlot(new Slot(playerInventory, k, 8 + k * 18, startY + 58));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// When the server sends a menu property message, the client handles the synced property here.
|
||||||
|
public void setClientProperty(int index, int value) {
|
||||||
|
if (index == 0) {
|
||||||
|
this.prevEnergy = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void broadcastChanges() {
|
||||||
|
super.broadcastChanges();
|
||||||
|
|
||||||
|
if (this.player != null) {
|
||||||
|
syncProperties(this.player);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void broadcastFullState() {
|
||||||
|
super.broadcastFullState();
|
||||||
|
|
||||||
|
if (this.player != null) {
|
||||||
|
syncProperties(this.player);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void syncProperties(ServerPlayer player) {
|
||||||
|
if (this.prevEnergy != this.machine.energy.getEnergyStored()) {
|
||||||
|
this.prevEnergy = this.machine.energy.getEnergyStored();
|
||||||
|
|
||||||
|
NetworkHandler.sendMenuProperty(player, this.containerId, 0, this.prevEnergy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean clickMenuButton(Player pPlayer, int id) {
|
||||||
|
if (0 <= id && id < 3) {
|
||||||
|
this.machine.setRedstoneMode(id);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean stillValid(Player player) {
|
||||||
|
return this.machine.stillValid(player);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,31 +0,0 @@
|
||||||
/*
|
|
||||||
* Ex Deorum
|
|
||||||
* Copyright (c) 2024 thedarkcolour
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program 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 General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package thedarkcolour.exdeorum.menu;
|
|
||||||
|
|
||||||
import net.minecraft.world.inventory.AbstractContainerMenu;
|
|
||||||
import net.minecraft.world.inventory.MenuType;
|
|
||||||
|
|
||||||
public abstract class EContainerMenu extends AbstractContainerMenu {
|
|
||||||
protected EContainerMenu(MenuType<?> pMenuType, int pContainerId) {
|
|
||||||
super(pMenuType, pContainerId);
|
|
||||||
}
|
|
||||||
|
|
||||||
// When the server sends a menu property message, the client handles the synced property here.
|
|
||||||
public abstract void setClientProperty(int index, int value);
|
|
||||||
}
|
|
||||||
|
|
@ -20,38 +20,24 @@ package thedarkcolour.exdeorum.menu;
|
||||||
|
|
||||||
import net.minecraft.network.FriendlyByteBuf;
|
import net.minecraft.network.FriendlyByteBuf;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.server.level.ServerPlayer;
|
|
||||||
import net.minecraft.world.entity.player.Inventory;
|
import net.minecraft.world.entity.player.Inventory;
|
||||||
import net.minecraft.world.entity.player.Player;
|
import net.minecraft.world.entity.player.Player;
|
||||||
import net.minecraft.world.inventory.InventoryMenu;
|
import net.minecraft.world.inventory.InventoryMenu;
|
||||||
import net.minecraft.world.inventory.Slot;
|
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
import thedarkcolour.exdeorum.ExDeorum;
|
import thedarkcolour.exdeorum.ExDeorum;
|
||||||
import thedarkcolour.exdeorum.blockentity.MechanicalSieveBlockEntity;
|
import thedarkcolour.exdeorum.blockentity.MechanicalSieveBlockEntity;
|
||||||
import thedarkcolour.exdeorum.network.NetworkHandler;
|
|
||||||
import thedarkcolour.exdeorum.registry.EMenus;
|
import thedarkcolour.exdeorum.registry.EMenus;
|
||||||
|
|
||||||
public class MechanicalSieveMenu extends EContainerMenu {
|
public class MechanicalSieveMenu extends AbstractMachineMenu<MechanicalSieveBlockEntity> {
|
||||||
private static final ResourceLocation EMPTY_SLOT_MESH = new ResourceLocation(ExDeorum.ID, "item/empty_slot_mesh");
|
private static final ResourceLocation EMPTY_SLOT_MESH = new ResourceLocation(ExDeorum.ID, "item/empty_slot_mesh");
|
||||||
private static final int NUM_SLOTS = 22; // input + mesh, 20 output slots
|
private static final int NUM_SLOTS = 22; // input + mesh, 20 output slots
|
||||||
private static final int PLAYER_SLOTS = 36; // hotbar + inventory
|
|
||||||
|
|
||||||
public final MechanicalSieveBlockEntity sieve;
|
|
||||||
@Nullable
|
|
||||||
private final ServerPlayer player;
|
|
||||||
|
|
||||||
public int prevSieveEnergy;
|
|
||||||
|
|
||||||
public MechanicalSieveMenu(int containerId, Inventory playerInventory, FriendlyByteBuf data) {
|
public MechanicalSieveMenu(int containerId, Inventory playerInventory, FriendlyByteBuf data) {
|
||||||
this(containerId, playerInventory, (MechanicalSieveBlockEntity) playerInventory.player.level().getBlockEntity(data.readBlockPos()));
|
this(containerId, playerInventory, (MechanicalSieveBlockEntity) readPayload(playerInventory, data));
|
||||||
this.sieve.setRedstoneMode(data.readByte());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public MechanicalSieveMenu(int containerId, Inventory playerInventory, MechanicalSieveBlockEntity sieve) {
|
public MechanicalSieveMenu(int containerId, Inventory playerInventory, MechanicalSieveBlockEntity sieve) {
|
||||||
super(EMenus.MECHANICAL_SIEVE.get(), containerId);
|
super(EMenus.MECHANICAL_SIEVE.get(), containerId, playerInventory, sieve);
|
||||||
|
|
||||||
this.sieve = sieve;
|
|
||||||
|
|
||||||
// input slot
|
// input slot
|
||||||
addSlot(sieve.inventory.createSlot(0, 26, 30));
|
addSlot(sieve.inventory.createSlot(0, 26, 30));
|
||||||
|
|
@ -63,54 +49,7 @@ public class MechanicalSieveMenu extends EContainerMenu {
|
||||||
addSlot(sieve.inventory.createSlot(2 + r * 5 + c, 80 + c * 18, 15 + r * 18));
|
addSlot(sieve.inventory.createSlot(2 + r * 5 + c, 80 + c * 18, 15 + r * 18));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Player slots
|
addPlayerSlots(playerInventory, 91);
|
||||||
for (int i = 0; i < 3; ++i) {
|
|
||||||
for (int j = 0; j < 9; ++j) {
|
|
||||||
addSlot(new Slot(playerInventory, j + i * 9 + 9, 8 + j * 18, 7 + 84 + i * 18));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (int k = 0; k < 9; ++k) {
|
|
||||||
addSlot(new Slot(playerInventory, k, 8 + k * 18, 149));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (playerInventory.player instanceof ServerPlayer serverPlayer) {
|
|
||||||
this.player = serverPlayer;
|
|
||||||
} else {
|
|
||||||
this.player = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void broadcastChanges() {
|
|
||||||
super.broadcastChanges();
|
|
||||||
|
|
||||||
if (this.player != null) {
|
|
||||||
if (this.prevSieveEnergy != this.sieve.energy.getEnergyStored()) {
|
|
||||||
this.prevSieveEnergy = this.sieve.energy.getEnergyStored();
|
|
||||||
|
|
||||||
NetworkHandler.sendMenuProperty(this.player, this.containerId, 0, this.prevSieveEnergy);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void broadcastFullState() {
|
|
||||||
super.broadcastFullState();
|
|
||||||
|
|
||||||
if (this.player != null) {
|
|
||||||
if (this.prevSieveEnergy != this.sieve.energy.getEnergyStored()) {
|
|
||||||
this.prevSieveEnergy = this.sieve.energy.getEnergyStored();
|
|
||||||
|
|
||||||
NetworkHandler.sendMenuProperty(this.player, this.containerId, 0, this.prevSieveEnergy);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setClientProperty(int index, int value) {
|
|
||||||
if (index == 0) {
|
|
||||||
this.prevSieveEnergy = value;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -130,11 +69,11 @@ public class MechanicalSieveMenu extends EContainerMenu {
|
||||||
if (!moveItemStackTo(clickedStack, NUM_SLOTS, NUM_SLOTS + PLAYER_SLOTS, false)) {
|
if (!moveItemStackTo(clickedStack, NUM_SLOTS, NUM_SLOTS + PLAYER_SLOTS, false)) {
|
||||||
return ItemStack.EMPTY;
|
return ItemStack.EMPTY;
|
||||||
}
|
}
|
||||||
} else if (this.sieve.getLogic().isValidInput(clickedStack)) { // attempting to move into input slot
|
} else if (this.machine.getLogic().isValidInput(clickedStack)) { // attempting to move into input slot
|
||||||
if (!moveItemStackTo(clickedStack, 0, 1, false)) {
|
if (!moveItemStackTo(clickedStack, 0, 1, false)) {
|
||||||
return ItemStack.EMPTY;
|
return ItemStack.EMPTY;
|
||||||
}
|
}
|
||||||
} else if (this.sieve.getLogic().isValidMesh(clickedStack)) { // attempting to move into mesh slot
|
} else if (this.machine.getLogic().isValidMesh(clickedStack)) { // attempting to move into mesh slot
|
||||||
if (!moveItemStackTo(clickedStack, 1, 2, false)) {
|
if (!moveItemStackTo(clickedStack, 1, 2, false)) {
|
||||||
return ItemStack.EMPTY;
|
return ItemStack.EMPTY;
|
||||||
}
|
}
|
||||||
|
|
@ -161,18 +100,4 @@ public class MechanicalSieveMenu extends EContainerMenu {
|
||||||
|
|
||||||
return stack;
|
return stack;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean clickMenuButton(Player player, int id) {
|
|
||||||
if (0 <= id && id < 3) {
|
|
||||||
this.sieve.setRedstoneMode(id);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean stillValid(Player player) {
|
|
||||||
return this.sieve.stillValid(player);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ import net.minecraft.client.multiplayer.ClientLevel;
|
||||||
import net.minecraft.world.entity.player.Player;
|
import net.minecraft.world.entity.player.Player;
|
||||||
import thedarkcolour.exdeorum.blockentity.EBlockEntity;
|
import thedarkcolour.exdeorum.blockentity.EBlockEntity;
|
||||||
import thedarkcolour.exdeorum.client.ClientHandler;
|
import thedarkcolour.exdeorum.client.ClientHandler;
|
||||||
import thedarkcolour.exdeorum.menu.EContainerMenu;
|
import thedarkcolour.exdeorum.menu.AbstractMachineMenu;
|
||||||
|
|
||||||
public class ClientMessageHandler {
|
public class ClientMessageHandler {
|
||||||
public static boolean isInVoidWorld;
|
public static boolean isInVoidWorld;
|
||||||
|
|
@ -54,7 +54,7 @@ public class ClientMessageHandler {
|
||||||
public static void handleMenuProperty(MenuPropertyMessage msg) {
|
public static void handleMenuProperty(MenuPropertyMessage msg) {
|
||||||
Player player = Minecraft.getInstance().player;
|
Player player = Minecraft.getInstance().player;
|
||||||
|
|
||||||
if (player != null && player.containerMenu instanceof EContainerMenu menu && menu.containerId == msg.containerId()) {
|
if (player != null && player.containerMenu instanceof AbstractMachineMenu menu && menu.containerId == msg.containerId()) {
|
||||||
menu.setClientProperty(msg.index(), msg.value());
|
menu.setClientProperty(msg.index(), msg.value());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
||||||
import net.minecraft.core.registries.BuiltInRegistries;
|
import net.minecraft.core.registries.BuiltInRegistries;
|
||||||
import net.minecraft.network.FriendlyByteBuf;
|
import net.minecraft.network.FriendlyByteBuf;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
import net.minecraft.server.level.ServerLevel;
|
||||||
import net.minecraft.tags.TagKey;
|
import net.minecraft.tags.TagKey;
|
||||||
import net.minecraft.util.GsonHelper;
|
import net.minecraft.util.GsonHelper;
|
||||||
import net.minecraft.world.Container;
|
import net.minecraft.world.Container;
|
||||||
|
|
@ -36,7 +37,9 @@ import net.minecraft.world.item.crafting.RecipeManager;
|
||||||
import net.minecraft.world.item.crafting.RecipeType;
|
import net.minecraft.world.item.crafting.RecipeType;
|
||||||
import net.minecraft.world.level.material.Fluid;
|
import net.minecraft.world.level.material.Fluid;
|
||||||
import net.minecraft.world.level.material.Fluids;
|
import net.minecraft.world.level.material.Fluids;
|
||||||
|
import net.minecraft.world.level.storage.loot.LootContext;
|
||||||
import net.minecraft.world.level.storage.loot.LootDataType;
|
import net.minecraft.world.level.storage.loot.LootDataType;
|
||||||
|
import net.minecraft.world.level.storage.loot.LootParams;
|
||||||
import net.minecraft.world.level.storage.loot.providers.number.*;
|
import net.minecraft.world.level.storage.loot.providers.number.*;
|
||||||
import net.minecraftforge.common.crafting.CraftingHelper;
|
import net.minecraftforge.common.crafting.CraftingHelper;
|
||||||
import net.minecraftforge.fluids.FluidStack;
|
import net.minecraftforge.fluids.FluidStack;
|
||||||
|
|
@ -55,6 +58,7 @@ import thedarkcolour.exdeorum.registry.ERecipeTypes;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
public final class RecipeUtil {
|
public final class RecipeUtil {
|
||||||
|
|
@ -298,7 +302,12 @@ public final class RecipeUtil {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
public static boolean isTagEmpty(TagKey<Item> tag) {
|
public static boolean isTagEmpty(TagKey<Item> tag) {
|
||||||
return BuiltInRegistries.ITEM.getTag(tag).map(set -> !set.iterator().hasNext()).orElse(PreferredOres.getPreferredOre(tag) == Items.AIR);
|
return BuiltInRegistries.ITEM.getTag(tag).map(set -> !set.iterator().hasNext()).orElse(PreferredOres.getPreferredOre(tag) == Items.AIR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static LootContext emptyLootContext(ServerLevel level) {
|
||||||
|
return new LootContext.Builder(new LootParams(level, Map.of(), Map.of(), 0)).create(null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -87,6 +87,7 @@ public class SieveRecipe extends ProbabilityRecipe {
|
||||||
return new SieveRecipe(id, ingredient, mesh, result, resultAmount, byHandOnly);
|
return new SieveRecipe(id, ingredient, mesh, result, resultAmount, byHandOnly);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
@Override
|
@Override
|
||||||
public @Nullable SieveRecipe fromNetwork(ResourceLocation id, FriendlyByteBuf buffer) {
|
public @Nullable SieveRecipe fromNetwork(ResourceLocation id, FriendlyByteBuf buffer) {
|
||||||
Ingredient ingredient = Ingredient.fromNetwork(buffer);
|
Ingredient ingredient = Ingredient.fromNetwork(buffer);
|
||||||
|
|
@ -96,6 +97,7 @@ public class SieveRecipe extends ProbabilityRecipe {
|
||||||
return new SieveRecipe(id, ingredient, mesh, result, resultAmount, buffer.readBoolean());
|
return new SieveRecipe(id, ingredient, mesh, result, resultAmount, buffer.readBoolean());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
@Override
|
@Override
|
||||||
public void toNetwork(FriendlyByteBuf buffer, SieveRecipe recipe) {
|
public void toNetwork(FriendlyByteBuf buffer, SieveRecipe recipe) {
|
||||||
recipe.getIngredient().toNetwork(buffer);
|
recipe.getIngredient().toNetwork(buffer);
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ import thedarkcolour.exdeorum.ExDeorum;
|
||||||
import thedarkcolour.exdeorum.blockentity.BarrelBlockEntity;
|
import thedarkcolour.exdeorum.blockentity.BarrelBlockEntity;
|
||||||
import thedarkcolour.exdeorum.blockentity.InfestedLeavesBlockEntity;
|
import thedarkcolour.exdeorum.blockentity.InfestedLeavesBlockEntity;
|
||||||
import thedarkcolour.exdeorum.blockentity.LavaCrucibleBlockEntity;
|
import thedarkcolour.exdeorum.blockentity.LavaCrucibleBlockEntity;
|
||||||
|
import thedarkcolour.exdeorum.blockentity.MechanicalHammerBlockEntity;
|
||||||
import thedarkcolour.exdeorum.blockentity.MechanicalSieveBlockEntity;
|
import thedarkcolour.exdeorum.blockentity.MechanicalSieveBlockEntity;
|
||||||
import thedarkcolour.exdeorum.blockentity.SieveBlockEntity;
|
import thedarkcolour.exdeorum.blockentity.SieveBlockEntity;
|
||||||
import thedarkcolour.exdeorum.blockentity.WaterCrucibleBlockEntity;
|
import thedarkcolour.exdeorum.blockentity.WaterCrucibleBlockEntity;
|
||||||
|
|
@ -156,4 +157,5 @@ public class EBlockEntities {
|
||||||
EBlocks.CRYSTALLIZED_SIEVE.get()
|
EBlocks.CRYSTALLIZED_SIEVE.get()
|
||||||
).build(null));
|
).build(null));
|
||||||
public static final RegistryObject<BlockEntityType<MechanicalSieveBlockEntity>> MECHANICAL_SIEVE = BLOCK_ENTITIES.register("mechanical_sieve", () -> BlockEntityType.Builder.of(MechanicalSieveBlockEntity::new, EBlocks.MECHANICAL_SIEVE.get()).build(null));
|
public static final RegistryObject<BlockEntityType<MechanicalSieveBlockEntity>> MECHANICAL_SIEVE = BLOCK_ENTITIES.register("mechanical_sieve", () -> BlockEntityType.Builder.of(MechanicalSieveBlockEntity::new, EBlocks.MECHANICAL_SIEVE.get()).build(null));
|
||||||
|
public static final RegistryObject<BlockEntityType<MechanicalHammerBlockEntity>> MECHANICAL_HAMMER = BLOCK_ENTITIES.register("mechanical_hammer", () -> BlockEntityType.Builder.of(MechanicalHammerBlockEntity::new, EBlocks.MECHANICAL_HAMMER.get()).build(null));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -121,6 +121,8 @@ public class EBlocks {
|
||||||
public static final RegistryObject<SieveBlock> CRYSTALLIZED_SIEVE = registerSieve("crystallized_sieve", SoundType.GLASS);
|
public static final RegistryObject<SieveBlock> CRYSTALLIZED_SIEVE = registerSieve("crystallized_sieve", SoundType.GLASS);
|
||||||
// Mechanical Sieve
|
// Mechanical Sieve
|
||||||
public static final RegistryObject<MechanicalSieveBlock> MECHANICAL_SIEVE = BLOCKS.register("mechanical_sieve", () -> new MechanicalSieveBlock(of().mapColor(MapColor.METAL).requiresCorrectToolForDrops().strength(5f, 1200f)));
|
public static final RegistryObject<MechanicalSieveBlock> MECHANICAL_SIEVE = BLOCKS.register("mechanical_sieve", () -> new MechanicalSieveBlock(of().mapColor(MapColor.METAL).requiresCorrectToolForDrops().strength(5f, 1200f)));
|
||||||
|
// Mechanical Hammer
|
||||||
|
public static final RegistryObject<MechanicalHammerBlock> MECHANICAL_HAMMER = BLOCKS.register("mechanical_hammer", () -> new MechanicalHammerBlock(of()));
|
||||||
|
|
||||||
// Lava Crucibles
|
// Lava Crucibles
|
||||||
public static final RegistryObject<LavaCrucibleBlock> PORCELAIN_CRUCIBLE = registerLavaCrucible("porcelain_crucible", true, SoundType.STONE);
|
public static final RegistryObject<LavaCrucibleBlock> PORCELAIN_CRUCIBLE = registerLavaCrucible("porcelain_crucible", true, SoundType.STONE);
|
||||||
|
|
|
||||||
|
|
@ -225,6 +225,7 @@ public class EItems {
|
||||||
public static final RegistryObject<BlockItem> CRYSTALLIZED_SIEVE = registerItemBlock(EBlocks.CRYSTALLIZED_SIEVE);
|
public static final RegistryObject<BlockItem> CRYSTALLIZED_SIEVE = registerItemBlock(EBlocks.CRYSTALLIZED_SIEVE);
|
||||||
// Mechanical Sieves
|
// Mechanical Sieves
|
||||||
public static final RegistryObject<BlockItem> MECHANICAL_SIEVE = registerItemBlock(EBlocks.MECHANICAL_SIEVE);
|
public static final RegistryObject<BlockItem> MECHANICAL_SIEVE = registerItemBlock(EBlocks.MECHANICAL_SIEVE);
|
||||||
|
public static final RegistryObject<BlockItem> MECHANICAL_HAMMER = registerItemBlock(EBlocks.MECHANICAL_HAMMER);
|
||||||
|
|
||||||
// Lava Crucibles
|
// Lava Crucibles
|
||||||
public static final RegistryObject<BlockItem> PORCELAIN_CRUCIBLE = registerItemBlock(EBlocks.PORCELAIN_CRUCIBLE);
|
public static final RegistryObject<BlockItem> PORCELAIN_CRUCIBLE = registerItemBlock(EBlocks.PORCELAIN_CRUCIBLE);
|
||||||
|
|
@ -365,6 +366,7 @@ public class EItems {
|
||||||
output.accept(CRYSTALLIZED_SIEVE.get());
|
output.accept(CRYSTALLIZED_SIEVE.get());
|
||||||
}
|
}
|
||||||
output.accept(MECHANICAL_SIEVE.get());
|
output.accept(MECHANICAL_SIEVE.get());
|
||||||
|
output.accept(MECHANICAL_HAMMER.get());
|
||||||
|
|
||||||
output.accept(PORCELAIN_CRUCIBLE.get());
|
output.accept(PORCELAIN_CRUCIBLE.get());
|
||||||
output.accept(WARPED_CRUCIBLE.get());
|
output.accept(WARPED_CRUCIBLE.get());
|
||||||
|
|
|
||||||
|
|
@ -25,10 +25,12 @@ import net.minecraftforge.network.IContainerFactory;
|
||||||
import net.minecraftforge.registries.DeferredRegister;
|
import net.minecraftforge.registries.DeferredRegister;
|
||||||
import net.minecraftforge.registries.RegistryObject;
|
import net.minecraftforge.registries.RegistryObject;
|
||||||
import thedarkcolour.exdeorum.ExDeorum;
|
import thedarkcolour.exdeorum.ExDeorum;
|
||||||
|
import thedarkcolour.exdeorum.blockentity.MechanicalHammerMenu;
|
||||||
import thedarkcolour.exdeorum.menu.MechanicalSieveMenu;
|
import thedarkcolour.exdeorum.menu.MechanicalSieveMenu;
|
||||||
|
|
||||||
public class EMenus {
|
public class EMenus {
|
||||||
public static final DeferredRegister<MenuType<?>> MENUS = DeferredRegister.create(Registries.MENU, ExDeorum.ID);
|
public static final DeferredRegister<MenuType<?>> MENUS = DeferredRegister.create(Registries.MENU, ExDeorum.ID);
|
||||||
|
|
||||||
public static final RegistryObject<MenuType<MechanicalSieveMenu>> MECHANICAL_SIEVE = MENUS.register("mechanical_sieve", () -> new MenuType<>((IContainerFactory<MechanicalSieveMenu>) MechanicalSieveMenu::new, FeatureFlags.DEFAULT_FLAGS));
|
public static final RegistryObject<MenuType<MechanicalSieveMenu>> MECHANICAL_SIEVE = MENUS.register("mechanical_sieve", () -> new MenuType<>((IContainerFactory<MechanicalSieveMenu>) MechanicalSieveMenu::new, FeatureFlags.DEFAULT_FLAGS));
|
||||||
|
public static final RegistryObject<MenuType<MechanicalHammerMenu>> MECHANICAL_HAMMER = MENUS.register("mechanical_hammer", () -> new MenuType<>((IContainerFactory<MechanicalHammerMenu>) MechanicalHammerMenu::new, FeatureFlags.DEFAULT_FLAGS));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
{
|
||||||
|
"variants": {
|
||||||
|
"facing=east,running=false": {
|
||||||
|
"model": "exdeorum:block/mechanical_hammer_off",
|
||||||
|
"y": 90
|
||||||
|
},
|
||||||
|
"facing=east,running=true": {
|
||||||
|
"model": "exdeorum:block/mechanical_hammer_on",
|
||||||
|
"y": 90
|
||||||
|
},
|
||||||
|
"facing=north,running=false": {
|
||||||
|
"model": "exdeorum:block/mechanical_hammer_off"
|
||||||
|
},
|
||||||
|
"facing=north,running=true": {
|
||||||
|
"model": "exdeorum:block/mechanical_hammer_on"
|
||||||
|
},
|
||||||
|
"facing=south,running=false": {
|
||||||
|
"model": "exdeorum:block/mechanical_hammer_off",
|
||||||
|
"y": 180
|
||||||
|
},
|
||||||
|
"facing=south,running=true": {
|
||||||
|
"model": "exdeorum:block/mechanical_hammer_on",
|
||||||
|
"y": 180
|
||||||
|
},
|
||||||
|
"facing=west,running=false": {
|
||||||
|
"model": "exdeorum:block/mechanical_hammer_off",
|
||||||
|
"y": 270
|
||||||
|
},
|
||||||
|
"facing=west,running=true": {
|
||||||
|
"model": "exdeorum:block/mechanical_hammer_on",
|
||||||
|
"y": 270
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
{
|
||||||
|
"parent": "minecraft:block/orientable_with_bottom",
|
||||||
|
"textures": {
|
||||||
|
"front": "exdeorum:block/mechanical_hammer_front",
|
||||||
|
"side": "exdeorum:block/mechanical_hammer_side",
|
||||||
|
"top": "exdeorum:block/mechanical_hammer_top",
|
||||||
|
"bottom": "exdeorum:block/mechanical_hammer_bottom"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
{
|
||||||
|
"parent": "minecraft:block/orientable_with_bottom",
|
||||||
|
"textures": {
|
||||||
|
"front": "exdeorum:block/mechanical_hammer_front_on",
|
||||||
|
"side": "exdeorum:block/mechanical_hammer_side",
|
||||||
|
"top": "exdeorum:block/mechanical_hammer_top",
|
||||||
|
"bottom": "exdeorum:block/mechanical_hammer_bottom"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 712 B |
|
After Width: | Height: | Size: 609 B |
|
After Width: | Height: | Size: 647 B |
|
After Width: | Height: | Size: 614 B |
|
After Width: | Height: | Size: 701 B |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 2.8 KiB |