移植部分Capability、方块、菜单
This commit is contained in:
parent
85d5e741e7
commit
47896a82fe
40 changed files with 3980 additions and 15 deletions
|
@ -1,5 +1,6 @@
|
|||
package com.atsuishio.superbwarfare;
|
||||
|
||||
import com.atsuishio.superbwarfare.capability.CapabilityHandler;
|
||||
import com.atsuishio.superbwarfare.component.ModDataComponents;
|
||||
import com.atsuishio.superbwarfare.config.ClientConfig;
|
||||
import com.atsuishio.superbwarfare.config.CommonConfig;
|
||||
|
@ -55,6 +56,8 @@ public class ModUtils {
|
|||
// bus.addListener(this::onCommonSetup);
|
||||
// bus.addListener(this::onClientSetup);
|
||||
|
||||
CapabilityHandler.register(bus);
|
||||
|
||||
NeoForge.EVENT_BUS.register(this);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,108 @@
|
|||
package com.atsuishio.superbwarfare.block;
|
||||
|
||||
import com.atsuishio.superbwarfare.block.entity.ChargingStationBlockEntity;
|
||||
import com.atsuishio.superbwarfare.init.ModBlockEntities;
|
||||
import com.mojang.serialization.MapCodec;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.Containers;
|
||||
import net.minecraft.world.InteractionResult;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.context.BlockPlaceContext;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.*;
|
||||
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.minecraft.world.phys.BlockHitResult;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
|
||||
public class ChargingStationBlock extends BaseEntityBlock {
|
||||
|
||||
public static final DirectionProperty FACING = HorizontalDirectionalBlock.FACING;
|
||||
public static final BooleanProperty SHOW_RANGE = BooleanProperty.create("show_range");
|
||||
|
||||
public ChargingStationBlock() {
|
||||
super(Properties.of().sound(SoundType.METAL).strength(3.0f).requiresCorrectToolForDrops());
|
||||
this.registerDefaultState(this.stateDefinition.any().setValue(FACING, Direction.NORTH).setValue(SHOW_RANGE, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ParametersAreNonnullByDefault
|
||||
protected @NotNull InteractionResult useWithoutItem(BlockState state, Level level, BlockPos pos, Player player, BlockHitResult hitResult) {
|
||||
if (level.isClientSide) {
|
||||
return InteractionResult.SUCCESS;
|
||||
} else {
|
||||
this.openContainer(level, pos, player);
|
||||
return InteractionResult.CONSUME;
|
||||
}
|
||||
}
|
||||
|
||||
protected void openContainer(Level pLevel, BlockPos pPos, Player pPlayer) {
|
||||
BlockEntity blockentity = pLevel.getBlockEntity(pPos);
|
||||
if (blockentity instanceof ChargingStationBlockEntity blockEntity) {
|
||||
pPlayer.openMenu(blockEntity);
|
||||
}
|
||||
}
|
||||
|
||||
public static final MapCodec<ChargingStationBlock> CODEC = simpleCodec((prop) -> new ChargingStationBlock());
|
||||
|
||||
@Override
|
||||
protected @NotNull MapCodec<? extends BaseEntityBlock> codec() {
|
||||
return CODEC;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull RenderShape getRenderShape(@NotNull BlockState pState) {
|
||||
return RenderShape.MODEL;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public BlockEntity newBlockEntity(@NotNull BlockPos pPos, @NotNull BlockState pState) {
|
||||
return new ChargingStationBlockEntity(pPos, pState);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public <T extends BlockEntity> BlockEntityTicker<T> getTicker(Level pLevel, @NotNull BlockState pState, @NotNull BlockEntityType<T> pBlockEntityType) {
|
||||
if (!pLevel.isClientSide) {
|
||||
return createTickerHelper(pBlockEntityType, ModBlockEntities.CHARGING_STATION.get(), ChargingStationBlockEntity::serverTick);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRemove(BlockState pState, @NotNull Level pLevel, @NotNull BlockPos pPos, BlockState pNewState, boolean pMovedByPiston) {
|
||||
if (!pState.is(pNewState.getBlock())) {
|
||||
BlockEntity blockentity = pLevel.getBlockEntity(pPos);
|
||||
if (blockentity instanceof ChargingStationBlockEntity blockEntity) {
|
||||
if (pLevel instanceof ServerLevel serverLevel) {
|
||||
Containers.dropContents(serverLevel, pPos, blockEntity);
|
||||
}
|
||||
pLevel.updateNeighbourForOutputSignal(pPos, this);
|
||||
}
|
||||
}
|
||||
|
||||
super.onRemove(pState, pLevel, pPos, pNewState, pMovedByPiston);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> pBuilder) {
|
||||
pBuilder.add(FACING).add(SHOW_RANGE);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public BlockState getStateForPlacement(BlockPlaceContext pContext) {
|
||||
return this.defaultBlockState().setValue(FACING, pContext.getHorizontalDirection().getOpposite()).setValue(SHOW_RANGE, false);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,218 @@
|
|||
package com.atsuishio.superbwarfare.block;
|
||||
|
||||
import com.atsuishio.superbwarfare.block.entity.ContainerBlockEntity;
|
||||
import com.atsuishio.superbwarfare.init.ModBlockEntities;
|
||||
import com.atsuishio.superbwarfare.init.ModItems;
|
||||
import com.atsuishio.superbwarfare.init.ModSounds;
|
||||
import com.mojang.serialization.MapCodec;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.sounds.SoundSource;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.ItemInteractionResult;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.Item;
|
||||
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.Level;
|
||||
import net.minecraft.world.level.LevelReader;
|
||||
import net.minecraft.world.level.block.*;
|
||||
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.minecraft.world.phys.BlockHitResult;
|
||||
import net.minecraft.world.phys.HitResult;
|
||||
import net.minecraft.world.phys.shapes.CollisionContext;
|
||||
import net.minecraft.world.phys.shapes.VoxelShape;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
import java.util.List;
|
||||
|
||||
public class ContainerBlock extends BaseEntityBlock {
|
||||
|
||||
public static final DirectionProperty FACING = HorizontalDirectionalBlock.FACING;
|
||||
public static final BooleanProperty OPENED = BooleanProperty.create("opened");
|
||||
|
||||
public ContainerBlock() {
|
||||
super(Properties.of().sound(SoundType.METAL).strength(3.0f).noOcclusion().requiresCorrectToolForDrops());
|
||||
this.registerDefaultState(this.stateDefinition.any().setValue(FACING, Direction.NORTH).setValue(OPENED, false));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
@ParametersAreNonnullByDefault
|
||||
protected @NotNull ItemInteractionResult useItemOn(ItemStack stack, BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hitResult) {
|
||||
if (level.isClientSide
|
||||
|| state.getValue(OPENED)
|
||||
|| !(level.getBlockEntity(pos) instanceof ContainerBlockEntity containerBlockEntity)
|
||||
) return ItemInteractionResult.FAIL;
|
||||
|
||||
if (!stack.is(ModItems.CROWBAR.get())) {
|
||||
player.displayClientMessage(Component.translatable("des.superbwarfare.container.fail.crowbar"), true);
|
||||
return ItemInteractionResult.FAIL;
|
||||
}
|
||||
|
||||
if (!hasEntity(level, pos)) {
|
||||
player.displayClientMessage(Component.translatable("des.superbwarfare.container.fail.empty"), true);
|
||||
return ItemInteractionResult.FAIL;
|
||||
}
|
||||
|
||||
if (canOpen(level, pos, containerBlockEntity.entityType, containerBlockEntity.entity)) {
|
||||
level.setBlockAndUpdate(pos, state.setValue(OPENED, true));
|
||||
level.playSound(null, BlockPos.containing(pos.getX(), pos.getY(), pos.getZ()), ModSounds.OPEN.get(), SoundSource.BLOCKS, 1, 1);
|
||||
|
||||
return ItemInteractionResult.SUCCESS;
|
||||
} else {
|
||||
player.displayClientMessage(Component.translatable("des.superbwarfare.container.fail.open"), true);
|
||||
return ItemInteractionResult.FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasEntity(Level level, BlockPos pos) {
|
||||
BlockEntity blockEntity = level.getBlockEntity(pos);
|
||||
if (!(blockEntity instanceof ContainerBlockEntity containerBlockEntity)) return false;
|
||||
return containerBlockEntity.entity != null || containerBlockEntity.entityType != null;
|
||||
}
|
||||
|
||||
public static boolean canOpen(Level level, BlockPos pos, EntityType<?> entityType, Entity entity) {
|
||||
boolean flag = true;
|
||||
|
||||
int w = 0;
|
||||
int h = 0;
|
||||
|
||||
if (entityType != null) {
|
||||
w = (int) (entityType.getDimensions().width() / 2 + 1);
|
||||
h = (int) (entityType.getDimensions().height() + 1);
|
||||
}
|
||||
|
||||
if (entity != null) {
|
||||
w = (int) (entity.getType().getDimensions().width() / 2 + 1);
|
||||
h = (int) (entity.getType().getDimensions().height() + 1);
|
||||
}
|
||||
|
||||
for (int i = -w; i < w + 1; i++) {
|
||||
for (int j = 0; j < h; j++) {
|
||||
for (int k = -w; k < w + 1; k++) {
|
||||
if (i == 0 && j == 0 && k == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (level.getBlockState(pos.offset(i, j, k)).canOcclude()) {
|
||||
flag = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return flag;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public <T extends BlockEntity> BlockEntityTicker<T> getTicker(Level level, @NotNull BlockState state, @NotNull BlockEntityType<T> pBlockEntityType) {
|
||||
if (!level.isClientSide) {
|
||||
return createTickerHelper(pBlockEntityType, ModBlockEntities.CONTAINER.get(), ContainerBlockEntity::serverTick);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ParametersAreNonnullByDefault
|
||||
public void appendHoverText(ItemStack stack, Item.TooltipContext context, List<Component> tooltipComponents, TooltipFlag tooltipFlag) {
|
||||
super.appendHoverText(stack, context, tooltipComponents, tooltipFlag);
|
||||
|
||||
// TODO read NBT
|
||||
// CompoundTag tag = BlockItem.getBlockEntityData(pStack);
|
||||
// if (tag != null && tag.contains("EntityType")) {
|
||||
// String s = getEntityTranslationKey(tag.getString("EntityType"));
|
||||
// tooltipComponents.add(Component.translatable(s == null ? "des.superbwarfare.container.empty" : s).withStyle(ChatFormatting.GRAY));
|
||||
//
|
||||
// var entityType = EntityType.byString(tag.getString("EntityType")).orElse(null);
|
||||
// if (entityType != null) {
|
||||
// int w = 0, h = 0;
|
||||
// if (level instanceof Level level && tag.contains("Entity")) {
|
||||
// var entity = entityType.create(level);
|
||||
// if (entity != null) {
|
||||
// entity.load(tag.getCompound("Entity"));
|
||||
// w = (int) (entity.getType().getDimensions().width() + 1);
|
||||
// if (w % 2 == 0) w++;
|
||||
// h = (int) (entity.getType().getDimensions().height() + 1);
|
||||
// }
|
||||
// } else {
|
||||
// w = (int) (entityType.getDimensions().width() + 1);
|
||||
// if (w % 2 == 0) w++;
|
||||
// h = (int) (entityType.getDimensions().height() + 1);
|
||||
// }
|
||||
// if (w != 0 && h != 0) {
|
||||
// tooltipComponents.add(Component.literal(w + " x " + w + " x " + h).withStyle(ChatFormatting.YELLOW));
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static String getEntityTranslationKey(String path) {
|
||||
String[] parts = path.split(":");
|
||||
if (parts.length > 1) {
|
||||
return "entity." + parts[0] + "." + parts[1];
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ParametersAreNonnullByDefault
|
||||
public @NotNull VoxelShape getShape(BlockState state, BlockGetter world, BlockPos pos, CollisionContext context) {
|
||||
return state.getValue(OPENED) ? box(1, 0, 1, 15, 14, 15) : box(0, 0, 0, 16, 15, 16);
|
||||
}
|
||||
|
||||
// TODO codec
|
||||
@Override
|
||||
protected @NotNull MapCodec<? extends BaseEntityBlock> codec() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull RenderShape getRenderShape(@NotNull BlockState state) {
|
||||
return RenderShape.ENTITYBLOCK_ANIMATED;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public BlockEntity newBlockEntity(@NotNull BlockPos blockPos, @NotNull BlockState blockState) {
|
||||
return new ContainerBlockEntity(blockPos, blockState);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
|
||||
builder.add(FACING).add(OPENED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getStateForPlacement(BlockPlaceContext context) {
|
||||
return this.defaultBlockState().setValue(FACING, context.getHorizontalDirection().getOpposite()).setValue(OPENED, false);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
@ParametersAreNonnullByDefault
|
||||
public @NotNull ItemStack getCloneItemStack(BlockState state, HitResult target, LevelReader level, BlockPos pos, Player player) {
|
||||
var itemStack = super.getCloneItemStack(state, target, level, pos, player);
|
||||
// TODO saveToItem
|
||||
// level.getBlockEntity(pos, ModBlockEntities.CONTAINER.get()).ifPresent((blockEntity) -> blockEntity.saveToItem(itemStack));
|
||||
return itemStack;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
package com.atsuishio.superbwarfare.block;
|
||||
|
||||
import com.atsuishio.superbwarfare.block.entity.CreativeChargingStationBlockEntity;
|
||||
import com.atsuishio.superbwarfare.init.ModBlockEntities;
|
||||
import com.mojang.serialization.MapCodec;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.world.item.context.BlockPlaceContext;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.*;
|
||||
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.BlockBehaviour;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.StateDefinition;
|
||||
import net.minecraft.world.level.block.state.properties.DirectionProperty;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
|
||||
public class CreativeChargingStationBlock extends BaseEntityBlock {
|
||||
|
||||
public static final DirectionProperty FACING = HorizontalDirectionalBlock.FACING;
|
||||
|
||||
public CreativeChargingStationBlock() {
|
||||
this(Properties.of().sound(SoundType.METAL).strength(3.0f).requiresCorrectToolForDrops());
|
||||
}
|
||||
|
||||
public CreativeChargingStationBlock(BlockBehaviour.Properties properties) {
|
||||
super(properties);
|
||||
this.registerDefaultState(this.stateDefinition.any().setValue(FACING, Direction.NORTH));
|
||||
}
|
||||
|
||||
private static final MapCodec<CreativeChargingStationBlock> CODEC = BlockBehaviour.simpleCodec(CreativeChargingStationBlock::new);
|
||||
|
||||
@Override
|
||||
protected @NotNull MapCodec<? extends BaseEntityBlock> codec() {
|
||||
return CODEC;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull RenderShape getRenderShape(@NotNull BlockState pState) {
|
||||
return RenderShape.MODEL;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
@ParametersAreNonnullByDefault
|
||||
public BlockEntity newBlockEntity(BlockPos pPos, BlockState pState) {
|
||||
return new CreativeChargingStationBlockEntity(pPos, pState);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public <T extends BlockEntity> BlockEntityTicker<T> getTicker(Level pLevel, @NotNull BlockState pState, @NotNull BlockEntityType<T> pBlockEntityType) {
|
||||
if (!pLevel.isClientSide) {
|
||||
return createTickerHelper(
|
||||
pBlockEntityType, ModBlockEntities.CREATIVE_CHARGING_STATION.get(),
|
||||
(pLevel1, pPos, pState1, blockEntity) -> CreativeChargingStationBlockEntity.serverTick(blockEntity)
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRemove(BlockState pState, @NotNull Level pLevel, @NotNull BlockPos pPos, BlockState pNewState, boolean pMovedByPiston) {
|
||||
if (!pState.is(pNewState.getBlock())) {
|
||||
BlockEntity blockentity = pLevel.getBlockEntity(pPos);
|
||||
if (blockentity instanceof CreativeChargingStationBlockEntity) {
|
||||
pLevel.updateNeighbourForOutputSignal(pPos, this);
|
||||
}
|
||||
}
|
||||
|
||||
super.onRemove(pState, pLevel, pPos, pNewState, pMovedByPiston);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> pBuilder) {
|
||||
pBuilder.add(FACING);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public BlockState getStateForPlacement(BlockPlaceContext pContext) {
|
||||
return this.defaultBlockState().setValue(FACING, pContext.getHorizontalDirection().getOpposite());
|
||||
}
|
||||
}
|
|
@ -25,7 +25,7 @@ import org.jetbrains.annotations.Nullable;
|
|||
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
// TODO 解决obj渲染问题
|
||||
public class DragonTeethBlock extends Block {
|
||||
|
||||
public static final BooleanProperty WATERLOGGED = BlockStateProperties.WATERLOGGED;
|
||||
|
|
102
src/main/java/com/atsuishio/superbwarfare/block/FuMO25Block.java
Normal file
102
src/main/java/com/atsuishio/superbwarfare/block/FuMO25Block.java
Normal file
|
@ -0,0 +1,102 @@
|
|||
package com.atsuishio.superbwarfare.block;
|
||||
|
||||
import com.atsuishio.superbwarfare.block.entity.FuMO25BlockEntity;
|
||||
import com.atsuishio.superbwarfare.init.ModBlockEntities;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.InteractionResult;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.context.BlockPlaceContext;
|
||||
import net.minecraft.world.level.BlockGetter;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.EntityBlock;
|
||||
import net.minecraft.world.level.block.RenderShape;
|
||||
import net.minecraft.world.level.block.SoundType;
|
||||
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.phys.BlockHitResult;
|
||||
import net.minecraft.world.phys.shapes.CollisionContext;
|
||||
import net.minecraft.world.phys.shapes.Shapes;
|
||||
import net.minecraft.world.phys.shapes.VoxelShape;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
|
||||
public class FuMO25Block extends Block implements EntityBlock {
|
||||
|
||||
public static final BooleanProperty POWERED = BooleanProperty.create("powered");
|
||||
|
||||
public FuMO25Block() {
|
||||
super(Properties.of().sound(SoundType.METAL).strength(3.0f).requiresCorrectToolForDrops());
|
||||
this.registerDefaultState(this.stateDefinition.any().setValue(POWERED, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ParametersAreNonnullByDefault
|
||||
protected @NotNull InteractionResult useWithoutItem(BlockState state, Level level, BlockPos pos, Player player, BlockHitResult hitResult) {
|
||||
if (level.isClientSide) {
|
||||
return InteractionResult.SUCCESS;
|
||||
} else {
|
||||
BlockEntity blockentity = level.getBlockEntity(pos);
|
||||
if (blockentity instanceof FuMO25BlockEntity blockEntity) {
|
||||
player.openMenu(blockEntity);
|
||||
}
|
||||
return InteractionResult.CONSUME;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ParametersAreNonnullByDefault
|
||||
public @NotNull VoxelShape getShape(BlockState pState, BlockGetter pLevel, BlockPos pPos, CollisionContext pContext) {
|
||||
return Shapes.or(box(1, 0, 1, 15, 6, 15), box(6, 6, 6, 10, 58, 10));
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull RenderShape getRenderShape(@NotNull BlockState pState) {
|
||||
return RenderShape.ENTITYBLOCK_ANIMATED;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
@ParametersAreNonnullByDefault
|
||||
public BlockEntity newBlockEntity(BlockPos pPos, BlockState pState) {
|
||||
return new FuMO25BlockEntity(pPos, pState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable <T extends BlockEntity> BlockEntityTicker<T> getTicker(Level pLevel, @NotNull BlockState pState, @NotNull BlockEntityType<T> pBlockEntityType) {
|
||||
if (!pLevel.isClientSide && pBlockEntityType == ModBlockEntities.FUMO_25.get()) {
|
||||
return FuMO25BlockEntity::serverTick;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ParametersAreNonnullByDefault
|
||||
public void onRemove(BlockState pState, Level pLevel, BlockPos pPos, BlockState pNewState, boolean pMovedByPiston) {
|
||||
if (!pState.is(pNewState.getBlock())) {
|
||||
BlockEntity blockentity = pLevel.getBlockEntity(pPos);
|
||||
if (blockentity instanceof FuMO25BlockEntity) {
|
||||
pLevel.updateNeighbourForOutputSignal(pPos, this);
|
||||
}
|
||||
}
|
||||
|
||||
super.onRemove(pState, pLevel, pPos, pNewState, pMovedByPiston);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> pBuilder) {
|
||||
pBuilder.add(POWERED);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public BlockState getStateForPlacement(@NotNull BlockPlaceContext pContext) {
|
||||
return this.defaultBlockState().setValue(POWERED, false);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,397 @@
|
|||
package com.atsuishio.superbwarfare.block.entity;
|
||||
|
||||
import com.atsuishio.superbwarfare.block.ChargingStationBlock;
|
||||
import com.atsuishio.superbwarfare.init.ModBlockEntities;
|
||||
import com.atsuishio.superbwarfare.menu.ChargingStationMenu;
|
||||
import com.atsuishio.superbwarfare.network.dataslot.ContainerEnergyData;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.core.HolderLookup;
|
||||
import net.minecraft.core.NonNullList;
|
||||
import net.minecraft.core.component.DataComponents;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket;
|
||||
import net.minecraft.world.Container;
|
||||
import net.minecraft.world.ContainerHelper;
|
||||
import net.minecraft.world.MenuProvider;
|
||||
import net.minecraft.world.WorldlyContainer;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.item.ItemEntity;
|
||||
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.ItemStack;
|
||||
import net.minecraft.world.item.crafting.RecipeType;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.phys.AABB;
|
||||
import net.neoforged.neoforge.capabilities.Capabilities;
|
||||
import net.neoforged.neoforge.energy.EnergyStorage;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
* Energy Data Slot Code based on @GoryMoon's Chargers
|
||||
*/
|
||||
public class ChargingStationBlockEntity extends BlockEntity implements WorldlyContainer, MenuProvider {
|
||||
|
||||
protected static final int SLOT_FUEL = 0;
|
||||
protected static final int SLOT_CHARGE = 1;
|
||||
|
||||
public static final int MAX_ENERGY = 4000000;
|
||||
public static final int MAX_DATA_COUNT = 4;
|
||||
public static final int DEFAULT_FUEL_TIME = 1600;
|
||||
public static final int CHARGE_SPEED = 128;
|
||||
public static final int CHARGE_OTHER_SPEED = 100000;
|
||||
public static final int CHARGE_RADIUS = 8;
|
||||
|
||||
protected NonNullList<ItemStack> items = NonNullList.withSize(2, ItemStack.EMPTY);
|
||||
|
||||
private EnergyStorage energyHandler;
|
||||
|
||||
// TODO SidedInvWrapper Energy
|
||||
// private LazyOptional<?>[] itemHandlers = SidedInvWrapper.create(this, Direction.UP, Direction.DOWN, Direction.NORTH);
|
||||
|
||||
public int fuelTick = 0;
|
||||
public int maxFuelTick = DEFAULT_FUEL_TIME;
|
||||
public boolean showRange = false;
|
||||
|
||||
protected final ContainerEnergyData dataAccess = new ContainerEnergyData() {
|
||||
public long get(int pIndex) {
|
||||
return switch (pIndex) {
|
||||
case 0 -> ChargingStationBlockEntity.this.fuelTick;
|
||||
case 1 -> ChargingStationBlockEntity.this.maxFuelTick;
|
||||
case 2 -> {
|
||||
AtomicInteger energy = new AtomicInteger();
|
||||
// ChargingStationBlockEntity.this.getCapability(Capabilities.ENERGY).ifPresent(consumer -> energy.set(consumer.getEnergyStored()));
|
||||
yield energy.get();
|
||||
}
|
||||
case 3 -> ChargingStationBlockEntity.this.showRange ? 1 : 0;
|
||||
default -> 0;
|
||||
};
|
||||
}
|
||||
|
||||
public void set(int pIndex, long pValue) {
|
||||
switch (pIndex) {
|
||||
case 0:
|
||||
ChargingStationBlockEntity.this.fuelTick = (int) pValue;
|
||||
break;
|
||||
case 1:
|
||||
ChargingStationBlockEntity.this.maxFuelTick = (int) pValue;
|
||||
break;
|
||||
case 2:
|
||||
// ChargingStationBlockEntity.this.getCapability(Capabilities.ENERGY).ifPresent(consumer -> consumer.receiveEnergy((int) pValue, false));
|
||||
break;
|
||||
case 3:
|
||||
ChargingStationBlockEntity.this.showRange = pValue == 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public int getCount() {
|
||||
return MAX_DATA_COUNT;
|
||||
}
|
||||
};
|
||||
|
||||
public ChargingStationBlockEntity(BlockPos pos, BlockState state) {
|
||||
super(ModBlockEntities.CHARGING_STATION.get(), pos, state);
|
||||
|
||||
this.energyHandler = new EnergyStorage(MAX_ENERGY);
|
||||
}
|
||||
|
||||
public static void serverTick(Level pLevel, BlockPos pPos, BlockState pState, ChargingStationBlockEntity blockEntity) {
|
||||
if (blockEntity.showRange != pState.getValue(ChargingStationBlock.SHOW_RANGE)) {
|
||||
pLevel.setBlockAndUpdate(pPos, pState.setValue(ChargingStationBlock.SHOW_RANGE, blockEntity.showRange));
|
||||
setChanged(pLevel, pPos, pState);
|
||||
}
|
||||
|
||||
var handler = blockEntity.energyHandler;
|
||||
int energy = handler.getEnergyStored();
|
||||
if (energy > 0) {
|
||||
blockEntity.chargeEntity(handler);
|
||||
}
|
||||
if (handler.getEnergyStored() > 0) {
|
||||
blockEntity.chargeItemStack(handler);
|
||||
}
|
||||
if (handler.getEnergyStored() > 0) {
|
||||
blockEntity.chargeBlock(handler);
|
||||
}
|
||||
|
||||
if (blockEntity.fuelTick > 0) {
|
||||
blockEntity.fuelTick--;
|
||||
if (energy < handler.getMaxEnergyStored()) {
|
||||
handler.receiveEnergy(CHARGE_SPEED, false);
|
||||
}
|
||||
} else if (!blockEntity.getItem(SLOT_FUEL).isEmpty()) {
|
||||
if (handler.getEnergyStored() >= handler.getMaxEnergyStored()) return;
|
||||
|
||||
ItemStack fuel = blockEntity.getItem(SLOT_FUEL);
|
||||
int burnTime = fuel.getBurnTime(RecipeType.SMELTING);
|
||||
|
||||
var fuelEnergy = fuel.getCapability(Capabilities.EnergyStorage.ITEM);
|
||||
|
||||
if (fuelEnergy != null) {
|
||||
// 优先当作电池处理
|
||||
var energyToExtract = Math.min(CHARGE_OTHER_SPEED, handler.getMaxEnergyStored() - handler.getEnergyStored());
|
||||
if (fuelEnergy.canExtract() && handler.canReceive()) {
|
||||
handler.receiveEnergy(fuelEnergy.extractEnergy(energyToExtract, false), false);
|
||||
}
|
||||
|
||||
blockEntity.setChanged();
|
||||
} else if (burnTime > 0) {
|
||||
// 其次尝试作为燃料处理
|
||||
blockEntity.fuelTick = burnTime;
|
||||
blockEntity.maxFuelTick = burnTime;
|
||||
|
||||
if (fuel.hasCraftingRemainingItem()) {
|
||||
if (fuel.getCount() <= 1) {
|
||||
blockEntity.setItem(SLOT_FUEL, fuel.getCraftingRemainingItem());
|
||||
} else {
|
||||
ItemStack copy = fuel.getCraftingRemainingItem().copy();
|
||||
copy.setCount(1);
|
||||
|
||||
ItemEntity itemEntity = new ItemEntity(pLevel,
|
||||
pPos.getX() + 0.5,
|
||||
pPos.getY() + 0.2,
|
||||
pPos.getZ() + 0.5,
|
||||
copy);
|
||||
pLevel.addFreshEntity(itemEntity);
|
||||
|
||||
fuel.shrink(1);
|
||||
}
|
||||
} else {
|
||||
fuel.shrink(1);
|
||||
}
|
||||
|
||||
blockEntity.setChanged();
|
||||
} else if (fuel.get(DataComponents.FOOD) != null) {
|
||||
// 最后作为食物处理
|
||||
var foodComponent = fuel.get(DataComponents.FOOD);
|
||||
if (foodComponent == null) return;
|
||||
|
||||
int nutrition = foodComponent.nutrition();
|
||||
float saturation = foodComponent.saturation() * 2.0f * nutrition;
|
||||
int tick = nutrition * 80 + (int) (saturation * 200);
|
||||
|
||||
if (fuel.hasCraftingRemainingItem()) {
|
||||
tick += 400;
|
||||
}
|
||||
|
||||
fuel.shrink(1);
|
||||
|
||||
blockEntity.fuelTick = tick;
|
||||
blockEntity.maxFuelTick = tick;
|
||||
blockEntity.setChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void chargeEntity(EnergyStorage handler) {
|
||||
if (this.level == null) return;
|
||||
if (this.level.getGameTime() % 20 != 0) return;
|
||||
|
||||
List<Entity> entities = this.level.getEntitiesOfClass(Entity.class, new AABB(this.getBlockPos()).inflate(CHARGE_RADIUS));
|
||||
entities.forEach(entity -> {
|
||||
var cap = entity.getCapability(Capabilities.EnergyStorage.ENTITY, null);
|
||||
if (cap == null || !cap.canReceive()) return;
|
||||
|
||||
int charged = cap.receiveEnergy(Math.min(handler.getEnergyStored(), CHARGE_OTHER_SPEED * 20), false);
|
||||
handler.extractEnergy(charged, false);
|
||||
});
|
||||
this.setChanged();
|
||||
}
|
||||
|
||||
private void chargeItemStack(EnergyStorage handler) {
|
||||
ItemStack stack = this.getItem(SLOT_CHARGE);
|
||||
if (stack.isEmpty()) return;
|
||||
|
||||
var consumer = stack.getCapability(Capabilities.EnergyStorage.ITEM);
|
||||
if (consumer != null) {
|
||||
if (consumer.getEnergyStored() < consumer.getMaxEnergyStored()) {
|
||||
int charged = consumer.receiveEnergy(Math.min(CHARGE_OTHER_SPEED, handler.getEnergyStored()), false);
|
||||
handler.extractEnergy(Math.min(charged, handler.getEnergyStored()), false);
|
||||
}
|
||||
}
|
||||
this.setChanged();
|
||||
}
|
||||
|
||||
private void chargeBlock(EnergyStorage handler) {
|
||||
if (this.level == null) return;
|
||||
|
||||
for (Direction direction : Direction.values()) {
|
||||
var blockEntity = this.level.getBlockEntity(this.getBlockPos().relative(direction));
|
||||
if (blockEntity == null) return;
|
||||
|
||||
var energy = level.getCapability(Capabilities.EnergyStorage.BLOCK, blockEntity.getBlockPos(), direction);
|
||||
if (energy == null || !(blockEntity instanceof ChargingStationBlockEntity)) return;
|
||||
|
||||
if (energy.canReceive() && energy.getEnergyStored() < energy.getMaxEnergyStored()) {
|
||||
int receiveEnergy = energy.receiveEnergy(Math.min(handler.getEnergyStored(), CHARGE_OTHER_SPEED), false);
|
||||
handler.extractEnergy(receiveEnergy, false);
|
||||
|
||||
blockEntity.setChanged();
|
||||
this.setChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public NonNullList<ItemStack> getItems() {
|
||||
return this.items;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void loadAdditional(@NotNull CompoundTag tag, HolderLookup.@NotNull Provider registries) {
|
||||
super.loadAdditional(tag, registries);
|
||||
|
||||
if (tag.contains("Energy")) {
|
||||
// getCapability(Capabilities.ENERGY).ifPresent(handler -> ((EnergyStorage) handler).deserializeNBT(tag.get("Energy")));
|
||||
}
|
||||
this.fuelTick = tag.getInt("FuelTick");
|
||||
this.maxFuelTick = tag.getInt("MaxFuelTick");
|
||||
this.showRange = tag.getBoolean("ShowRange");
|
||||
this.items = NonNullList.withSize(this.getContainerSize(), ItemStack.EMPTY);
|
||||
ContainerHelper.loadAllItems(tag, this.items, registries);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void saveAdditional(@NotNull CompoundTag tag, HolderLookup.@NotNull Provider registries) {
|
||||
super.saveAdditional(tag, registries);
|
||||
|
||||
// getCapability(Capabilities.ENERGY).ifPresent(handler -> tag.put("Energy", ((EnergyStorage) handler).serializeNBT()));
|
||||
tag.putInt("FuelTick", this.fuelTick);
|
||||
tag.putInt("MaxFuelTick", this.maxFuelTick);
|
||||
tag.putBoolean("ShowRange", this.showRange);
|
||||
ContainerHelper.saveAllItems(tag, this.items, registries);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int @NotNull [] getSlotsForFace(@NotNull Direction pSide) {
|
||||
return new int[]{SLOT_FUEL};
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canPlaceItemThroughFace(int pIndex, @NotNull ItemStack pItemStack, @Nullable Direction pDirection) {
|
||||
return pIndex == SLOT_FUEL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canTakeItemThroughFace(int pIndex, @NotNull ItemStack pStack, @NotNull Direction pDirection) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getContainerSize() {
|
||||
return this.items.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
for (ItemStack itemstack : this.items) {
|
||||
if (!itemstack.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ItemStack getItem(int pSlot) {
|
||||
return this.items.get(pSlot);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ItemStack removeItem(int pSlot, int pAmount) {
|
||||
return ContainerHelper.removeItem(this.items, pSlot, pAmount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ItemStack removeItemNoUpdate(int pSlot) {
|
||||
return ContainerHelper.takeItem(this.items, pSlot);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setItem(int pSlot, ItemStack pStack) {
|
||||
ItemStack itemstack = this.items.get(pSlot);
|
||||
boolean flag = !pStack.isEmpty() && ItemStack.isSameItem(itemstack, pStack);
|
||||
this.items.set(pSlot, pStack);
|
||||
if (pStack.getCount() > this.getMaxStackSize()) {
|
||||
pStack.setCount(this.getMaxStackSize());
|
||||
}
|
||||
|
||||
if (pSlot == 0 && !flag) {
|
||||
this.setChanged();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean stillValid(@NotNull Player pPlayer) {
|
||||
return Container.stillValidBlockEntity(this, pPlayer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearContent() {
|
||||
this.items.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Component getDisplayName() {
|
||||
return Component.translatable("container.superbwarfare.charging_station");
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public AbstractContainerMenu createMenu(int pContainerId, @NotNull Inventory pPlayerInventory, @NotNull Player pPlayer) {
|
||||
return new ChargingStationMenu(pContainerId, pPlayerInventory, this, this.dataAccess);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClientboundBlockEntityDataPacket getUpdatePacket() {
|
||||
return ClientboundBlockEntityDataPacket.create(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull CompoundTag getUpdateTag(HolderLookup.@NotNull Provider registries) {
|
||||
CompoundTag compoundtag = new CompoundTag();
|
||||
ContainerHelper.saveAllItems(compoundtag, this.items, registries);
|
||||
compoundtag.putBoolean("ShowRange", this.showRange);
|
||||
return compoundtag;
|
||||
}
|
||||
|
||||
|
||||
// @Override
|
||||
// public <T> LazyOptional<T> getCapability(Capability<T> cap, Direction side) {
|
||||
// if (cap == Capabilities.ENERGY) {
|
||||
// return energyHandler.cast();
|
||||
// }
|
||||
// if (!this.remove && side != null && cap == Capabilities.ITEM_HANDLER) {
|
||||
// if (side == Direction.UP) {
|
||||
// return itemHandlers[0].cast();
|
||||
// } else if (side == Direction.DOWN) {
|
||||
// return itemHandlers[1].cast();
|
||||
// } else {
|
||||
// return itemHandlers[2].cast();
|
||||
// }
|
||||
// }
|
||||
// return super.getCapability(cap, side);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void invalidateCaps() {
|
||||
// super.invalidateCaps();
|
||||
// for (LazyOptional<?> itemHandler : itemHandlers) itemHandler.invalidate();
|
||||
// energyHandler.invalidate();
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void reviveCaps() {
|
||||
// super.reviveCaps();
|
||||
// this.itemHandlers = SidedInvWrapper.create(this, Direction.UP, Direction.DOWN, Direction.NORTH);
|
||||
// this.energyHandler = LazyOptional.of(() -> new EnergyStorage(MAX_ENERGY));
|
||||
// }
|
||||
}
|
|
@ -0,0 +1,139 @@
|
|||
package com.atsuishio.superbwarfare.block.entity;
|
||||
|
||||
import com.atsuishio.superbwarfare.block.ContainerBlock;
|
||||
import com.atsuishio.superbwarfare.init.ModBlockEntities;
|
||||
import com.atsuishio.superbwarfare.tools.ParticleTool;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.HolderLookup;
|
||||
import net.minecraft.core.particles.ParticleTypes;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.sounds.SoundEvents;
|
||||
import net.minecraft.sounds.SoundSource;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.item.BlockItem;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.joml.Math;
|
||||
import software.bernie.geckolib.animatable.GeoBlockEntity;
|
||||
import software.bernie.geckolib.animatable.instance.AnimatableInstanceCache;
|
||||
import software.bernie.geckolib.animation.*;
|
||||
import software.bernie.geckolib.util.GeckoLibUtil;
|
||||
|
||||
public class ContainerBlockEntity extends BlockEntity implements GeoBlockEntity {
|
||||
|
||||
public EntityType<?> entityType;
|
||||
public Entity entity = null;
|
||||
public int tick = 0;
|
||||
|
||||
private final AnimatableInstanceCache cache = GeckoLibUtil.createInstanceCache(this);
|
||||
|
||||
public ContainerBlockEntity(BlockPos pos, BlockState state) {
|
||||
super(ModBlockEntities.CONTAINER.get(), pos, state);
|
||||
}
|
||||
|
||||
public static void serverTick(Level pLevel, BlockPos pPos, BlockState pState, ContainerBlockEntity blockEntity) {
|
||||
if (!pState.getValue(ContainerBlock.OPENED)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (blockEntity.tick < 20) {
|
||||
blockEntity.tick++;
|
||||
blockEntity.setChanged();
|
||||
|
||||
if (blockEntity.tick == 18) {
|
||||
ParticleTool.sendParticle((ServerLevel) pLevel, ParticleTypes.EXPLOSION, pPos.getX(), pPos.getY() + 1, pPos.getZ(), 40, 1.5, 1.5, 1.5, 1, false);
|
||||
pLevel.playSound(null, pPos, SoundEvents.GENERIC_EXPLODE.value(), SoundSource.BLOCKS, 4.0F, (1.0F + (pLevel.random.nextFloat() - pLevel.random.nextFloat()) * 0.2F) * 0.7F);
|
||||
}
|
||||
} else {
|
||||
if (blockEntity.entity != null) {
|
||||
blockEntity.entity.setPos(pPos.getX() + 0.5 + (2 * Math.random() - 1) * 0.1f, pPos.getY() + 0.5 + (2 * Math.random() - 1) * 0.1f, pPos.getZ() + 0.5 + (2 * Math.random() - 1) * 0.1f);
|
||||
pLevel.addFreshEntity(blockEntity.entity);
|
||||
} else if (blockEntity.entityType != null) {
|
||||
var entity = blockEntity.entityType.create(pLevel);
|
||||
if (entity != null) {
|
||||
entity.setPos(pPos.getX() + 0.5 + (2 * Math.random() - 1) * 0.1f, pPos.getY() + 0.5 + (2 * Math.random() - 1) * 0.1f, pPos.getZ() + 0.5 + (2 * Math.random() - 1) * 0.1f);
|
||||
pLevel.addFreshEntity(entity);
|
||||
}
|
||||
}
|
||||
|
||||
pLevel.setBlockAndUpdate(pPos, Blocks.AIR.defaultBlockState());
|
||||
}
|
||||
}
|
||||
|
||||
private PlayState predicate(AnimationState<ContainerBlockEntity> event) {
|
||||
if (this.getBlockState().getValue(ContainerBlock.OPENED)) {
|
||||
return event.setAndContinue(RawAnimation.begin().thenPlay("animation.container.open"));
|
||||
}
|
||||
return PlayState.STOP;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerControllers(AnimatableManager.ControllerRegistrar controllers) {
|
||||
controllers.add(new AnimationController<>(this, "controller", 0, this::predicate));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnimatableInstanceCache getAnimatableInstanceCache() {
|
||||
return this.cache;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void loadAdditional(@NotNull CompoundTag tag, HolderLookup.@NotNull Provider registries) {
|
||||
super.loadAdditional(tag, registries);
|
||||
|
||||
if (tag.contains("EntityType")) {
|
||||
this.entityType = EntityType.byString(tag.getString("EntityType")).orElse(null);
|
||||
}
|
||||
if (tag.contains("Entity") && this.entityType != null && this.level != null) {
|
||||
this.entity = this.entityType.create(this.level);
|
||||
if (entity != null) {
|
||||
entity.load(tag.getCompound("Entity"));
|
||||
}
|
||||
}
|
||||
this.tick = tag.getInt("Tick");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void saveAdditional(@NotNull CompoundTag tag, HolderLookup.@NotNull Provider registries) {
|
||||
super.saveAdditional(tag, registries);
|
||||
|
||||
if (this.entity != null) {
|
||||
tag.put("Entity", this.entity.getPersistentData());
|
||||
}
|
||||
if (this.entityType != null) {
|
||||
tag.putString("EntityType", EntityType.getKey(this.entityType).toString());
|
||||
}
|
||||
tag.putInt("Tick", this.tick);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClientboundBlockEntityDataPacket getUpdatePacket() {
|
||||
return ClientboundBlockEntityDataPacket.create(this);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public @NotNull CompoundTag getUpdateTag(HolderLookup.@NotNull Provider registries) {
|
||||
return this.saveWithFullMetadata(registries);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveToItem(@NotNull ItemStack stack, HolderLookup.@NotNull Provider registries) {
|
||||
super.saveToItem(stack, registries);
|
||||
|
||||
CompoundTag tag = new CompoundTag();
|
||||
if (this.entityType != null) {
|
||||
tag.putString("EntityType", EntityType.getKey(this.entityType).toString());
|
||||
}
|
||||
BlockItem.setBlockEntityData(stack, this.getType(), tag);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
package com.atsuishio.superbwarfare.block.entity;
|
||||
|
||||
import com.atsuishio.superbwarfare.capability.energy.InfinityEnergyStorage;
|
||||
import com.atsuishio.superbwarfare.init.ModBlockEntities;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.phys.AABB;
|
||||
import net.neoforged.neoforge.capabilities.Capabilities;
|
||||
import net.neoforged.neoforge.energy.IEnergyStorage;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Energy Data Slot Code based on @GoryMoon's Chargers
|
||||
*/
|
||||
public class CreativeChargingStationBlockEntity extends BlockEntity {
|
||||
|
||||
public static final int CHARGE_RADIUS = 8;
|
||||
|
||||
private final IEnergyStorage energyHandler;
|
||||
|
||||
public CreativeChargingStationBlockEntity(BlockPos pos, BlockState state) {
|
||||
super(ModBlockEntities.CREATIVE_CHARGING_STATION.get(), pos, state);
|
||||
this.energyHandler = new InfinityEnergyStorage();
|
||||
}
|
||||
|
||||
public static void serverTick(CreativeChargingStationBlockEntity blockEntity) {
|
||||
if (blockEntity.level == null) return;
|
||||
|
||||
if (blockEntity.energyHandler != null) {
|
||||
blockEntity.chargeEntity();
|
||||
blockEntity.chargeBlock();
|
||||
}
|
||||
}
|
||||
|
||||
private void chargeEntity() {
|
||||
if (this.level == null) return;
|
||||
if (this.level.getGameTime() % 20 != 0) return;
|
||||
|
||||
List<Entity> entities = this.level.getEntitiesOfClass(Entity.class, new AABB(this.getBlockPos()).inflate(CHARGE_RADIUS));
|
||||
entities.forEach(entity -> {
|
||||
var cap = entity.getCapability(Capabilities.EnergyStorage.ENTITY, null);
|
||||
if (cap == null || !cap.canReceive()) return;
|
||||
|
||||
cap.receiveEnergy(Integer.MAX_VALUE, false);
|
||||
});
|
||||
}
|
||||
|
||||
private void chargeBlock() {
|
||||
if (this.level == null) return;
|
||||
|
||||
for (Direction direction : Direction.values()) {
|
||||
var blockEntity = this.level.getBlockEntity(this.getBlockPos().relative(direction));
|
||||
if (blockEntity == null) return;
|
||||
|
||||
var energy = level.getCapability(Capabilities.EnergyStorage.BLOCK, blockEntity.getBlockPos(), direction);
|
||||
if (energy == null || blockEntity instanceof CreativeChargingStationBlockEntity) continue;
|
||||
|
||||
if (energy.canReceive() && energy.getEnergyStored() < energy.getMaxEnergyStored()) {
|
||||
energy.receiveEnergy(Integer.MAX_VALUE, false);
|
||||
blockEntity.setChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClientboundBlockEntityDataPacket getUpdatePacket() {
|
||||
return ClientboundBlockEntityDataPacket.create(this);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,245 @@
|
|||
package com.atsuishio.superbwarfare.block.entity;
|
||||
|
||||
import com.atsuishio.superbwarfare.init.ModBlockEntities;
|
||||
import com.atsuishio.superbwarfare.menu.FuMO25Menu;
|
||||
import com.atsuishio.superbwarfare.network.dataslot.ContainerEnergyData;
|
||||
import com.atsuishio.superbwarfare.tools.SeekTool;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.HolderLookup;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.MenuProvider;
|
||||
import net.minecraft.world.effect.MobEffectInstance;
|
||||
import net.minecraft.world.effect.MobEffects;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
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.ContainerLevelAccess;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import software.bernie.geckolib.animatable.GeoBlockEntity;
|
||||
import software.bernie.geckolib.animatable.instance.AnimatableInstanceCache;
|
||||
import software.bernie.geckolib.animation.AnimatableManager;
|
||||
import software.bernie.geckolib.util.GeckoLibUtil;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class FuMO25BlockEntity extends BlockEntity implements MenuProvider, GeoBlockEntity {
|
||||
|
||||
private final AnimatableInstanceCache cache = GeckoLibUtil.createInstanceCache(this);
|
||||
|
||||
public static final int MAX_ENERGY = 1000000;
|
||||
|
||||
// 固定距离,以后有人改动这个需要自行解决GUI渲染问题
|
||||
public static final int DEFAULT_RANGE = 96;
|
||||
public static final int MAX_RANGE = 128;
|
||||
public static final int GLOW_RANGE = 64;
|
||||
|
||||
public static final int DEFAULT_ENERGY_COST = 256;
|
||||
public static final int MAX_ENERGY_COST = 1024;
|
||||
|
||||
public static final int DEFAULT_MIN_ENERGY = 64000;
|
||||
|
||||
public static final int MAX_DATA_COUNT = 5;
|
||||
|
||||
// private LazyOptional<EnergyStorage> energyHandler;
|
||||
|
||||
public FuncType type = FuncType.NORMAL;
|
||||
public int time = 0;
|
||||
public boolean powered = false;
|
||||
public int tick = 0;
|
||||
|
||||
protected final ContainerEnergyData dataAccess = new ContainerEnergyData() {
|
||||
// TODO energy
|
||||
@Override
|
||||
public long get(int pIndex) {
|
||||
return switch (pIndex) {
|
||||
// case 0 -> FuMO25BlockEntity.this.energyHandler.map(EnergyStorage::getEnergyStored).orElse(0);
|
||||
case 1 -> FuMO25BlockEntity.this.type.ordinal();
|
||||
case 2 -> FuMO25BlockEntity.this.time;
|
||||
case 3 -> FuMO25BlockEntity.this.powered ? 1 : 0;
|
||||
case 4 -> FuMO25BlockEntity.this.tick;
|
||||
default -> 0;
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(int pIndex, long pValue) {
|
||||
switch (pIndex) {
|
||||
case 0 -> {
|
||||
}
|
||||
// FuMO25BlockEntity.this.energyHandler.ifPresent(handler -> handler.receiveEnergy((int) pValue, false));
|
||||
case 1 -> FuMO25BlockEntity.this.type = FuncType.values()[(int) pValue];
|
||||
case 2 -> FuMO25BlockEntity.this.time = (int) pValue;
|
||||
case 3 -> FuMO25BlockEntity.this.powered = pValue == 1;
|
||||
case 4 -> FuMO25BlockEntity.this.tick = (int) pValue;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return MAX_DATA_COUNT;
|
||||
}
|
||||
};
|
||||
|
||||
public FuMO25BlockEntity(BlockPos pPos, BlockState pBlockState) {
|
||||
super(ModBlockEntities.FUMO_25.get(), pPos, pBlockState);
|
||||
// this.energyHandler = LazyOptional.of(() -> new EnergyStorage(MAX_ENERGY));
|
||||
}
|
||||
|
||||
public static <T extends BlockEntity> void serverTick(Level pLevel, BlockPos pPos, BlockState pState, T blockEntity) {
|
||||
var radar = (FuMO25BlockEntity) blockEntity;
|
||||
|
||||
// int energy = radar.energyHandler.map(EnergyStorage::getEnergyStored).orElse(0);
|
||||
radar.tick++;
|
||||
|
||||
FuncType funcType = radar.type;
|
||||
int energyCost;
|
||||
if (funcType == FuncType.WIDER) {
|
||||
energyCost = MAX_ENERGY_COST;
|
||||
} else {
|
||||
energyCost = DEFAULT_ENERGY_COST;
|
||||
}
|
||||
|
||||
// if (energy < energyCost) {
|
||||
// if (pState.getValue(FuMO25Block.POWERED)) {
|
||||
// pLevel.setBlockAndUpdate(pPos, pState.setValue(FuMO25Block.POWERED, false));
|
||||
// pLevel.playSound(null, pPos, ModSounds.RADAR_SEARCH_END.get(), SoundSource.BLOCKS, 1.0F, 1.0F);
|
||||
// radar.powered = false;
|
||||
// setChanged(pLevel, pPos, pState);
|
||||
// }
|
||||
// if (radar.time > 0) {
|
||||
// radar.time = 0;
|
||||
// radar.setChanged();
|
||||
// }
|
||||
// } else {
|
||||
// if (!pState.getValue(FuMO25Block.POWERED)) {
|
||||
// if (energy >= DEFAULT_MIN_ENERGY) {
|
||||
// pLevel.setBlockAndUpdate(pPos, pState.setValue(FuMO25Block.POWERED, true));
|
||||
// pLevel.playSound(null, pPos, ModSounds.RADAR_SEARCH_START.get(), SoundSource.BLOCKS, 1.0F, 1.0F);
|
||||
// radar.powered = true;
|
||||
// setChanged(pLevel, pPos, pState);
|
||||
// }
|
||||
// } else {
|
||||
// radar.energyHandler.ifPresent(handler -> handler.extractEnergy(energyCost, false));
|
||||
// if (radar.tick == 200) {
|
||||
// pLevel.playSound(null, pPos, ModSounds.RADAR_SEARCH_IDLE.get(), SoundSource.BLOCKS, 1.0F, 1.0F);
|
||||
// }
|
||||
//
|
||||
// if (radar.time > 0) {
|
||||
// if (radar.time % 100 == 0) {
|
||||
// radar.setGlowEffect();
|
||||
// }
|
||||
// radar.time--;
|
||||
// radar.setChanged();
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
if (radar.tick >= 200) {
|
||||
radar.tick = 0;
|
||||
}
|
||||
|
||||
if (radar.time <= 0 && radar.type != FuncType.NORMAL) {
|
||||
radar.type = FuncType.NORMAL;
|
||||
radar.setChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private void setGlowEffect() {
|
||||
if (this.type != FuncType.GLOW) return;
|
||||
|
||||
Level level = this.level;
|
||||
if (level == null) return;
|
||||
BlockPos pos = this.getBlockPos();
|
||||
List<Entity> entities = SeekTool.getEntitiesWithinRange(pos, level, GLOW_RANGE);
|
||||
entities.forEach(e -> {
|
||||
if (e instanceof LivingEntity living) {
|
||||
living.addEffect(new MobEffectInstance(MobEffects.GLOWING, 100, 0, true, false));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void loadAdditional(@NotNull CompoundTag tag, HolderLookup.@NotNull Provider registries) {
|
||||
super.loadAdditional(tag, registries);
|
||||
|
||||
if (tag.contains("Energy")) {
|
||||
// getCapability(Capabilities.ENERGY).ifPresent(handler -> ((EnergyStorage) handler).deserializeNBT(tag.get("Energy")));
|
||||
}
|
||||
this.type = FuncType.values()[Mth.clamp(tag.getInt("Type"), 0, 3)];
|
||||
this.time = tag.getInt("Time");
|
||||
this.powered = tag.getBoolean("Powered");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void saveAdditional(CompoundTag tag, HolderLookup.Provider registries) {
|
||||
super.saveAdditional(tag, registries);
|
||||
|
||||
// getCapability(Capabilities.ENERGY).ifPresent(handler -> tag.put("Energy", ((EnergyStorage) handler).serializeNBT()));
|
||||
tag.putInt("Type", this.type.ordinal());
|
||||
tag.putInt("Time", this.time);
|
||||
tag.putBoolean("Powered", this.powered);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Component getDisplayName() {
|
||||
return Component.literal("");
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public AbstractContainerMenu createMenu(int pContainerId, @NotNull Inventory pPlayerInventory, @NotNull Player pPlayer) {
|
||||
if (this.level == null) return null;
|
||||
return new FuMO25Menu(pContainerId, pPlayerInventory, ContainerLevelAccess.create(this.level, this.getBlockPos()), this.dataAccess);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClientboundBlockEntityDataPacket getUpdatePacket() {
|
||||
return ClientboundBlockEntityDataPacket.create(this);
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public <T> LazyOptional<T> getCapability(Capability<T> cap, Direction side) {
|
||||
// if (cap == Capabilities.ENERGY) {
|
||||
// return energyHandler.cast();
|
||||
// }
|
||||
// return super.getCapability(cap, side);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void invalidateCapabilities() {
|
||||
// this.energyHandler.invalidate();
|
||||
// super.invalidateCapabilities();
|
||||
// }
|
||||
//
|
||||
//
|
||||
// @Override
|
||||
// public void reviveCaps() {
|
||||
// super.reviveCaps();
|
||||
// this.energyHandler = LazyOptional.of(() -> new EnergyStorage(MAX_ENERGY));
|
||||
// }
|
||||
|
||||
@Override
|
||||
public void registerControllers(AnimatableManager.ControllerRegistrar controllers) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnimatableInstanceCache getAnimatableInstanceCache() {
|
||||
return this.cache;
|
||||
}
|
||||
|
||||
public enum FuncType {
|
||||
NORMAL,
|
||||
WIDER,
|
||||
GLOW,
|
||||
GUIDE
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package com.atsuishio.superbwarfare.capability;
|
||||
|
||||
import net.minecraft.core.registries.BuiltInRegistries;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.neoforged.bus.api.IEventBus;
|
||||
import net.neoforged.neoforge.capabilities.RegisterCapabilitiesEvent;
|
||||
|
||||
public class CapabilityHandler {
|
||||
|
||||
private static final CapabilityHandler INSTANCE = new CapabilityHandler();
|
||||
|
||||
public static void register(IEventBus bus) {
|
||||
bus.addListener(INSTANCE::registerCapabilities);
|
||||
}
|
||||
|
||||
public void registerCapabilities(RegisterCapabilitiesEvent event) {
|
||||
for (EntityType<?> entityType : BuiltInRegistries.ENTITY_TYPE) {
|
||||
event.registerEntity(ModCapabilities.LASER_CAPABILITY, entityType,
|
||||
(entity, ctx) -> {
|
||||
if (entity instanceof Player) {
|
||||
return new LaserCapability.LaserCapabilityImpl();
|
||||
}
|
||||
return null;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,100 @@
|
|||
package com.atsuishio.superbwarfare.capability;
|
||||
|
||||
import com.atsuishio.superbwarfare.ModUtils;
|
||||
import net.minecraft.core.HolderLookup;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.neoforged.neoforge.capabilities.ICapabilityProvider;
|
||||
import net.neoforged.neoforge.common.util.INBTSerializable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.UnknownNullability;
|
||||
|
||||
public class LaserCapability {
|
||||
|
||||
public static ResourceLocation ID = ModUtils.loc("laser_capability");
|
||||
|
||||
public interface ILaserCapability extends INBTSerializable<CompoundTag> {
|
||||
|
||||
void init(LaserHandler handler);
|
||||
|
||||
void start();
|
||||
|
||||
void tick();
|
||||
|
||||
void stop();
|
||||
|
||||
void end();
|
||||
|
||||
}
|
||||
|
||||
public static class LaserCapabilityImpl implements ILaserCapability {
|
||||
|
||||
public LaserHandler laserHandler;
|
||||
|
||||
@Override
|
||||
public void init(LaserHandler handler) {
|
||||
this.laserHandler = handler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
this.laserHandler.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
if (this.laserHandler != null) {
|
||||
this.laserHandler.stop();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void end() {
|
||||
if (this.laserHandler != null) {
|
||||
this.laserHandler.end();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public @UnknownNullability CompoundTag serializeNBT(HolderLookup.@NotNull Provider provider) {
|
||||
CompoundTag tag = new CompoundTag();
|
||||
if (this.laserHandler != null) {
|
||||
tag.put("Laser", this.laserHandler.writeNBT());
|
||||
}
|
||||
return tag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserializeNBT(HolderLookup.@NotNull Provider provider, @NotNull CompoundTag compoundTag) {
|
||||
if (compoundTag.contains("Laser") && this.laserHandler != null) {
|
||||
this.laserHandler.readNBT(compoundTag.getCompound("Laser"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class LaserCapabilityProvider implements ICapabilityProvider<Player, Void, ILaserCapability>, INBTSerializable<CompoundTag> {
|
||||
|
||||
private final LaserCapabilityImpl instance = new LaserCapabilityImpl();
|
||||
|
||||
@Override
|
||||
public @Nullable ILaserCapability getCapability(@NotNull Player object, Void context) {
|
||||
return object.getCapability(ModCapabilities.LASER_CAPABILITY, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @UnknownNullability CompoundTag serializeNBT(HolderLookup.@NotNull Provider provider) {
|
||||
return instance.serializeNBT(provider);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserializeNBT(HolderLookup.@NotNull Provider provider, @NotNull CompoundTag nbt) {
|
||||
instance.deserializeNBT(provider, nbt);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
package com.atsuishio.superbwarfare.capability;
|
||||
|
||||
import com.atsuishio.superbwarfare.entity.projectile.AbstractLaserEntity;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.Tag;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
|
||||
public class LaserHandler {
|
||||
|
||||
public boolean isUsing;
|
||||
public final LivingEntity entity;
|
||||
public final AbstractLaserEntity laserEntity;
|
||||
private int tick;
|
||||
|
||||
public LaserHandler(LivingEntity entity, AbstractLaserEntity laserEntity) {
|
||||
this.entity = entity;
|
||||
this.laserEntity = laserEntity;
|
||||
}
|
||||
|
||||
public void start() {
|
||||
this.tick = 0;
|
||||
this.isUsing = true;
|
||||
|
||||
if (this.entity.level() instanceof ServerLevel level) {
|
||||
level.addFreshEntity(this.laserEntity);
|
||||
}
|
||||
}
|
||||
|
||||
public void tick() {
|
||||
if (this.isUsing) {
|
||||
this.tick++;
|
||||
|
||||
if (this.tick > laserEntity.getDuration()) {
|
||||
this.stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 终止光束,并带有淡出效果
|
||||
*/
|
||||
public void stop() {
|
||||
if (!this.isUsing) return;
|
||||
|
||||
this.isUsing = false;
|
||||
this.tick = 0;
|
||||
if (this.laserEntity != null) {
|
||||
this.laserEntity.setDuration(3);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 直接终止光束
|
||||
*/
|
||||
public void end() {
|
||||
if (!this.isUsing) return;
|
||||
|
||||
this.isUsing = false;
|
||||
this.tick = 0;
|
||||
if (this.laserEntity != null) {
|
||||
this.laserEntity.discard();
|
||||
}
|
||||
}
|
||||
|
||||
public int getTick() {
|
||||
return this.tick;
|
||||
}
|
||||
|
||||
public CompoundTag writeNBT() {
|
||||
CompoundTag compoundTag = new CompoundTag();
|
||||
if (this.isUsing) {
|
||||
compoundTag.putInt("Tick", this.tick);
|
||||
}
|
||||
return compoundTag;
|
||||
}
|
||||
|
||||
public void readNBT(Tag nbt) {
|
||||
CompoundTag compoundTag = (CompoundTag) nbt;
|
||||
this.isUsing = compoundTag.contains("Tick");
|
||||
if (this.isUsing) {
|
||||
this.tick = compoundTag.getInt("Tick");
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isUsable() {
|
||||
return !this.isUsing;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package com.atsuishio.superbwarfare.capability;
|
||||
|
||||
import com.atsuishio.superbwarfare.ModUtils;
|
||||
import net.neoforged.neoforge.capabilities.EntityCapability;
|
||||
|
||||
public class ModCapabilities {
|
||||
|
||||
public static final EntityCapability<LaserCapability.ILaserCapability, Void> LASER_CAPABILITY = EntityCapability.createVoid(ModUtils.loc("laser_capability"), LaserCapability.ILaserCapability.class);
|
||||
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
package com.atsuishio.superbwarfare.capability.energy;
|
||||
|
||||
import net.neoforged.neoforge.energy.IEnergyStorage;
|
||||
|
||||
/**
|
||||
* 无限供电能力,纯逆天
|
||||
*/
|
||||
public class InfinityEnergyStorage implements IEnergyStorage {
|
||||
@Override
|
||||
public int receiveEnergy(int maxReceive, boolean simulate) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int extractEnergy(int maxExtract, boolean simulate) {
|
||||
return maxExtract;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getEnergyStored() {
|
||||
return Integer.MAX_VALUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxEnergyStored() {
|
||||
return Integer.MAX_VALUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canExtract() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canReceive() {
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
package com.atsuishio.superbwarfare.capability.energy;
|
||||
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.neoforged.neoforge.capabilities.Capabilities;
|
||||
import net.neoforged.neoforge.capabilities.ICapabilityProvider;
|
||||
import net.neoforged.neoforge.energy.IEnergyStorage;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class ItemEnergyProvider implements ICapabilityProvider<ItemStack, Void, IEnergyStorage> {
|
||||
|
||||
public ItemEnergyProvider(ItemStack stack, int energyCapacity) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public @org.jetbrains.annotations.Nullable IEnergyStorage getCapability(@NotNull ItemStack object, Void context) {
|
||||
return object.getCapability(Capabilities.EnergyStorage.ITEM);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
package com.atsuishio.superbwarfare.capability.energy;
|
||||
|
||||
import com.atsuishio.superbwarfare.component.ModDataComponents;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.neoforged.neoforge.energy.EnergyStorage;
|
||||
|
||||
public class ItemEnergyStorage extends EnergyStorage {
|
||||
|
||||
private final ItemStack stack;
|
||||
|
||||
public ItemEnergyStorage(ItemStack stack, int capacity) {
|
||||
super(capacity, Integer.MAX_VALUE, Integer.MAX_VALUE);
|
||||
|
||||
this.stack = stack;
|
||||
var component = stack.get(ModDataComponents.ENERGY);
|
||||
this.energy = component == null ? 0 : component;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int receiveEnergy(int maxReceive, boolean simulate) {
|
||||
int received = super.receiveEnergy(maxReceive, simulate);
|
||||
|
||||
if (received > 0 && !simulate) {
|
||||
stack.set(ModDataComponents.ENERGY, getEnergyStored());
|
||||
}
|
||||
|
||||
return received;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int extractEnergy(int maxExtract, boolean simulate) {
|
||||
int extracted = super.extractEnergy(maxExtract, simulate);
|
||||
|
||||
if (extracted > 0 && !simulate) {
|
||||
stack.set(ModDataComponents.ENERGY, getEnergyStored());
|
||||
}
|
||||
|
||||
return extracted;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
package com.atsuishio.superbwarfare.capability.energy;
|
||||
|
||||
import net.minecraft.core.HolderLookup;
|
||||
import net.minecraft.nbt.Tag;
|
||||
import net.minecraft.network.syncher.EntityDataAccessor;
|
||||
import net.minecraft.network.syncher.SynchedEntityData;
|
||||
import net.neoforged.neoforge.energy.EnergyStorage;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* 自动同步的实体能量存储能力,会和客户端自动同步实体的当前能量值
|
||||
*/
|
||||
public class SyncedEntityEnergyStorage extends EnergyStorage {
|
||||
|
||||
protected SynchedEntityData entityData;
|
||||
protected EntityDataAccessor<Integer> energyDataAccessor;
|
||||
|
||||
/**
|
||||
* 自动同步的实体能量存储能力
|
||||
*
|
||||
* @param capacity 能量上限
|
||||
* @param data 实体的entityData
|
||||
* @param energyDataAccessor 能量的EntityDataAccessor
|
||||
*/
|
||||
public SyncedEntityEnergyStorage(int capacity, SynchedEntityData data, EntityDataAccessor<Integer> energyDataAccessor) {
|
||||
super(capacity, capacity, capacity, 0);
|
||||
|
||||
this.entityData = data;
|
||||
this.energyDataAccessor = energyDataAccessor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int receiveEnergy(int maxReceive, boolean simulate) {
|
||||
var received = super.receiveEnergy(maxReceive, simulate);
|
||||
|
||||
if (!simulate) {
|
||||
entityData.set(energyDataAccessor, this.energy);
|
||||
}
|
||||
|
||||
return received;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int extractEnergy(int maxExtract, boolean simulate) {
|
||||
var extracted = super.extractEnergy(maxExtract, simulate);
|
||||
|
||||
if (!simulate) {
|
||||
entityData.set(energyDataAccessor, energy);
|
||||
}
|
||||
|
||||
return extracted;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getEnergyStored() {
|
||||
// 获取同步数据,保证客户端能正确获得能量值
|
||||
return entityData.get(energyDataAccessor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserializeNBT(HolderLookup.@NotNull Provider provider, @NotNull Tag nbt) {
|
||||
super.deserializeNBT(provider, nbt);
|
||||
entityData.set(energyDataAccessor, energy);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
package com.atsuishio.superbwarfare.client;
|
||||
|
||||
/**
|
||||
* Code based on @EEEAB's EEEABsMobs and @Mercurows's DreamaticVoyage
|
||||
*/
|
||||
public class AnimationTicker {
|
||||
|
||||
private int tick;
|
||||
private int prevTick;
|
||||
private int duration;
|
||||
|
||||
public AnimationTicker(int duration) {
|
||||
this.tick = 0;
|
||||
this.prevTick = 0;
|
||||
this.duration = duration;
|
||||
}
|
||||
|
||||
public void setDuration(int duration) {
|
||||
this.tick = 0;
|
||||
this.prevTick = 0;
|
||||
this.duration = duration;
|
||||
}
|
||||
|
||||
public int getTick() {
|
||||
return this.tick;
|
||||
}
|
||||
|
||||
public boolean isStopped() {
|
||||
return this.tick == 0 && this.prevTick == 0;
|
||||
}
|
||||
|
||||
public boolean isEnded() {
|
||||
return this.tick == this.duration || this.prevTick == this.duration;
|
||||
}
|
||||
|
||||
public int getPrevTick() {
|
||||
return this.prevTick;
|
||||
}
|
||||
|
||||
public int getDuration() {
|
||||
return this.duration;
|
||||
}
|
||||
|
||||
public void changeTimer(boolean flag) {
|
||||
changeTimer(flag, 1);
|
||||
}
|
||||
|
||||
public void changeTimer(boolean add, int time) {
|
||||
if (add) {
|
||||
increaseTimer(time);
|
||||
} else {
|
||||
decreaseTimer(time);
|
||||
}
|
||||
}
|
||||
|
||||
public void increaseTimer(int time) {
|
||||
int newTime = this.tick + time;
|
||||
if (newTime <= duration && newTime >= 0) {
|
||||
this.tick = newTime;
|
||||
} else {
|
||||
this.tick = newTime < 0 ? 0 : duration;
|
||||
}
|
||||
}
|
||||
|
||||
public void decreaseTimer(int time) {
|
||||
if (this.tick - time > 0.0D) {
|
||||
this.tick -= time;
|
||||
} else {
|
||||
this.tick = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public void updatePrevTimer() {
|
||||
this.prevTick = this.tick;
|
||||
}
|
||||
|
||||
public void resetTimer() {
|
||||
this.tick = 0;
|
||||
this.prevTick = 0;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
package com.atsuishio.superbwarfare.component;
|
||||
|
||||
import com.atsuishio.superbwarfare.ModUtils;
|
||||
import com.mojang.serialization.Codec;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.component.DataComponentType;
|
||||
import net.minecraft.core.registries.Registries;
|
||||
|
@ -19,6 +20,11 @@ public class ModDataComponents {
|
|||
builder -> builder.persistent(BlockPos.CODEC)
|
||||
);
|
||||
|
||||
public static final DeferredHolder<DataComponentType<?>, DataComponentType<Integer>> ENERGY = register(
|
||||
"energy",
|
||||
builder -> builder.persistent(Codec.INT)
|
||||
);
|
||||
|
||||
private static <T> DeferredHolder<DataComponentType<?>, DataComponentType<T>> register(String name, UnaryOperator<DataComponentType.Builder<T>> builderOperator) {
|
||||
return DATA_COMPONENT_TYPES.register(name, () -> builderOperator.apply(DataComponentType.builder()).build());
|
||||
}
|
||||
|
|
|
@ -0,0 +1,273 @@
|
|||
package com.atsuishio.superbwarfare.entity.projectile;
|
||||
|
||||
import com.atsuishio.superbwarfare.client.AnimationTicker;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.syncher.EntityDataAccessor;
|
||||
import net.minecraft.network.syncher.EntityDataSerializers;
|
||||
import net.minecraft.network.syncher.SynchedEntityData;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.TraceableEntity;
|
||||
import net.minecraft.world.level.ClipContext;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.gameevent.GameEvent;
|
||||
import net.minecraft.world.level.material.PushReaction;
|
||||
import net.minecraft.world.phys.*;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Code based on @BobMowzie's MowziesMobs, @EEEAB's EEEABsMobs and @Mercurows's DreamaticVoyage
|
||||
*/
|
||||
public abstract class AbstractLaserEntity extends Entity implements TraceableEntity {
|
||||
|
||||
public LivingEntity caster;
|
||||
public float yaw, pitch;
|
||||
public float preYaw, prePitch;
|
||||
public double endPosX, endPosY, endPosZ;
|
||||
public double collidePosX, collidePosY, collidePosZ;
|
||||
public double prevCollidePosX, prevCollidePosY, prevCollidePosZ;
|
||||
public Direction blockSide = null;
|
||||
public boolean on = true;
|
||||
public AnimationTicker ticker = new AnimationTicker(3);
|
||||
|
||||
private static final EntityDataAccessor<Integer> DATA_CASTER_ID = SynchedEntityData.defineId(AbstractLaserEntity.class, EntityDataSerializers.INT);
|
||||
private static final EntityDataAccessor<Float> DATA_YAW = SynchedEntityData.defineId(AbstractLaserEntity.class, EntityDataSerializers.FLOAT);
|
||||
private static final EntityDataAccessor<Float> DATA_PITCH = SynchedEntityData.defineId(AbstractLaserEntity.class, EntityDataSerializers.FLOAT);
|
||||
private static final EntityDataAccessor<Integer> DATA_DURATION = SynchedEntityData.defineId(AbstractLaserEntity.class, EntityDataSerializers.INT);
|
||||
private static final EntityDataAccessor<Integer> DATA_COUNT_DOWN = SynchedEntityData.defineId(AbstractLaserEntity.class, EntityDataSerializers.INT);
|
||||
|
||||
public AbstractLaserEntity(EntityType<?> type, Level level, int countDown) {
|
||||
super(type, level);
|
||||
this.setCountDown(countDown);
|
||||
this.noCulling = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
super.tick();
|
||||
this.prevCollidePosX = this.collidePosX;
|
||||
this.prevCollidePosY = this.collidePosY;
|
||||
this.prevCollidePosZ = this.collidePosZ;
|
||||
this.preYaw = this.yaw;
|
||||
this.prePitch = this.pitch;
|
||||
this.yaw = this.getYaw();
|
||||
this.pitch = this.getPitch();
|
||||
this.xo = this.getX();
|
||||
this.yo = this.getY();
|
||||
this.zo = this.getZ();
|
||||
if (this.tickCount == 1 && this.level().isClientSide) {
|
||||
this.caster = (LivingEntity) this.level().getEntity(getCasterId());
|
||||
}
|
||||
|
||||
this.beamTick();
|
||||
|
||||
if ((!this.on && this.ticker.isStopped()) || (this.caster != null && !this.caster.isAlive())) {
|
||||
this.discard();
|
||||
}
|
||||
this.ticker.changeTimer(this.on && this.isAccumulating());
|
||||
|
||||
if (this.tickCount - this.getCountDown() > this.getDuration()) {
|
||||
this.on = false;
|
||||
}
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public Packet<ClientGamePacketListener> getAddEntityPacket() {
|
||||
// return NetworkHooks.getEntitySpawningPacket(this);
|
||||
// }
|
||||
|
||||
@Override
|
||||
protected void readAdditionalSaveData(CompoundTag pCompound) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addAdditionalSaveData(CompoundTag pCompound) {
|
||||
|
||||
}
|
||||
|
||||
protected void beamTick() {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public LivingEntity getOwner() {
|
||||
return caster;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPickable() {
|
||||
return super.isPickable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void push(Entity entityIn) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public PushReaction getPistonPushReaction() {
|
||||
return PushReaction.IGNORE;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void defineSynchedData(SynchedEntityData.Builder builder) {
|
||||
builder
|
||||
.define(DATA_CASTER_ID, -1)
|
||||
.define(DATA_YAW, 0F)
|
||||
.define(DATA_PITCH, 0F)
|
||||
.define(DATA_DURATION, 0)
|
||||
.define(DATA_COUNT_DOWN, 0);
|
||||
}
|
||||
|
||||
public void setCasterId(int id) {
|
||||
this.entityData.set(DATA_CASTER_ID, id);
|
||||
}
|
||||
|
||||
public int getCasterId() {
|
||||
return this.entityData.get(DATA_CASTER_ID);
|
||||
}
|
||||
|
||||
public boolean isAccumulating() {
|
||||
return this.tickCount > this.getCountDown();
|
||||
}
|
||||
|
||||
public float getYaw() {
|
||||
return getEntityData().get(DATA_YAW);
|
||||
}
|
||||
|
||||
public void setYaw(float rotAngle) {
|
||||
getEntityData().set(DATA_YAW, rotAngle);
|
||||
}
|
||||
|
||||
public float getPitch() {
|
||||
return getEntityData().get(DATA_PITCH);
|
||||
}
|
||||
|
||||
public void setPitch(float rotAngle) {
|
||||
getEntityData().set(DATA_PITCH, rotAngle);
|
||||
}
|
||||
|
||||
public int getDuration() {
|
||||
return getEntityData().get(DATA_DURATION);
|
||||
}
|
||||
|
||||
public void setDuration(int duration) {
|
||||
getEntityData().set(DATA_DURATION, duration);
|
||||
}
|
||||
|
||||
public int getCountDown() {
|
||||
return getEntityData().get(DATA_COUNT_DOWN);
|
||||
}
|
||||
|
||||
public void setCountDown(int countDown) {
|
||||
getEntityData().set(DATA_COUNT_DOWN, countDown);
|
||||
}
|
||||
|
||||
protected void calculateEndPos(double radius) {
|
||||
if (level().isClientSide()) {
|
||||
endPosX = getX() + radius * Math.cos(yaw) * Math.cos(pitch);
|
||||
endPosZ = getZ() + radius * Math.sin(yaw) * Math.cos(pitch);
|
||||
endPosY = getY() + radius * Math.sin(pitch);
|
||||
} else {
|
||||
endPosX = getX() + radius * Math.cos(getYaw()) * Math.cos(getPitch());
|
||||
endPosZ = getZ() + radius * Math.sin(getYaw()) * Math.cos(getPitch());
|
||||
endPosY = getY() + radius * Math.sin(getPitch());
|
||||
}
|
||||
}
|
||||
|
||||
public CustomHitResult raytraceEntities(Level world, Vec3 from, Vec3 to) {
|
||||
CustomHitResult result = new CustomHitResult();
|
||||
result.setBlockHit(world.clip(new ClipContext(from, to, ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, this)));
|
||||
if (result.getBlockHit() != null) {
|
||||
Vec3 hitVec = result.getBlockHit().getLocation();
|
||||
collidePosX = hitVec.x;
|
||||
collidePosY = hitVec.y;
|
||||
collidePosZ = hitVec.z;
|
||||
blockSide = result.getBlockHit().getDirection();
|
||||
} else {
|
||||
collidePosX = endPosX;
|
||||
collidePosY = endPosY;
|
||||
collidePosZ = endPosZ;
|
||||
blockSide = null;
|
||||
}
|
||||
List<LivingEntity> entities = world.getEntitiesOfClass(LivingEntity.class, new AABB(Math.min(getX(), collidePosX), Math.min(getY(), collidePosY), Math.min(getZ(), collidePosZ), Math.max(getX(), collidePosX), Math.max(getY(), collidePosY), Math.max(getZ(), collidePosZ)).inflate(1, 1, 1));
|
||||
for (LivingEntity entity : entities) {
|
||||
if (entity == this.caster) {
|
||||
continue;
|
||||
}
|
||||
float pad = entity.getPickRadius() + getBaseScale();
|
||||
AABB aabb = entity.getBoundingBox().inflate(pad, pad, pad);
|
||||
Optional<Vec3> hit = aabb.clip(from, to);
|
||||
if (aabb.contains(from)) {
|
||||
result.addEntityHit(entity);
|
||||
} else if (hit.isPresent()) {
|
||||
result.addEntityHit(entity);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAttackable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean displayFireAnimation() {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected void onHit(HitResult hitResult) {
|
||||
HitResult.Type hitresult$type = hitResult.getType();
|
||||
if (hitresult$type == HitResult.Type.ENTITY) {
|
||||
this.onHitEntity((EntityHitResult) hitResult);
|
||||
this.level().gameEvent(GameEvent.PROJECTILE_LAND, hitResult.getLocation(), GameEvent.Context.of(this, null));
|
||||
} else if (hitresult$type == HitResult.Type.BLOCK) {
|
||||
BlockHitResult blockhitresult = (BlockHitResult) hitResult;
|
||||
this.onHitBlock(blockhitresult);
|
||||
BlockPos blockpos = blockhitresult.getBlockPos();
|
||||
this.level().gameEvent(GameEvent.PROJECTILE_LAND, blockpos, GameEvent.Context.of(this, this.level().getBlockState(blockpos)));
|
||||
}
|
||||
}
|
||||
|
||||
protected void onHitEntity(EntityHitResult result) {
|
||||
}
|
||||
|
||||
protected void onHitBlock(BlockHitResult result) {
|
||||
}
|
||||
|
||||
protected float getBaseScale() {
|
||||
return 0.5F;
|
||||
}
|
||||
|
||||
public static class CustomHitResult {
|
||||
|
||||
private BlockHitResult blockHit;
|
||||
private final List<LivingEntity> entities = new ArrayList<>();
|
||||
|
||||
public BlockHitResult getBlockHit() {
|
||||
return blockHit;
|
||||
}
|
||||
|
||||
public List<LivingEntity> getEntities() {
|
||||
return entities;
|
||||
}
|
||||
|
||||
public void setBlockHit(HitResult rayTraceResult) {
|
||||
if (rayTraceResult.getType() == HitResult.Type.BLOCK)
|
||||
this.blockHit = (BlockHitResult) rayTraceResult;
|
||||
}
|
||||
|
||||
public void addEntityHit(LivingEntity entity) {
|
||||
entities.add(entity);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,141 @@
|
|||
package com.atsuishio.superbwarfare.entity.projectile;
|
||||
|
||||
import com.atsuishio.superbwarfare.init.ModEntities;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.level.ClipContext;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.phys.AABB;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Code based on @BobMowzie's MowziesMobs, @EEEAB's EEEABsMobs and @Mercurows's DreamaticVoyage
|
||||
*/
|
||||
public class LaserEntity extends AbstractLaserEntity {
|
||||
|
||||
public static final double RADIUS = 512D;
|
||||
|
||||
public LaserEntity(EntityType<? extends LaserEntity> type, Level level) {
|
||||
super(type, level, 1);
|
||||
}
|
||||
|
||||
public LaserEntity(Level level, LivingEntity caster, double x, double y, double z, float yaw, float pitch, int duration) {
|
||||
super(ModEntities.LASER.get(), level, 1);
|
||||
this.caster = caster;
|
||||
this.setYaw(yaw);
|
||||
this.setPitch(pitch);
|
||||
this.setDuration(duration);
|
||||
this.setPos(x, y, z);
|
||||
this.calculateEndPos(RADIUS);
|
||||
if (!level().isClientSide) {
|
||||
setCasterId(caster.getId());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beamTick() {
|
||||
if (!this.level().isClientSide) {
|
||||
if (this.caster instanceof Player) {
|
||||
this.updateWithPlayer();
|
||||
} else if (this.caster != null) {
|
||||
this.updateWithEntity();
|
||||
}
|
||||
}
|
||||
|
||||
if (caster != null) {
|
||||
this.yaw = (float) Math.toRadians(caster.yHeadRot + 90);
|
||||
this.pitch = (float) -Math.toRadians(caster.getXRot());
|
||||
}
|
||||
|
||||
if (this.tickCount >= this.getCountDown()) {
|
||||
this.calculateEndPos(RADIUS);
|
||||
|
||||
raytraceEntities(this.level(), new Vec3(getX(), getY(), getZ()), new Vec3(endPosX, endPosY, endPosZ));
|
||||
|
||||
if (this.blockSide != null) {
|
||||
this.spawnExplosionParticles();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CustomHitResult raytraceEntities(Level world, Vec3 from, Vec3 to) {
|
||||
CustomHitResult result = new CustomHitResult();
|
||||
result.setBlockHit(this.level().clip(new ClipContext(new Vec3(getX(), getY(), getZ()), new Vec3(endPosX, endPosY, endPosZ),
|
||||
ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, this)));
|
||||
if (result.getBlockHit() != null) {
|
||||
Vec3 hitVec = result.getBlockHit().getLocation();
|
||||
collidePosX = hitVec.x;
|
||||
collidePosY = hitVec.y;
|
||||
collidePosZ = hitVec.z;
|
||||
blockSide = result.getBlockHit().getDirection();
|
||||
} else {
|
||||
List<LivingEntity> entities = world.getEntitiesOfClass(LivingEntity.class, new AABB(Math.min(getX(), collidePosX), Math.min(getY(), collidePosY), Math.min(getZ(), collidePosZ), Math.max(getX(), collidePosX), Math.max(getY(), collidePosY), Math.max(getZ(), collidePosZ)).inflate(1, 1, 1));
|
||||
for (LivingEntity entity : entities) {
|
||||
if (entity == this.caster) {
|
||||
continue;
|
||||
}
|
||||
float pad = entity.getPickRadius() + getBaseScale();
|
||||
AABB aabb = entity.getBoundingBox().inflate(pad, pad, pad);
|
||||
Optional<Vec3> hit = aabb.clip(from, to);
|
||||
if (aabb.contains(from)) {
|
||||
result.addEntityHit(entity);
|
||||
} else if (hit.isPresent()) {
|
||||
result.addEntityHit(entity);
|
||||
}
|
||||
}
|
||||
|
||||
var target = result.getEntities().stream().min(Comparator.comparingDouble(e -> e.distanceToSqr(this.caster)));
|
||||
if (target.isPresent()) {
|
||||
collidePosX = target.get().getX();
|
||||
collidePosY = target.get().getY();
|
||||
collidePosZ = target.get().getZ();
|
||||
} else {
|
||||
collidePosX = endPosX;
|
||||
collidePosY = endPosY;
|
||||
collidePosZ = endPosZ;
|
||||
}
|
||||
blockSide = null;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public void spawnExplosionParticles() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void readAdditionalSaveData(CompoundTag compoundTag) {
|
||||
if (this.caster == null) {
|
||||
discard();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldRenderAtSqrDistance(double distance) {
|
||||
return true;
|
||||
}
|
||||
|
||||
private void updateWithPlayer() {
|
||||
this.setYaw((float) Math.toRadians(caster.yHeadRot + 90));
|
||||
this.setPitch((float) Math.toRadians(-caster.getXRot()));
|
||||
Vec3 vecOffset = caster.getLookAngle().normalize().scale(1.25);
|
||||
this.setPos(caster.getX() + vecOffset.x(), caster.getY() + caster.getBbHeight() * 0.5F + vecOffset.y(), caster.getZ() + vecOffset.z());
|
||||
}
|
||||
|
||||
private void updateWithEntity() {
|
||||
double radians = Math.toRadians(this.caster.yHeadRot + 90);
|
||||
this.setYaw((float) radians);
|
||||
this.setPitch((float) ((double) (-this.caster.getXRot()) * Math.PI / 180.0));
|
||||
double offsetX = Math.cos(radians) * (float) 0.0;
|
||||
double offsetZ = Math.sin(radians) * (float) 0.0;
|
||||
this.setPos(this.caster.getX() + offsetX, this.caster.getY((float) 0.75), this.caster.getZ() + offsetZ);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
package com.atsuishio.superbwarfare.init;
|
||||
|
||||
import com.atsuishio.superbwarfare.ModUtils;
|
||||
import com.atsuishio.superbwarfare.block.entity.ChargingStationBlockEntity;
|
||||
import com.atsuishio.superbwarfare.block.entity.ContainerBlockEntity;
|
||||
import com.atsuishio.superbwarfare.block.entity.CreativeChargingStationBlockEntity;
|
||||
import com.atsuishio.superbwarfare.block.entity.FuMO25BlockEntity;
|
||||
import net.minecraft.core.registries.BuiltInRegistries;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
import net.neoforged.neoforge.registries.DeferredHolder;
|
||||
import net.neoforged.neoforge.registries.DeferredRegister;
|
||||
|
||||
public class ModBlockEntities {
|
||||
|
||||
public static final DeferredRegister<BlockEntityType<?>> REGISTRY = DeferredRegister.create(BuiltInRegistries.BLOCK_ENTITY_TYPE, ModUtils.MODID);
|
||||
|
||||
public static final DeferredHolder<BlockEntityType<?>, BlockEntityType<ContainerBlockEntity>> CONTAINER = REGISTRY.register("container",
|
||||
() -> BlockEntityType.Builder.of(ContainerBlockEntity::new, ModBlocks.CONTAINER.get()).build(null));
|
||||
public static final DeferredHolder<BlockEntityType<?>, BlockEntityType<ChargingStationBlockEntity>> CHARGING_STATION = REGISTRY.register("charging_station",
|
||||
() -> BlockEntityType.Builder.of(ChargingStationBlockEntity::new, ModBlocks.CHARGING_STATION.get()).build(null));
|
||||
public static final DeferredHolder<BlockEntityType<?>, BlockEntityType<CreativeChargingStationBlockEntity>> CREATIVE_CHARGING_STATION = REGISTRY.register("creative_charging_station",
|
||||
() -> BlockEntityType.Builder.of(CreativeChargingStationBlockEntity::new, ModBlocks.CREATIVE_CHARGING_STATION.get()).build(null));
|
||||
public static final DeferredHolder<BlockEntityType<?>, BlockEntityType<FuMO25BlockEntity>> FUMO_25 = REGISTRY.register("fumo_25",
|
||||
() -> BlockEntityType.Builder.of(FuMO25BlockEntity::new, ModBlocks.FUMO_25.get()).build(null));
|
||||
|
||||
}
|
|
@ -1,10 +1,7 @@
|
|||
package com.atsuishio.superbwarfare.init;
|
||||
|
||||
import com.atsuishio.superbwarfare.ModUtils;
|
||||
import com.atsuishio.superbwarfare.block.BarbedWireBlock;
|
||||
import com.atsuishio.superbwarfare.block.DragonTeethBlock;
|
||||
import com.atsuishio.superbwarfare.block.JumpPadBlock;
|
||||
import com.atsuishio.superbwarfare.block.ReforgingTableBlock;
|
||||
import com.atsuishio.superbwarfare.block.*;
|
||||
import net.minecraft.core.registries.BuiltInRegistries;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.SoundType;
|
||||
|
@ -46,9 +43,8 @@ public class ModBlocks {
|
|||
() -> new Block(BlockBehaviour.Properties.of().instrument(NoteBlockInstrument.BASEDRUM).sound(SoundType.METAL).strength(5f, 6f).requiresCorrectToolForDrops()));
|
||||
public static final DeferredHolder<Block, Block> CEMENTED_CARBIDE_BLOCK = REGISTRY.register("cemented_carbide_block",
|
||||
() -> new Block(BlockBehaviour.Properties.of().instrument(NoteBlockInstrument.BASEDRUM).sound(SoundType.METAL).strength(5f, 6f).requiresCorrectToolForDrops()));
|
||||
// TODO blocks
|
||||
// public static final DeferredHolder<Block, Block> CONTAINER = REGISTRY.register("container", ContainerBlock::new);
|
||||
// public static final DeferredHolder<Block, Block> CHARGING_STATION = REGISTRY.register("charging_station", ChargingStationBlock::new);
|
||||
// public static final DeferredHolder<Block, Block> CREATIVE_CHARGING_STATION = REGISTRY.register("creative_charging_station", CreativeChargingStationBlock::new);
|
||||
// public static final DeferredHolder<Block, Block> FUMO_25 = REGISTRY.register("fumo_25", FuMO25Block::new);
|
||||
public static final DeferredHolder<Block, Block> CONTAINER = REGISTRY.register("container", ContainerBlock::new);
|
||||
public static final DeferredHolder<Block, Block> CHARGING_STATION = REGISTRY.register("charging_station", ChargingStationBlock::new);
|
||||
public static final DeferredHolder<Block, Block> CREATIVE_CHARGING_STATION = REGISTRY.register("creative_charging_station", () -> new CreativeChargingStationBlock());
|
||||
public static final DeferredHolder<Block, Block> FUMO_25 = REGISTRY.register("fumo_25", FuMO25Block::new);
|
||||
}
|
||||
|
|
115
src/main/java/com/atsuishio/superbwarfare/init/ModEntities.java
Normal file
115
src/main/java/com/atsuishio/superbwarfare/init/ModEntities.java
Normal file
|
@ -0,0 +1,115 @@
|
|||
package com.atsuishio.superbwarfare.init;
|
||||
|
||||
import com.atsuishio.superbwarfare.ModUtils;
|
||||
import com.atsuishio.superbwarfare.entity.projectile.LaserEntity;
|
||||
import net.minecraft.core.registries.BuiltInRegistries;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.entity.MobCategory;
|
||||
import net.neoforged.bus.api.SubscribeEvent;
|
||||
import net.neoforged.fml.common.EventBusSubscriber;
|
||||
import net.neoforged.neoforge.event.entity.EntityAttributeCreationEvent;
|
||||
import net.neoforged.neoforge.registries.DeferredHolder;
|
||||
import net.neoforged.neoforge.registries.DeferredRegister;
|
||||
|
||||
@EventBusSubscriber(bus = EventBusSubscriber.Bus.MOD)
|
||||
public class ModEntities {
|
||||
|
||||
public static final DeferredRegister<EntityType<?>> REGISTRY = DeferredRegister.create(BuiltInRegistries.ENTITY_TYPE, ModUtils.MODID);
|
||||
|
||||
// // Living Entities
|
||||
// public static final DeferredHolder<EntityType<?>, EntityType<TargetEntity>> TARGET = register("target",
|
||||
// EntityType.Builder.<TargetEntity>of(TargetEntity::new, MobCategory.CREATURE).setTrackingRange(64).setUpdateInterval(3).setCustomClientFactory(TargetEntity::new).fireImmune().sized(0.875f, 2f));
|
||||
// public static final DeferredHolder<EntityType<?>, EntityType<SenpaiEntity>> SENPAI = register("senpai",
|
||||
// EntityType.Builder.<SenpaiEntity>of(SenpaiEntity::new, MobCategory.MONSTER).setTrackingRange(64).setUpdateInterval(3).setCustomClientFactory(SenpaiEntity::new)
|
||||
// .sized(0.6f, 2f));
|
||||
//
|
||||
// // Misc Entities
|
||||
// public static final DeferredHolder<EntityType<?>, EntityType<MortarEntity>> MORTAR = register("mortar",
|
||||
// EntityType.Builder.<MortarEntity>of(MortarEntity::new, MobCategory.MISC).setTrackingRange(64).setUpdateInterval(3).setCustomClientFactory(MortarEntity::new).fireImmune().sized(0.8f, 1.4f));
|
||||
public static final DeferredHolder<EntityType<?>, EntityType<LaserEntity>> LASER = register("laser",
|
||||
EntityType.Builder.<LaserEntity>of(LaserEntity::new, MobCategory.MISC).sized(0.1f, 0.1f).fireImmune().setUpdateInterval(1));
|
||||
// public static final DeferredHolder<EntityType<?>, EntityType<FlareDecoyEntity>> FLARE_DECOY = register("flare_decoy",
|
||||
// EntityType.Builder.<FlareDecoyEntity>of(FlareDecoyEntity::new, MobCategory.MISC).setTrackingRange(64).setUpdateInterval(1).setCustomClientFactory(FlareDecoyEntity::new).sized(0.5f, 0.5f));
|
||||
// public static final DeferredHolder<EntityType<?>, EntityType<ClaymoreEntity>> CLAYMORE = register("claymore",
|
||||
// EntityType.Builder.<ClaymoreEntity>of(ClaymoreEntity::new, MobCategory.MISC).setTrackingRange(64).setUpdateInterval(1).sized(0.5f, 0.5f));
|
||||
// public static final DeferredHolder<EntityType<?>, EntityType<C4Entity>> C_4 = register("c4",
|
||||
// EntityType.Builder.<C4Entity>of(C4Entity::new, MobCategory.MISC).setTrackingRange(64).setUpdateInterval(1).sized(0.5f, 0.5f));
|
||||
//
|
||||
// // Projectiles
|
||||
// public static final DeferredHolder<EntityType<?>, EntityType<TaserBulletEntity>> TASER_BULLET = register("taser_bullet",
|
||||
// EntityType.Builder.<TaserBulletEntity>of(TaserBulletEntity::new, MobCategory.MISC).setCustomClientFactory(TaserBulletEntity::new).setTrackingRange(64)
|
||||
// .setUpdateInterval(1).sized(0.5f, 0.5f));
|
||||
//
|
||||
// // Fast Projectiles
|
||||
// public static final DeferredHolder<EntityType<?>, EntityType<SmallCannonShellEntity>> SMALL_CANNON_SHELL = register("small_cannon_shell",
|
||||
// EntityType.Builder.<SmallCannonShellEntity>of(SmallCannonShellEntity::new, MobCategory.MISC).setShouldReceiveVelocityUpdates(false).setTrackingRange(64).setUpdateInterval(1).setCustomClientFactory(SmallCannonShellEntity::new).sized(0.5f, 0.5f));
|
||||
// public static final DeferredHolder<EntityType<?>, EntityType<RpgRocketEntity>> RPG_ROCKET = register("rpg_rocket",
|
||||
// EntityType.Builder.<RpgRocketEntity>of(RpgRocketEntity::new, MobCategory.MISC).setShouldReceiveVelocityUpdates(false).setTrackingRange(64).setUpdateInterval(1).setCustomClientFactory(RpgRocketEntity::new).sized(0.5f, 0.5f));
|
||||
// public static final DeferredHolder<EntityType<?>, EntityType<MortarShellEntity>> MORTAR_SHELL = register("mortar_shell",
|
||||
// EntityType.Builder.<MortarShellEntity>of(MortarShellEntity::new, MobCategory.MISC).setShouldReceiveVelocityUpdates(false).setTrackingRange(64).setUpdateInterval(1).setCustomClientFactory(MortarShellEntity::new).sized(0.5f, 0.5f));
|
||||
// public static final DeferredHolder<EntityType<?>, EntityType<ProjectileEntity>> PROJECTILE = register("projectile",
|
||||
// EntityType.Builder.<ProjectileEntity>of(ProjectileEntity::new, MobCategory.MISC).setShouldReceiveVelocityUpdates(false).setCustomClientFactory(ProjectileEntity::new).setTrackingRange(64).noSave().noSummon().sized(0.25f, 0.25f));
|
||||
// public static final DeferredHolder<EntityType<?>, EntityType<CannonShellEntity>> CANNON_SHELL = register("cannon_shell",
|
||||
// EntityType.Builder.<CannonShellEntity>of(CannonShellEntity::new, MobCategory.MISC).setShouldReceiveVelocityUpdates(false).setTrackingRange(64).setUpdateInterval(1).setCustomClientFactory(CannonShellEntity::new).sized(0.5f, 0.5f));
|
||||
// public static final DeferredHolder<EntityType<?>, EntityType<GunGrenadeEntity>> GUN_GRENADE = register("gun_grenade",
|
||||
// EntityType.Builder.<GunGrenadeEntity>of(GunGrenadeEntity::new, MobCategory.MISC).setShouldReceiveVelocityUpdates(false).setTrackingRange(64).setUpdateInterval(1).setCustomClientFactory(GunGrenadeEntity::new).sized(0.5f, 0.5f));
|
||||
// public static final DeferredHolder<EntityType<?>, EntityType<MelonBombEntity>> MELON_BOMB = register("melon_bomb",
|
||||
// EntityType.Builder.<MelonBombEntity>of(MelonBombEntity::new, MobCategory.MISC).setShouldReceiveVelocityUpdates(false).setTrackingRange(64).setUpdateInterval(1).setCustomClientFactory(MelonBombEntity::new).sized(1f, 1f));
|
||||
// public static final DeferredHolder<EntityType<?>, EntityType<HandGrenadeEntity>> HAND_GRENADE = register("hand_grenade",
|
||||
// EntityType.Builder.<HandGrenadeEntity>of(HandGrenadeEntity::new, MobCategory.MISC).setShouldReceiveVelocityUpdates(false).setTrackingRange(64).setUpdateInterval(1).setCustomClientFactory(HandGrenadeEntity::new).sized(0.3f, 0.3f));
|
||||
// public static final DeferredHolder<EntityType<?>, EntityType<RgoGrenadeEntity>> RGO_GRENADE = register("rgo_grenade",
|
||||
// EntityType.Builder.<RgoGrenadeEntity>of(RgoGrenadeEntity::new, MobCategory.MISC).setShouldReceiveVelocityUpdates(false).setTrackingRange(64).setUpdateInterval(1).setCustomClientFactory(RgoGrenadeEntity::new).sized(0.3f, 0.3f));
|
||||
// public static final DeferredHolder<EntityType<?>, EntityType<JavelinMissileEntity>> JAVELIN_MISSILE = register("javelin_missile",
|
||||
// EntityType.Builder.<JavelinMissileEntity>of(JavelinMissileEntity::new, MobCategory.MISC).setShouldReceiveVelocityUpdates(false).setTrackingRange(64).setUpdateInterval(1).setCustomClientFactory(JavelinMissileEntity::new).sized(0.5f, 0.5f));
|
||||
// public static final DeferredHolder<EntityType<?>, EntityType<HeliRocketEntity>> HELI_ROCKET = register("heli_rocket",
|
||||
// EntityType.Builder.<HeliRocketEntity>of(HeliRocketEntity::new, MobCategory.MISC).setShouldReceiveVelocityUpdates(false).setTrackingRange(64).setUpdateInterval(1).setCustomClientFactory(HeliRocketEntity::new).sized(0.5f, 0.5f));
|
||||
// public static final DeferredHolder<EntityType<?>, EntityType<WgMissileEntity>> WG_MISSILE = register("wg_missile",
|
||||
// EntityType.Builder.<WgMissileEntity>of(WgMissileEntity::new, MobCategory.MISC).setShouldReceiveVelocityUpdates(false).setTrackingRange(64).setUpdateInterval(3).setCustomClientFactory(WgMissileEntity::new).fireImmune().sized(0.5f, 0.5f));
|
||||
//
|
||||
// // Vehicles
|
||||
// public static final DeferredHolder<EntityType<?>, EntityType<Mk42Entity>> MK_42 = register("mk_42",
|
||||
// EntityType.Builder.<Mk42Entity>of(Mk42Entity::new, MobCategory.MISC).setTrackingRange(64).setUpdateInterval(3).setCustomClientFactory(Mk42Entity::new).fireImmune().sized(3.4f, 3.5f));
|
||||
// public static final DeferredHolder<EntityType<?>, EntityType<Mle1934Entity>> MLE_1934 = register("mle_1934",
|
||||
// EntityType.Builder.<Mle1934Entity>of(Mle1934Entity::new, MobCategory.MISC).setTrackingRange(64).setUpdateInterval(3).setCustomClientFactory(Mle1934Entity::new).fireImmune().sized(4.5f, 2.8f));
|
||||
// public static final DeferredHolder<EntityType<?>, EntityType<AnnihilatorEntity>> ANNIHILATOR = register("annihilator",
|
||||
// EntityType.Builder.<AnnihilatorEntity>of(AnnihilatorEntity::new, MobCategory.MISC).setTrackingRange(64).setUpdateInterval(3).setCustomClientFactory(AnnihilatorEntity::new).fireImmune().sized(13f, 4.2f));
|
||||
//
|
||||
// public static final DeferredHolder<EntityType<?>, EntityType<SpeedboatEntity>> SPEEDBOAT = register("speedboat",
|
||||
// EntityType.Builder.<SpeedboatEntity>of(SpeedboatEntity::new, MobCategory.MISC).setTrackingRange(64).setUpdateInterval(3).setCustomClientFactory(SpeedboatEntity::new).fireImmune().sized(3.0f, 2.0f));
|
||||
// public static final DeferredHolder<EntityType<?>, EntityType<WheelChairEntity>> WHEEL_CHAIR = register("wheel_chair",
|
||||
// EntityType.Builder.<WheelChairEntity>of(WheelChairEntity::new, MobCategory.MISC).setTrackingRange(64).setUpdateInterval(3).setCustomClientFactory(WheelChairEntity::new).fireImmune().sized(1.0f, 1.0f));
|
||||
// public static final DeferredHolder<EntityType<?>, EntityType<Ah6Entity>> AH_6 = register("ah_6",
|
||||
// EntityType.Builder.<Ah6Entity>of(Ah6Entity::new, MobCategory.MISC).setTrackingRange(64).setUpdateInterval(3).setCustomClientFactory(Ah6Entity::new).fireImmune().sized(2.8f, 2.9f));
|
||||
// public static final DeferredHolder<EntityType<?>, EntityType<Lav150Entity>> LAV_150 = register("lav_150",
|
||||
// EntityType.Builder.<Lav150Entity>of(Lav150Entity::new, MobCategory.MISC).setTrackingRange(64).setUpdateInterval(3).setCustomClientFactory(Lav150Entity::new).fireImmune().sized(2.8f, 3.1f));
|
||||
// public static final DeferredHolder<EntityType<?>, EntityType<Tom6Entity>> TOM_6 = register("tom_6",
|
||||
// EntityType.Builder.<Tom6Entity>of(Tom6Entity::new, MobCategory.MISC).setTrackingRange(64).setUpdateInterval(3).setCustomClientFactory(Tom6Entity::new).fireImmune().sized(1.05f, 1.0f));
|
||||
// public static final DeferredHolder<EntityType<?>, EntityType<Bmp2Entity>> BMP_2 = register("bmp_2",
|
||||
// EntityType.Builder.<Bmp2Entity>of(Bmp2Entity::new, MobCategory.MISC).setTrackingRange(64).setUpdateInterval(3).setCustomClientFactory(Bmp2Entity::new).fireImmune().sized(4f, 3f));
|
||||
// public static final DeferredHolder<EntityType<?>, EntityType<Yx100Entity>> YX_100 = register("yx_100",
|
||||
// EntityType.Builder.<Yx100Entity>of(Yx100Entity::new, MobCategory.MISC).setTrackingRange(64).setUpdateInterval(3).setCustomClientFactory(Yx100Entity::new).fireImmune().sized(5.5f, 3.25f));
|
||||
//
|
||||
// public static final DeferredHolder<EntityType<?>, EntityType<DroneEntity>> DRONE = register("drone",
|
||||
// EntityType.Builder.<DroneEntity>of(DroneEntity::new, MobCategory.MISC).setTrackingRange(64).setUpdateInterval(3).setCustomClientFactory(DroneEntity::new).sized(0.6f, 0.2f));
|
||||
// public static final DeferredHolder<EntityType<?>, EntityType<LaserTowerEntity>> LASER_TOWER = register("laser_tower",
|
||||
// EntityType.Builder.<LaserTowerEntity>of(LaserTowerEntity::new, MobCategory.MISC).setTrackingRange(64).setUpdateInterval(3).setCustomClientFactory(LaserTowerEntity::new).fireImmune().sized(0.9f, 1.65f));
|
||||
|
||||
private static <T extends Entity> DeferredHolder<EntityType<?>, EntityType<T>> register(String name, EntityType.Builder<T> entityTypeBuilder) {
|
||||
return REGISTRY.register(name, () -> entityTypeBuilder.build(name));
|
||||
}
|
||||
|
||||
// @SubscribeEvent
|
||||
// public static void onRegisterSpawnPlacement(SpawnPlacementRegisterEvent event) {
|
||||
// event.register(ModEntities.SENPAI.get(), SpawnPlacements.Type.ON_GROUND, Heightmap.Types.MOTION_BLOCKING_NO_LEAVES,
|
||||
// (entityType, world, reason, pos, random) -> (world.getDifficulty() != Difficulty.PEACEFUL && SpawnConfig.SPAWN_SENPAI.get()
|
||||
// && Monster.isDarkEnoughToSpawn(world, pos, random) && Mob.checkMobSpawnRules(entityType, world, reason, pos, random)),
|
||||
// SpawnPlacementRegisterEvent.Operation.OR);
|
||||
// }
|
||||
|
||||
@SubscribeEvent
|
||||
public static void registerAttributes(EntityAttributeCreationEvent event) {
|
||||
// event.put(TARGET.get(), TargetEntity.createAttributes().build());
|
||||
// event.put(SENPAI.get(), SenpaiEntity.createAttributes().build());
|
||||
}
|
||||
}
|
|
@ -1,9 +1,7 @@
|
|||
package com.atsuishio.superbwarfare.init;
|
||||
|
||||
import com.atsuishio.superbwarfare.ModUtils;
|
||||
import com.atsuishio.superbwarfare.item.FiringParameters;
|
||||
import com.atsuishio.superbwarfare.item.PerkItem;
|
||||
import com.atsuishio.superbwarfare.item.ShortcutPack;
|
||||
import com.atsuishio.superbwarfare.item.*;
|
||||
import com.atsuishio.superbwarfare.item.common.BlueprintItem;
|
||||
import com.atsuishio.superbwarfare.item.common.CannonShellItem;
|
||||
import com.atsuishio.superbwarfare.item.common.MaterialPack;
|
||||
|
@ -93,7 +91,7 @@ public class ModItems {
|
|||
public static final DeferredHolder<Item, Item> SMALL_SHELL = AMMO.register("small_shell", () -> new Item(new Item.Properties()));
|
||||
public static final DeferredHolder<Item, Item> ROCKET_70 = AMMO.register("rocket_70", () -> new Item(new Item.Properties()));
|
||||
public static final DeferredHolder<Item, Item> WIRE_GUIDE_MISSILE = AMMO.register("wire_guide_missile", () -> new Item(new Item.Properties()));
|
||||
// public static final DeferredHolder<Item, Item> BEAM_TEST = AMMO.register("beam_test", BeamTest::new);
|
||||
public static final DeferredHolder<Item, Item> BEAM_TEST = AMMO.register("beam_test", BeamTest::new);
|
||||
|
||||
/**
|
||||
* items
|
||||
|
@ -117,7 +115,7 @@ public class ModItems {
|
|||
// public static final DeferredHolder<Item, Item> TARGET_DEPLOYER = ITEMS.register("target_deployer", TargetDeployer::new);
|
||||
// public static final DeferredHolder<Item, Item> KNIFE = ITEMS.register("knife", Knife::new);
|
||||
// public static final DeferredHolder<Item, Item> HAMMER = ITEMS.register("hammer", Hammer::new);
|
||||
// public static final DeferredHolder<Item, Item> CROWBAR = ITEMS.register("crowbar", Crowbar::new);
|
||||
public static final DeferredHolder<Item, Item> CROWBAR = ITEMS.register("crowbar", Crowbar::new);
|
||||
// public static final DeferredHolder<Item, Item> DEFUSER = ITEMS.register("defuser", Defuser::new);
|
||||
// public static final DeferredHolder<Item, Item> ARMOR_PLATE = ITEMS.register("armor_plate", ArmorPlate::new);
|
||||
//
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
package com.atsuishio.superbwarfare.init;
|
||||
|
||||
import com.atsuishio.superbwarfare.ModUtils;
|
||||
import com.atsuishio.superbwarfare.menu.ChargingStationMenu;
|
||||
import com.atsuishio.superbwarfare.menu.FuMO25Menu;
|
||||
import com.atsuishio.superbwarfare.menu.ReforgingTableMenu;
|
||||
import com.atsuishio.superbwarfare.menu.VehicleMenu;
|
||||
import net.minecraft.core.registries.BuiltInRegistries;
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu;
|
||||
import net.minecraft.world.inventory.MenuType;
|
||||
import net.neoforged.neoforge.common.extensions.IMenuTypeExtension;
|
||||
import net.neoforged.neoforge.registries.DeferredHolder;
|
||||
import net.neoforged.neoforge.registries.DeferredRegister;
|
||||
|
||||
public class ModMenuTypes {
|
||||
|
||||
public static final DeferredRegister<MenuType<?>> REGISTRY = DeferredRegister.create(BuiltInRegistries.MENU, ModUtils.MODID);
|
||||
|
||||
public static final DeferredHolder<MenuType<?>, MenuType<AbstractContainerMenu>> REFORGING_TABLE_MENU =
|
||||
REGISTRY.register("reforging_table_menu",
|
||||
() -> IMenuTypeExtension.create((windowId, inv, data) -> new ReforgingTableMenu(windowId, inv)));
|
||||
public static final DeferredHolder<MenuType<?>, MenuType<AbstractContainerMenu>> CHARGING_STATION_MENU =
|
||||
REGISTRY.register("charging_station_menu",
|
||||
() -> IMenuTypeExtension.create((windowId, inv, data) -> new ChargingStationMenu(windowId, inv)));
|
||||
public static final DeferredHolder<MenuType<?>, MenuType<AbstractContainerMenu>> VEHICLE_MENU =
|
||||
REGISTRY.register("vehicle_menu",
|
||||
() -> IMenuTypeExtension.create((windowId, inv, data) -> new VehicleMenu(windowId, inv)));
|
||||
public static final DeferredHolder<MenuType<?>, MenuType<AbstractContainerMenu>> FUMO_25_MENU =
|
||||
REGISTRY.register("fumo_25_menu",
|
||||
() -> IMenuTypeExtension.create((windowId, inv, data) -> new FuMO25Menu(windowId, inv)));
|
||||
}
|
153
src/main/java/com/atsuishio/superbwarfare/item/BeamTest.java
Normal file
153
src/main/java/com/atsuishio/superbwarfare/item/BeamTest.java
Normal file
|
@ -0,0 +1,153 @@
|
|||
package com.atsuishio.superbwarfare.item;
|
||||
|
||||
import com.atsuishio.superbwarfare.capability.LaserHandler;
|
||||
import com.atsuishio.superbwarfare.capability.ModCapabilities;
|
||||
import com.atsuishio.superbwarfare.entity.projectile.LaserEntity;
|
||||
import com.atsuishio.superbwarfare.init.ModSounds;
|
||||
import com.atsuishio.superbwarfare.tools.TraceTool;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.protocol.game.ClientboundStopSoundPacket;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.sounds.SoundEvent;
|
||||
import net.minecraft.sounds.SoundSource;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.InteractionResultHolder;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.TooltipFlag;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.phys.AABB;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class BeamTest extends Item {
|
||||
|
||||
public BeamTest() {
|
||||
super(new Properties());
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull InteractionResultHolder<ItemStack> use(@NotNull Level level, Player player, @NotNull InteractionHand hand) {
|
||||
|
||||
if (player.level().isClientSide) {
|
||||
player.playSound(ModSounds.CHARGE_RIFLE_FIRE_1P.get(), 1, 1);
|
||||
} else {
|
||||
player.playSound(ModSounds.CHARGE_RIFLE_FIRE_3P.get(), 2, 1);
|
||||
}
|
||||
|
||||
var capability = player.getCapability(ModCapabilities.LASER_CAPABILITY);
|
||||
if (capability != null) {
|
||||
player.startUsingItem(hand);
|
||||
if (!level.isClientSide) {
|
||||
double px = player.getX();
|
||||
double py = player.getY() + player.getBbHeight() * 0.6F;
|
||||
double pz = player.getZ();
|
||||
float yHeadRotAngle = (float) Math.toRadians(player.yHeadRot + 90);
|
||||
float xHeadRotAngle = (float) (float) -Math.toRadians(player.getXRot());
|
||||
LaserEntity laserEntity = new LaserEntity(player.level(), player, px, py, pz, yHeadRotAngle, xHeadRotAngle, 6000);
|
||||
capability.init(new LaserHandler(player, laserEntity));
|
||||
capability.start();
|
||||
}
|
||||
}
|
||||
|
||||
return InteractionResultHolder.consume(player.getItemInHand(hand));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ParametersAreNonnullByDefault
|
||||
public void releaseUsing(ItemStack stack, Level level, LivingEntity livingEntity, int timeCharged) {
|
||||
if (livingEntity instanceof Player player) {
|
||||
var cap = player.getCapability(ModCapabilities.LASER_CAPABILITY);
|
||||
if (cap != null) {
|
||||
cap.stop();
|
||||
}
|
||||
}
|
||||
if (livingEntity instanceof ServerPlayer serverPlayer && stack.getItem() instanceof BeamTest beamTest) {
|
||||
stopGunChargeSound(serverPlayer, beamTest);
|
||||
}
|
||||
|
||||
|
||||
super.releaseUsing(stack, level, livingEntity, timeCharged);
|
||||
}
|
||||
|
||||
private static void stopGunChargeSound(ServerPlayer player, BeamTest beamTest) {
|
||||
beamTest.getChargeSound().forEach(sound -> {
|
||||
var clientboundstopsoundpacket = new ClientboundStopSoundPacket(sound.getLocation(), SoundSource.PLAYERS);
|
||||
final Vec3 center = new Vec3(player.getX(), player.getY(), player.getZ());
|
||||
for (ServerPlayer player1 : player.level().getEntitiesOfClass(ServerPlayer.class, new AABB(center, center).inflate(48), e -> true).stream().sorted(Comparator.comparingDouble(e -> e.distanceToSqr(center))).toList()) {
|
||||
player1.connection.send(clientboundstopsoundpacket);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public Set<SoundEvent> getChargeSound() {
|
||||
return Set.of(ModSounds.CHARGE_RIFLE_FIRE_1P.get(), ModSounds.CHARGE_RIFLE_FIRE_3P.get());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack finishUsingItem(ItemStack pStack, Level pLevel, LivingEntity pLivingEntity) {
|
||||
if (pLivingEntity instanceof Player player) {
|
||||
var cap = player.getCapability(ModCapabilities.LASER_CAPABILITY);
|
||||
if (cap != null) {
|
||||
cap.stop();
|
||||
}
|
||||
player.getCooldowns().addCooldown(pStack.getItem(), 20);
|
||||
|
||||
if (player.level().isClientSide()) {
|
||||
beamShoot(player);
|
||||
player.playSound(ModSounds.CHARGE_RIFLE_FIRE_BOOM_1P.get(), 1, 1);
|
||||
}
|
||||
if (!player.level().isClientSide) {
|
||||
player.playSound(ModSounds.CHARGE_RIFLE_FIRE_BOOM_3P.get(), 4, 1);
|
||||
}
|
||||
if (player instanceof ServerPlayer serverPlayer) {
|
||||
// TODO network
|
||||
// ModUtils.PACKET_HANDLER.send(PacketDistributor.PLAYER.with(() -> serverPlayer), new ShakeClientMessage(10, 10, 30, serverPlayer.getX(), serverPlayer.getEyeY(), serverPlayer.getZ()));
|
||||
}
|
||||
}
|
||||
return super.finishUsingItem(pStack, pLevel, pLivingEntity);
|
||||
}
|
||||
|
||||
public static void beamShoot(Player player) {
|
||||
Entity lookingEntity = TraceTool.laserfindLookingEntity(player, 512);
|
||||
|
||||
if (lookingEntity == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
boolean canAttack = lookingEntity != player && !(lookingEntity instanceof Player player_ && (player_.isCreative() || player_.isSpectator()))
|
||||
&& (!player.isAlliedTo(lookingEntity) || lookingEntity.getTeam() == null || lookingEntity.getTeam().getName().equals("TDM"));
|
||||
|
||||
if (canAttack) {
|
||||
// ModUtils.PACKET_HANDLER.sendToServer(new LaserShootMessage(45, lookingEntity.getUUID(), TraceTool.laserHeadshot));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ParametersAreNonnullByDefault
|
||||
public int getUseDuration(ItemStack stack, LivingEntity entity) {
|
||||
return 11;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ParametersAreNonnullByDefault
|
||||
public boolean shouldCauseReequipAnimation(ItemStack oldStack, ItemStack newStack, boolean slotChanged) {
|
||||
return slotChanged;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ParametersAreNonnullByDefault
|
||||
public void appendHoverText(ItemStack stack, TooltipContext context, List<Component> tooltipComponents, TooltipFlag tooltipFlag) {
|
||||
// TODO developing
|
||||
// TooltipTool.addDevelopingText(pTooltipComponents);
|
||||
}
|
||||
|
||||
}
|
88
src/main/java/com/atsuishio/superbwarfare/item/Crowbar.java
Normal file
88
src/main/java/com/atsuishio/superbwarfare/item/Crowbar.java
Normal file
|
@ -0,0 +1,88 @@
|
|||
package com.atsuishio.superbwarfare.item;
|
||||
|
||||
import com.atsuishio.superbwarfare.init.ModBlocks;
|
||||
import com.atsuishio.superbwarfare.init.ModItems;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.tags.BlockTags;
|
||||
import net.minecraft.tags.TagKey;
|
||||
import net.minecraft.world.InteractionResult;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.Items;
|
||||
import net.minecraft.world.item.SwordItem;
|
||||
import net.minecraft.world.item.Tier;
|
||||
import net.minecraft.world.item.context.UseOnContext;
|
||||
import net.minecraft.world.item.crafting.Ingredient;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.neoforged.neoforge.items.ItemHandlerHelper;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class Crowbar extends SwordItem {
|
||||
public Crowbar() {
|
||||
super(new Tier() {
|
||||
public int getUses() {
|
||||
return 400;
|
||||
}
|
||||
|
||||
public float getSpeed() {
|
||||
return 4f;
|
||||
}
|
||||
|
||||
public float getAttackDamageBonus() {
|
||||
return 3.5f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull TagKey<Block> getIncorrectBlocksForDrops() {
|
||||
return BlockTags.INCORRECT_FOR_IRON_TOOL;
|
||||
}
|
||||
|
||||
public int getLevel() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
public int getEnchantmentValue() {
|
||||
return 9;
|
||||
}
|
||||
|
||||
public @NotNull Ingredient getRepairIngredient() {
|
||||
return Ingredient.of(new ItemStack(Items.IRON_INGOT));
|
||||
}
|
||||
}, new Properties());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasCraftingRemainingItem(@NotNull ItemStack stack) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ItemStack getCraftingRemainingItem(ItemStack itemstack) {
|
||||
ItemStack retval = new ItemStack(this);
|
||||
retval.setDamageValue(itemstack.getDamageValue() + 1);
|
||||
if (retval.getDamageValue() >= retval.getMaxDamage()) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRepairable(@NotNull ItemStack itemstack) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull InteractionResult useOn(@NotNull UseOnContext context) {
|
||||
super.useOn(context);
|
||||
if ((context.getLevel().getBlockState(BlockPos.containing(context.getClickedPos().getX(), context.getClickedPos().getY(), context.getClickedPos().getZ()))).getBlock() == ModBlocks.JUMP_PAD.get()) {
|
||||
context.getLevel().setBlock(BlockPos.containing(context.getClickedPos().getX(), context.getClickedPos().getY(), context.getClickedPos().getZ()), Blocks.AIR.defaultBlockState(), 3);
|
||||
|
||||
if (context.getPlayer() != null) {
|
||||
ItemHandlerHelper.giveItemToPlayer(context.getPlayer(), new ItemStack(ModItems.JUMP_PAD.get()));
|
||||
}
|
||||
}
|
||||
return InteractionResult.SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,138 @@
|
|||
package com.atsuishio.superbwarfare.menu;
|
||||
|
||||
import com.atsuishio.superbwarfare.block.entity.ChargingStationBlockEntity;
|
||||
import com.atsuishio.superbwarfare.init.ModMenuTypes;
|
||||
import com.atsuishio.superbwarfare.network.dataslot.ContainerEnergyData;
|
||||
import com.atsuishio.superbwarfare.network.dataslot.SimpleEnergyData;
|
||||
import net.minecraft.world.Container;
|
||||
import net.minecraft.world.SimpleContainer;
|
||||
import net.minecraft.world.entity.player.Inventory;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.inventory.Slot;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.crafting.RecipeType;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.neoforged.neoforge.capabilities.Capabilities;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class ChargingStationMenu extends EnergyMenu {
|
||||
|
||||
private final Container container;
|
||||
private final ContainerEnergyData containerData;
|
||||
protected final Level level;
|
||||
|
||||
public static final int X_OFFSET = 0;
|
||||
public static final int Y_OFFSET = 0;
|
||||
|
||||
public ChargingStationMenu(int id, Inventory inventory) {
|
||||
this(id, inventory, new SimpleContainer(2), new SimpleEnergyData(ChargingStationBlockEntity.MAX_DATA_COUNT));
|
||||
}
|
||||
|
||||
public ChargingStationMenu(int id, Inventory inventory, Container container, ContainerEnergyData containerData) {
|
||||
super(ModMenuTypes.CHARGING_STATION_MENU.get(), id, containerData);
|
||||
|
||||
checkContainerSize(container, 2);
|
||||
|
||||
this.container = container;
|
||||
this.containerData = containerData;
|
||||
this.level = inventory.player.level();
|
||||
|
||||
this.addSlot(new Slot(container, 0, 44, 54));
|
||||
this.addSlot(new ChargingSlot(container, 1, 116, 54));
|
||||
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
for (int j = 0; j < 9; ++j) {
|
||||
this.addSlot(new Slot(inventory, j + i * 9 + 9, 8 + j * 18 + X_OFFSET, 84 + i * 18 + Y_OFFSET));
|
||||
}
|
||||
}
|
||||
|
||||
for (int k = 0; k < 9; ++k) {
|
||||
this.addSlot(new Slot(inventory, k, 8 + k * 18 + X_OFFSET, 142 + Y_OFFSET));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ItemStack quickMoveStack(@NotNull Player pPlayer, int pIndex) {
|
||||
ItemStack itemstack = ItemStack.EMPTY;
|
||||
Slot slot = this.slots.get(pIndex);
|
||||
if (slot.hasItem()) {
|
||||
ItemStack itemstack1 = slot.getItem();
|
||||
itemstack = itemstack1.copy();
|
||||
if (pIndex == 1) {
|
||||
if (!this.moveItemStackTo(itemstack1, 2, 38, true)) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
} else if (pIndex != 0) {
|
||||
var itemCapability = itemstack1.getCapability(Capabilities.EnergyStorage.ITEM);
|
||||
if (itemCapability != null) {
|
||||
if (!this.moveItemStackTo(itemstack1, 1, 2, true)) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
} else if (itemstack1.getBurnTime(RecipeType.SMELTING) > 0 || itemstack1.getFoodProperties(null) != null) {
|
||||
if (!this.moveItemStackTo(itemstack1, 0, 1, false)) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
} else if (pIndex >= 2 && pIndex < 29) {
|
||||
if (!this.moveItemStackTo(itemstack1, 29, 38, false)) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
} else if (pIndex >= 29 && pIndex < 38 && !this.moveItemStackTo(itemstack1, 2, 29, false)) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
} else if (!this.moveItemStackTo(itemstack1, 2, 38, false)) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
if (itemstack1.isEmpty()) {
|
||||
slot.setByPlayer(ItemStack.EMPTY);
|
||||
} else {
|
||||
slot.setChanged();
|
||||
}
|
||||
|
||||
if (itemstack1.getCount() == itemstack.getCount()) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
slot.onTake(pPlayer, itemstack1);
|
||||
}
|
||||
|
||||
return itemstack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean stillValid(@NotNull Player pPlayer) {
|
||||
return this.container.stillValid(pPlayer);
|
||||
}
|
||||
|
||||
public long getFuelTick() {
|
||||
return this.containerData.get(0);
|
||||
}
|
||||
|
||||
public long getMaxFuelTick() {
|
||||
return this.containerData.get(1);
|
||||
}
|
||||
|
||||
public long getEnergy() {
|
||||
return this.containerData.get(2);
|
||||
}
|
||||
|
||||
public boolean showRange() {
|
||||
return this.containerData.get(3) == 1;
|
||||
}
|
||||
|
||||
public void setShowRange(boolean showRange) {
|
||||
this.containerData.set(3, showRange ? 1 : 0);
|
||||
}
|
||||
|
||||
static class ChargingSlot extends Slot {
|
||||
|
||||
public ChargingSlot(Container pContainer, int pSlot, int pX, int pY) {
|
||||
super(pContainer, pSlot, pX, pY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mayPlace(@NotNull ItemStack pStack) {
|
||||
return super.mayPlace(pStack);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
package com.atsuishio.superbwarfare.menu;
|
||||
|
||||
import com.atsuishio.superbwarfare.network.dataslot.ContainerEnergyData;
|
||||
import com.atsuishio.superbwarfare.network.dataslot.ContainerEnergyDataSlot;
|
||||
import com.google.common.collect.Lists;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu;
|
||||
import net.minecraft.world.inventory.MenuType;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
//@EventBusSubscriber(bus = EventBusSubscriber.Bus.GAME)
|
||||
public abstract class EnergyMenu extends AbstractContainerMenu {
|
||||
|
||||
private final List<ContainerEnergyDataSlot> containerEnergyDataSlots = Lists.newArrayList();
|
||||
private final List<ServerPlayer> usingPlayers = new ArrayList<>();
|
||||
|
||||
public EnergyMenu(@Nullable MenuType<?> pMenuType, int pContainerId) {
|
||||
super(pMenuType, pContainerId);
|
||||
}
|
||||
|
||||
public EnergyMenu(@Nullable MenuType<?> pMenuType, int id, ContainerEnergyData containerData) {
|
||||
super(pMenuType, id);
|
||||
|
||||
for (int i = 0; i < containerData.getCount(); ++i) {
|
||||
this.containerEnergyDataSlots.add(ContainerEnergyDataSlot.forContainer(containerData, i));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void broadcastChanges() {
|
||||
// TODO network
|
||||
// List<ContainerDataMessage.Pair> pairs = new ArrayList<>();
|
||||
// for (int i = 0; i < this.containerEnergyDataSlots.size(); ++i) {
|
||||
// ContainerEnergyDataSlot dataSlot = this.containerEnergyDataSlots.get(i);
|
||||
// if (dataSlot.checkAndClearUpdateFlag())
|
||||
// pairs.add(new ContainerDataMessage.Pair(i, dataSlot.get()));
|
||||
// }
|
||||
//
|
||||
// if (!pairs.isEmpty()) {
|
||||
// PacketDistributor.PacketTarget target = PacketDistributor.NMLIST.with(this.usingPlayers.stream().map(serverPlayer -> serverPlayer.connection.connection)::toList);
|
||||
// ModUtils.PACKET_HANDLER.send(target, new ContainerDataMessage(this.containerId, pairs));
|
||||
// }
|
||||
|
||||
super.broadcastChanges();
|
||||
}
|
||||
|
||||
public void setData(int id, int data) {
|
||||
this.containerEnergyDataSlots.get(id).set(data);
|
||||
}
|
||||
|
||||
public void setData(int id, long data) {
|
||||
this.containerEnergyDataSlots.get(id).set(data);
|
||||
}
|
||||
|
||||
// @SubscribeEvent
|
||||
// public static void onContainerOpened(PlayerContainerEvent.Open event) {
|
||||
// if (event.getContainer() instanceof EnergyMenu menu && event.getEntity() instanceof ServerPlayer serverPlayer) {
|
||||
// menu.usingPlayers.add(serverPlayer);
|
||||
//
|
||||
//// List<ContainerDataMessage.Pair> toSync = new ArrayList<>();
|
||||
//// for (int i = 0; i < menu.containerEnergyDataSlots.size(); ++i) {
|
||||
//// toSync.add(new ContainerDataMessage.Pair(i, menu.containerEnergyDataSlots.get(i).get()));
|
||||
//// }
|
||||
//// ModUtils.PACKET_HANDLER.send(PacketDistributor.PLAYER.with(() -> serverPlayer), new ContainerDataMessage(menu.containerId, toSync));
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// @SubscribeEvent
|
||||
// public static void onContainerClosed(PlayerContainerEvent.Close event) {
|
||||
// if (event.getContainer() instanceof EnergyMenu menu && event.getEntity() instanceof ServerPlayer serverPlayer) {
|
||||
// menu.usingPlayers.remove(serverPlayer);
|
||||
// }
|
||||
// }
|
||||
}
|
222
src/main/java/com/atsuishio/superbwarfare/menu/FuMO25Menu.java
Normal file
222
src/main/java/com/atsuishio/superbwarfare/menu/FuMO25Menu.java
Normal file
|
@ -0,0 +1,222 @@
|
|||
package com.atsuishio.superbwarfare.menu;
|
||||
|
||||
import com.atsuishio.superbwarfare.block.entity.FuMO25BlockEntity;
|
||||
import com.atsuishio.superbwarfare.component.ModDataComponents;
|
||||
import com.atsuishio.superbwarfare.init.ModBlocks;
|
||||
import com.atsuishio.superbwarfare.init.ModItems;
|
||||
import com.atsuishio.superbwarfare.init.ModMenuTypes;
|
||||
import com.atsuishio.superbwarfare.network.dataslot.ContainerEnergyData;
|
||||
import com.atsuishio.superbwarfare.network.dataslot.SimpleEnergyData;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.Container;
|
||||
import net.minecraft.world.SimpleContainer;
|
||||
import net.minecraft.world.entity.player.Inventory;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.inventory.ContainerLevelAccess;
|
||||
import net.minecraft.world.inventory.Slot;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.neoforged.bus.api.SubscribeEvent;
|
||||
import net.neoforged.fml.common.EventBusSubscriber;
|
||||
import net.neoforged.neoforge.event.entity.player.PlayerContainerEvent;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Optional;
|
||||
|
||||
@EventBusSubscriber(bus = EventBusSubscriber.Bus.GAME)
|
||||
public class FuMO25Menu extends EnergyMenu {
|
||||
|
||||
protected final Container container;
|
||||
protected final ContainerLevelAccess access;
|
||||
protected final ContainerEnergyData containerData;
|
||||
|
||||
private int posX = Integer.MIN_VALUE;
|
||||
private int posY = Integer.MIN_VALUE;
|
||||
private int posZ = Integer.MIN_VALUE;
|
||||
|
||||
public static final int X_OFFSET = 164;
|
||||
public static final int Y_OFFSET = 0;
|
||||
|
||||
public FuMO25Menu(int pContainerId, Inventory pPlayerInventory) {
|
||||
this(pContainerId, pPlayerInventory, new SimpleContainer(1), ContainerLevelAccess.NULL, new SimpleEnergyData(FuMO25BlockEntity.MAX_DATA_COUNT));
|
||||
}
|
||||
|
||||
public FuMO25Menu(int pContainerId, Inventory pPlayerInventory, ContainerLevelAccess access, ContainerEnergyData containerData) {
|
||||
this(pContainerId, pPlayerInventory, new SimpleContainer(1), access, containerData);
|
||||
}
|
||||
|
||||
public FuMO25Menu(int pContainerId, Inventory inventory, Container container, ContainerLevelAccess access, ContainerEnergyData containerData) {
|
||||
super(ModMenuTypes.FUMO_25_MENU.get(), pContainerId, containerData);
|
||||
|
||||
checkContainerSize(container, 1);
|
||||
|
||||
this.container = container;
|
||||
this.access = access;
|
||||
this.containerData = containerData;
|
||||
|
||||
this.addSlot(new ParaSlot(container, 0, 278, 60));
|
||||
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
for (int j = 0; j < 9; ++j) {
|
||||
this.addSlot(new Slot(inventory, j + i * 9 + 9, 8 + j * 18 + X_OFFSET, 84 + i * 18 + Y_OFFSET));
|
||||
}
|
||||
}
|
||||
|
||||
for (int k = 0; k < 9; ++k) {
|
||||
this.addSlot(new Slot(inventory, k, 8 + k * 18 + X_OFFSET, 142 + Y_OFFSET));
|
||||
}
|
||||
}
|
||||
|
||||
public void setPos(int x, int y, int z) {
|
||||
this.posX = x;
|
||||
this.posY = y;
|
||||
this.posZ = z;
|
||||
}
|
||||
|
||||
public void resetPos() {
|
||||
this.posX = Integer.MIN_VALUE;
|
||||
this.posY = Integer.MIN_VALUE;
|
||||
this.posZ = Integer.MIN_VALUE;
|
||||
}
|
||||
|
||||
public void setPosToParameters() {
|
||||
if (this.posX != Integer.MIN_VALUE && this.posY != Integer.MIN_VALUE) {
|
||||
ItemStack stack = this.container.getItem(0);
|
||||
if (stack.isEmpty()) return;
|
||||
|
||||
stack.set(ModDataComponents.BLOCK_POS, new BlockPos(this.posX, this.posY, this.posZ));
|
||||
|
||||
this.resetPos();
|
||||
this.container.setChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public void setTargetToLaserTower() {
|
||||
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public BlockPos getCurrentPos() {
|
||||
if (this.posX != Integer.MIN_VALUE && this.posY != Integer.MIN_VALUE && this.posZ != Integer.MIN_VALUE) {
|
||||
return new BlockPos(this.posX, this.posY, this.posZ);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Optional<BlockPos> getSelfPos() {
|
||||
return this.access.evaluate((level, pos) -> pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ItemStack quickMoveStack(@NotNull Player pPlayer, int pIndex) {
|
||||
ItemStack itemstack = ItemStack.EMPTY;
|
||||
Slot slot = this.slots.get(pIndex);
|
||||
if (slot.hasItem()) {
|
||||
ItemStack stack = slot.getItem();
|
||||
itemstack = stack.copy();
|
||||
if (pIndex != 0) {
|
||||
if (!this.moveItemStackTo(stack, 0, 1, false)) {
|
||||
return ItemStack.EMPTY;
|
||||
} else if (pIndex >= 1 && pIndex < 28) {
|
||||
if (!this.moveItemStackTo(stack, 28, 37, false)) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
} else if (pIndex >= 28 && pIndex < 37 && !this.moveItemStackTo(stack, 1, 28, false)) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
} else if (!this.moveItemStackTo(stack, 1, 37, false)) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
if (stack.isEmpty()) {
|
||||
slot.setByPlayer(ItemStack.EMPTY);
|
||||
} else {
|
||||
slot.setChanged();
|
||||
}
|
||||
|
||||
if (stack.getCount() == itemstack.getCount()) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
slot.onTake(pPlayer, stack);
|
||||
}
|
||||
|
||||
return itemstack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean stillValid(@NotNull Player pPlayer) {
|
||||
return this.access.evaluate((level, pos) -> level.getBlockState(pos).is(ModBlocks.FUMO_25.get())
|
||||
&& pPlayer.distanceToSqr((double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D) <= 64.0D, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removed(@NotNull Player pPlayer) {
|
||||
this.access.execute((level, pos) -> {
|
||||
ItemStack para = this.container.getItem(0);
|
||||
if (!para.isEmpty()) {
|
||||
pPlayer.getInventory().placeItemBackInInventory(para);
|
||||
}
|
||||
this.container.removeItemNoUpdate(0);
|
||||
resetPos();
|
||||
});
|
||||
}
|
||||
|
||||
public long getEnergy() {
|
||||
return this.containerData.get(0);
|
||||
}
|
||||
|
||||
public long getFuncType() {
|
||||
return this.containerData.get(1);
|
||||
}
|
||||
|
||||
public void setFuncTypeAndTime(byte type) {
|
||||
this.containerData.set(1, type);
|
||||
int tick = switch (type) {
|
||||
case 1, 2 -> 1200;
|
||||
case 3 -> 600;
|
||||
default -> 0;
|
||||
};
|
||||
this.containerData.set(2, tick);
|
||||
}
|
||||
|
||||
public long getTime() {
|
||||
return this.containerData.get(2);
|
||||
}
|
||||
|
||||
public boolean isPowered() {
|
||||
return this.containerData.get(3) == 1;
|
||||
}
|
||||
|
||||
static class ParaSlot extends Slot {
|
||||
|
||||
public ParaSlot(Container pContainer, int pSlot, int pX, int pY) {
|
||||
super(pContainer, pSlot, pX, pY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mayPlace(ItemStack pStack) {
|
||||
return pStack.is(ModItems.FIRING_PARAMETERS.get());
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onContainerOpened(PlayerContainerEvent.Open event) {
|
||||
if (event.getContainer() instanceof FuMO25Menu fuMO25Menu && event.getEntity() instanceof ServerPlayer serverPlayer) {
|
||||
fuMO25Menu.getSelfPos().ifPresent(pos -> {
|
||||
}
|
||||
// TODO send packet
|
||||
// ModUtils.PACKET_HANDLER.send(PacketDistributor.PLAYER.with(() -> serverPlayer), new RadarMenuOpenMessage(pos))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onContainerClosed(PlayerContainerEvent.Close event) {
|
||||
if (event.getContainer() instanceof FuMO25Menu && event.getEntity() instanceof ServerPlayer serverPlayer) {
|
||||
// TODO send packet
|
||||
// ModUtils.PACKET_HANDLER.send(PacketDistributor.PLAYER.with(() -> serverPlayer), new RadarMenuCloseMessage(0));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,509 @@
|
|||
package com.atsuishio.superbwarfare.menu;
|
||||
|
||||
import com.atsuishio.superbwarfare.init.ModBlocks;
|
||||
import com.atsuishio.superbwarfare.init.ModMenuTypes;
|
||||
import com.atsuishio.superbwarfare.init.ModTags;
|
||||
import com.atsuishio.superbwarfare.item.PerkItem;
|
||||
import com.atsuishio.superbwarfare.perk.Perk;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.Container;
|
||||
import net.minecraft.world.SimpleContainer;
|
||||
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.ContainerLevelAccess;
|
||||
import net.minecraft.world.inventory.DataSlot;
|
||||
import net.minecraft.world.inventory.Slot;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class ReforgingTableMenu extends AbstractContainerMenu {
|
||||
|
||||
protected final Container container;
|
||||
protected final ContainerLevelAccess access;
|
||||
|
||||
public static final int INPUT_SLOT = 0;
|
||||
public static final int AMMO_PERK_SLOT = 1;
|
||||
public static final int FUNC_PERK_SLOT = 2;
|
||||
public static final int DAMAGE_PERK_SLOT = 3;
|
||||
public static final int RESULT_SLOT = 4;
|
||||
|
||||
public static final int MAX_PERK_LEVEL = 20;
|
||||
public static final int MAX_UPGRADE_POINT = 100;
|
||||
|
||||
public final DataSlot ammoPerkLevel = DataSlot.standalone();
|
||||
public final DataSlot funcPerkLevel = DataSlot.standalone();
|
||||
public final DataSlot damagePerkLevel = DataSlot.standalone();
|
||||
public final DataSlot upgradePoint = DataSlot.standalone();
|
||||
|
||||
public static final int X_OFFSET = 0;
|
||||
public static final int Y_OFFSET = 11;
|
||||
|
||||
public ReforgingTableMenu(int pContainerId, Inventory pPlayerInventory) {
|
||||
this(pContainerId, pPlayerInventory, new SimpleContainer(5), ContainerLevelAccess.NULL);
|
||||
}
|
||||
|
||||
public ReforgingTableMenu(int pContainerId, Inventory pPlayerInventory, ContainerLevelAccess access) {
|
||||
this(pContainerId, pPlayerInventory, new SimpleContainer(5), access);
|
||||
}
|
||||
|
||||
public ReforgingTableMenu(int pContainerId, Inventory inventory, Container container, ContainerLevelAccess pContainerLevelAccess) {
|
||||
super(ModMenuTypes.REFORGING_TABLE_MENU.get(), pContainerId);
|
||||
|
||||
checkContainerSize(container, 5);
|
||||
|
||||
this.container = container;
|
||||
this.access = pContainerLevelAccess;
|
||||
|
||||
this.ammoPerkLevel.set(0);
|
||||
this.funcPerkLevel.set(0);
|
||||
this.damagePerkLevel.set(0);
|
||||
this.upgradePoint.set(0);
|
||||
|
||||
this.addDataSlot(ammoPerkLevel);
|
||||
this.addDataSlot(funcPerkLevel);
|
||||
this.addDataSlot(damagePerkLevel);
|
||||
this.addDataSlot(upgradePoint);
|
||||
|
||||
this.addSlot(new InputSlot(container, INPUT_SLOT, 20, 22));
|
||||
this.addSlot(new PerkSlot(container, AMMO_PERK_SLOT, Perk.Type.AMMO, 80, 25));
|
||||
this.addSlot(new PerkSlot(container, FUNC_PERK_SLOT, Perk.Type.FUNCTIONAL, 80, 45));
|
||||
this.addSlot(new PerkSlot(container, DAMAGE_PERK_SLOT, Perk.Type.DAMAGE, 80, 65));
|
||||
this.addSlot(new ResultSlot(container, RESULT_SLOT, 142, 45));
|
||||
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
for (int j = 0; j < 9; ++j) {
|
||||
this.addSlot(new Slot(inventory, j + i * 9 + 9, 8 + j * 18 + X_OFFSET, 84 + i * 18 + Y_OFFSET));
|
||||
}
|
||||
}
|
||||
|
||||
for (int k = 0; k < 9; ++k) {
|
||||
this.addSlot(new Slot(inventory, k, 8 + k * 18 + X_OFFSET, 142 + Y_OFFSET));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ItemStack quickMoveStack(@NotNull Player pPlayer, int pIndex) {
|
||||
ItemStack itemstack = ItemStack.EMPTY;
|
||||
Slot slot = this.slots.get(pIndex);
|
||||
if (slot.hasItem()) {
|
||||
ItemStack stack = slot.getItem();
|
||||
itemstack = stack.copy();
|
||||
|
||||
if (pIndex == INPUT_SLOT) {
|
||||
onTakeGun(stack);
|
||||
if (!this.moveItemStackTo(stack, RESULT_SLOT + 1, RESULT_SLOT + 37, false)) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
} else if (pIndex >= AMMO_PERK_SLOT && pIndex <= DAMAGE_PERK_SLOT) {
|
||||
onTakePerk(stack);
|
||||
if (!this.moveItemStackTo(stack, RESULT_SLOT + 1, RESULT_SLOT + 37, false)) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
} else if (pIndex == RESULT_SLOT) {
|
||||
if (!this.moveItemStackTo(stack, RESULT_SLOT, RESULT_SLOT + 36, false)) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
} else {
|
||||
if (stack.is(ModTags.Items.GUN)) {
|
||||
if (!this.moveItemStackTo(stack, INPUT_SLOT, INPUT_SLOT + 1, false)) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
} else if (stack.getItem() instanceof PerkItem perkItem) {
|
||||
Perk.Type type = perkItem.getPerk().type;
|
||||
if (type == Perk.Type.AMMO) {
|
||||
if (!this.moveItemStackTo(stack, AMMO_PERK_SLOT, AMMO_PERK_SLOT + 1, false)) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
} else if (type == Perk.Type.FUNCTIONAL) {
|
||||
if (!this.moveItemStackTo(stack, FUNC_PERK_SLOT, FUNC_PERK_SLOT + 1, false)) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
} else if (type == Perk.Type.DAMAGE) {
|
||||
if (!this.moveItemStackTo(stack, DAMAGE_PERK_SLOT, DAMAGE_PERK_SLOT + 1, false)) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (stack.isEmpty()) {
|
||||
slot.setByPlayer(ItemStack.EMPTY);
|
||||
} else {
|
||||
slot.setChanged();
|
||||
}
|
||||
|
||||
if (stack.getCount() == itemstack.getCount()) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
slot.onTake(pPlayer, stack);
|
||||
}
|
||||
|
||||
return itemstack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean stillValid(@NotNull Player pPlayer) {
|
||||
return this.access.evaluate((level, pos) -> level.getBlockState(pos).is(ModBlocks.REFORGING_TABLE.get())
|
||||
&& pPlayer.distanceToSqr((double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D) <= 64.0D, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removed(@NotNull Player pPlayer) {
|
||||
this.access.execute((level, pos) -> {
|
||||
ItemStack gun = this.container.getItem(INPUT_SLOT);
|
||||
ItemStack copy = gun.copy();
|
||||
|
||||
for (int i = 0; i < this.container.getContainerSize(); ++i) {
|
||||
ItemStack itemstack = this.container.getItem(i);
|
||||
|
||||
if (itemstack.getItem() instanceof PerkItem<?> perkItem) {
|
||||
// TODO PerkHelper
|
||||
// if (!copy.isEmpty() && PerkHelper.getItemPerkLevel(perkItem.getPerk(), copy) > 0) {
|
||||
// continue;
|
||||
// }
|
||||
}
|
||||
|
||||
if (!itemstack.isEmpty()) {
|
||||
pPlayer.getInventory().placeItemBackInInventory(itemstack);
|
||||
}
|
||||
|
||||
this.container.removeItemNoUpdate(i);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void setPerkLevel(Perk.Type type, boolean upgrade, boolean isCreative) {
|
||||
if (upgrade && this.upgradePoint.get() <= 0 && !isCreative) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!upgrade && this.upgradePoint.get() >= MAX_UPGRADE_POINT && !isCreative) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case AMMO ->
|
||||
this.ammoPerkLevel.set(upgrade ? Math.min(MAX_PERK_LEVEL, this.ammoPerkLevel.get() + 1) : Math.max(1, this.ammoPerkLevel.get() - 1));
|
||||
case FUNCTIONAL ->
|
||||
this.funcPerkLevel.set(upgrade ? Math.min(MAX_PERK_LEVEL, this.funcPerkLevel.get() + 1) : Math.max(1, this.funcPerkLevel.get() - 1));
|
||||
case DAMAGE ->
|
||||
this.damagePerkLevel.set(upgrade ? Math.min(MAX_PERK_LEVEL, this.damagePerkLevel.get() + 1) : Math.max(1, this.damagePerkLevel.get() - 1));
|
||||
}
|
||||
|
||||
if (!isCreative) {
|
||||
this.upgradePoint.set(Mth.clamp(this.upgradePoint.get() + (upgrade ? -1 : 1), 0, MAX_UPGRADE_POINT));
|
||||
}
|
||||
}
|
||||
|
||||
public void handleUpgradePoint(ItemStack stack) {
|
||||
// TODO GunItem GunsTool
|
||||
// if (!(stack.getItem() instanceof GunItem)) {
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// double oldPoint = GunsTool.getGunDoubleTag(stack, "UpgradePoint", 0);
|
||||
// int point = (int) oldPoint;
|
||||
// int newPoint = this.upgradePoint.get();
|
||||
// int delta = newPoint - point;
|
||||
//
|
||||
// if (delta != 0) {
|
||||
// GunsTool.setGunDoubleTag(stack, "UpgradePoint", oldPoint + delta);
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据输入槽的枪械和Perk槽中的物品与等级,生成重铸后的武器,并放入输出槽中
|
||||
*/
|
||||
public void generateResult() {
|
||||
// ItemStack gun = this.container.getItem(INPUT_SLOT);
|
||||
// if (!(gun.getItem() instanceof GunItem gunItem)) {
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// ItemStack ammo = this.container.getItem(AMMO_PERK_SLOT);
|
||||
// ItemStack func = this.container.getItem(FUNC_PERK_SLOT);
|
||||
// ItemStack damage = this.container.getItem(DAMAGE_PERK_SLOT);
|
||||
// if (ammo.isEmpty() && func.isEmpty() && damage.isEmpty()) {
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// ItemStack result = gun.copy();
|
||||
//
|
||||
// if (!ammo.isEmpty() && ammo.getItem() instanceof PerkItem perkItem) {
|
||||
// if (gunItem.canApplyPerk(perkItem.getPerk())) {
|
||||
// PerkHelper.setPerk(result, perkItem.getPerk(), this.ammoPerkLevel.get());
|
||||
// this.container.setItem(AMMO_PERK_SLOT, ItemStack.EMPTY);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if (!func.isEmpty() && func.getItem() instanceof PerkItem perkItem) {
|
||||
// if (gunItem.canApplyPerk(perkItem.getPerk())) {
|
||||
// PerkHelper.setPerk(result, perkItem.getPerk(), this.funcPerkLevel.get());
|
||||
// this.container.setItem(FUNC_PERK_SLOT, ItemStack.EMPTY);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if (!damage.isEmpty() && damage.getItem() instanceof PerkItem perkItem) {
|
||||
// if (gunItem.canApplyPerk(perkItem.getPerk())) {
|
||||
// PerkHelper.setPerk(result, perkItem.getPerk(), this.damagePerkLevel.get());
|
||||
// this.container.setItem(DAMAGE_PERK_SLOT, ItemStack.EMPTY);
|
||||
// }
|
||||
// }
|
||||
|
||||
// handleUpgradePoint(result);
|
||||
//
|
||||
// this.ammoPerkLevel.set(0);
|
||||
// this.funcPerkLevel.set(0);
|
||||
// this.damagePerkLevel.set(0);
|
||||
// this.upgradePoint.set(0);
|
||||
//
|
||||
// this.container.setItem(INPUT_SLOT, ItemStack.EMPTY);
|
||||
// this.container.setItem(RESULT_SLOT, result);
|
||||
// this.container.setChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* 从Perk槽中取出对应的Perk物品时,根据其类型移除输入槽中枪械的Perk
|
||||
*
|
||||
* @param perk Perk物品
|
||||
*/
|
||||
private void onTakePerk(ItemStack perk) {
|
||||
// ItemStack gun = this.container.getItem(INPUT_SLOT);
|
||||
// if (!(gun.getItem() instanceof GunItem)) {
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// if (perk.getItem() instanceof PerkItem perkItem) {
|
||||
// switch (perkItem.getPerk().type) {
|
||||
// case AMMO -> this.ammoPerkLevel.set(0);
|
||||
// case FUNCTIONAL -> this.funcPerkLevel.set(0);
|
||||
// case DAMAGE -> this.damagePerkLevel.set(0);
|
||||
// }
|
||||
//
|
||||
// int level = PerkHelper.getItemPerkLevel(perkItem.getPerk(), gun);
|
||||
//
|
||||
// if (level <= 0) {
|
||||
// this.upgradePoint.set((int) GunsTool.getGunDoubleTag(gun, "UpgradePoint", 0));
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// ItemStack output = gun.copy();
|
||||
// PerkHelper.removePerkByType(output, perkItem.getPerk().type);
|
||||
// GunsTool.setGunDoubleTag(output, "UpgradePoint", Math.min(MAX_UPGRADE_POINT, level - 1 + GunsTool.getGunDoubleTag(output, "UpgradePoint", 0)));
|
||||
// this.upgradePoint.set((int) GunsTool.getGunDoubleTag(output, "UpgradePoint", 0));
|
||||
//
|
||||
// this.container.setItem(INPUT_SLOT, output);
|
||||
// this.container.setChanged();
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
* 放置perk物品时,将对应位置的level设置为1
|
||||
*
|
||||
* @param pStack Perk物品
|
||||
*/
|
||||
private void onPlacePerk(ItemStack pStack) {
|
||||
if (!(pStack.getItem() instanceof PerkItem<?> perkItem)) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (perkItem.getPerk().type) {
|
||||
case AMMO -> this.ammoPerkLevel.set(1);
|
||||
case FUNCTIONAL -> this.funcPerkLevel.set(1);
|
||||
case DAMAGE -> this.damagePerkLevel.set(1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将枪械放入输入槽中时,根据枪械上已有的Perk生成对应的Perk物品,并将等级调整为当前的等级
|
||||
*
|
||||
* @param stack 输入的枪械
|
||||
*/
|
||||
private void onPlaceGun(ItemStack stack) {
|
||||
// if (!(stack.getItem() instanceof GunItem)) {
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// int point = (int) GunsTool.getGunDoubleTag(stack, "UpgradePoint", 0);
|
||||
// this.upgradePoint.set(Mth.clamp(point, 0, MAX_UPGRADE_POINT));
|
||||
//
|
||||
// var ammoPerk = PerkHelper.getPerkByType(stack, Perk.Type.AMMO);
|
||||
// if (ammoPerk != null) {
|
||||
// this.ammoPerkLevel.set(PerkHelper.getItemPerkLevel(ammoPerk, stack));
|
||||
// var ammoPerkItem = PerkHelper.getPerkItem(ammoPerk);
|
||||
// ammoPerkItem.ifPresent(registryObject -> this.container.setItem(AMMO_PERK_SLOT, registryObject.get().getDefaultInstance()));
|
||||
// }
|
||||
//
|
||||
// var funcPerk = PerkHelper.getPerkByType(stack, Perk.Type.FUNCTIONAL);
|
||||
// if (funcPerk != null) {
|
||||
// this.funcPerkLevel.set(PerkHelper.getItemPerkLevel(funcPerk, stack));
|
||||
// var funcPerkItem = PerkHelper.getPerkItem(funcPerk);
|
||||
// funcPerkItem.ifPresent(registryObject -> this.container.setItem(FUNC_PERK_SLOT, registryObject.get().getDefaultInstance()));
|
||||
// }
|
||||
//
|
||||
// var damagePerk = PerkHelper.getPerkByType(stack, Perk.Type.DAMAGE);
|
||||
// if (damagePerk != null) {
|
||||
// this.damagePerkLevel.set(PerkHelper.getItemPerkLevel(damagePerk, stack));
|
||||
// var damagePerkItem = PerkHelper.getPerkItem(damagePerk);
|
||||
// damagePerkItem.ifPresent(registryObject -> this.container.setItem(DAMAGE_PERK_SLOT, registryObject.get().getDefaultInstance()));
|
||||
// }
|
||||
|
||||
this.container.setChanged();
|
||||
this.broadcastChanges();
|
||||
}
|
||||
|
||||
/**
|
||||
* 拿走输入槽中的枪械时,如果Perk槽中存在放入枪械时生成的Perk物品,则将其移除,如果是没有的Perk则无视
|
||||
*
|
||||
* @param pStack 输入的枪械
|
||||
*/
|
||||
private void onTakeGun(ItemStack pStack) {
|
||||
// if (!(pStack.getItem() instanceof GunItem)) {
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// var ammoPerk = PerkHelper.getPerkByType(pStack, Perk.Type.AMMO);
|
||||
// if (ammoPerk != null) {
|
||||
// if (this.container.getItem(AMMO_PERK_SLOT).getItem() instanceof PerkItem perkItem && perkItem.getPerk() == ammoPerk) {
|
||||
// this.container.setItem(AMMO_PERK_SLOT, ItemStack.EMPTY);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// var funcPerk = PerkHelper.getPerkByType(pStack, Perk.Type.FUNCTIONAL);
|
||||
// if (funcPerk != null) {
|
||||
// if (this.container.getItem(FUNC_PERK_SLOT).getItem() instanceof PerkItem perkItem && perkItem.getPerk() == funcPerk) {
|
||||
// this.container.setItem(FUNC_PERK_SLOT, ItemStack.EMPTY);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// var damagePerk = PerkHelper.getPerkByType(pStack, Perk.Type.DAMAGE);
|
||||
// if (damagePerk != null) {
|
||||
// if (this.container.getItem(DAMAGE_PERK_SLOT).getItem() instanceof PerkItem perkItem && perkItem.getPerk() == damagePerk) {
|
||||
// this.container.setItem(DAMAGE_PERK_SLOT, ItemStack.EMPTY);
|
||||
// }
|
||||
// }
|
||||
|
||||
this.upgradePoint.set(0);
|
||||
this.ammoPerkLevel.set(0);
|
||||
this.funcPerkLevel.set(0);
|
||||
this.damagePerkLevel.set(0);
|
||||
|
||||
var ammo = this.container.getItem(AMMO_PERK_SLOT);
|
||||
if (ammo != ItemStack.EMPTY) {
|
||||
this.moveItemStackTo(ammo, RESULT_SLOT + 1, RESULT_SLOT + 37, false);
|
||||
}
|
||||
|
||||
var func = this.container.getItem(FUNC_PERK_SLOT);
|
||||
if (func != ItemStack.EMPTY) {
|
||||
this.moveItemStackTo(func, RESULT_SLOT + 1, RESULT_SLOT + 37, false);
|
||||
}
|
||||
|
||||
var damage = this.container.getItem(DAMAGE_PERK_SLOT);
|
||||
if (damage != ItemStack.EMPTY) {
|
||||
this.moveItemStackTo(damage, RESULT_SLOT + 1, RESULT_SLOT + 37, false);
|
||||
}
|
||||
|
||||
this.container.setChanged();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public ItemStack getPerkItemBySlot(Perk.Type type) {
|
||||
return switch (type) {
|
||||
case AMMO -> this.container.getItem(AMMO_PERK_SLOT);
|
||||
case FUNCTIONAL -> this.container.getItem(FUNC_PERK_SLOT);
|
||||
case DAMAGE -> this.container.getItem(DAMAGE_PERK_SLOT);
|
||||
};
|
||||
}
|
||||
|
||||
class InputSlot extends Slot {
|
||||
public InputSlot(Container pContainer, int pSlot, int pX, int pY) {
|
||||
super(pContainer, pSlot, pX, pY);
|
||||
}
|
||||
|
||||
public boolean mayPlace(@NotNull ItemStack pStack) {
|
||||
// if (pStack.getItem() instanceof GunItem) {
|
||||
// ItemStack ammoPerk = this.container.getItem(AMMO_PERK_SLOT);
|
||||
// ItemStack funcPerk = this.container.getItem(FUNC_PERK_SLOT);
|
||||
// ItemStack damagePerk = this.container.getItem(DAMAGE_PERK_SLOT);
|
||||
//
|
||||
// boolean flag1 = ammoPerk.isEmpty();
|
||||
// boolean flag2 = funcPerk.isEmpty();
|
||||
// boolean flag3 = damagePerk.isEmpty();
|
||||
//
|
||||
// return flag1 && flag2 && flag3 && this.container.getItem(RESULT_SLOT).isEmpty() && this.container.getItem(INPUT_SLOT).isEmpty();
|
||||
// }
|
||||
return false;
|
||||
}
|
||||
|
||||
public int getMaxStackSize() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTake(@NotNull Player pPlayer, @NotNull ItemStack pStack) {
|
||||
super.onTake(pPlayer, pStack);
|
||||
onTakeGun(pStack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setByPlayer(@NotNull ItemStack pStack) {
|
||||
onPlaceGun(pStack);
|
||||
super.setByPlayer(pStack);
|
||||
}
|
||||
}
|
||||
|
||||
class PerkSlot extends Slot {
|
||||
public Perk.Type type;
|
||||
|
||||
public PerkSlot(Container pContainer, int pSlot, Perk.Type type, int pX, int pY) {
|
||||
super(pContainer, pSlot, pX, pY);
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public boolean mayPlace(@NotNull ItemStack pStack) {
|
||||
var slot = switch (type) {
|
||||
case AMMO -> AMMO_PERK_SLOT;
|
||||
case FUNCTIONAL -> FUNC_PERK_SLOT;
|
||||
case DAMAGE -> DAMAGE_PERK_SLOT;
|
||||
};
|
||||
|
||||
return pStack.getItem() instanceof PerkItem<?> perkItem && perkItem.getPerk().type == type;
|
||||
// && !container.getItem(INPUT_SLOT).isEmpty() && container.getItem(INPUT_SLOT).getItem() instanceof GunItem gunItem
|
||||
// && gunItem.canApplyPerk(perkItem.getPerk()) && container.getItem(slot).isEmpty();
|
||||
}
|
||||
|
||||
public int getMaxStackSize() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTake(@NotNull Player pPlayer, @NotNull ItemStack pStack) {
|
||||
onTakePerk(pStack);
|
||||
super.onTake(pPlayer, pStack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setByPlayer(@NotNull ItemStack pStack) {
|
||||
onPlacePerk(pStack);
|
||||
super.setByPlayer(pStack);
|
||||
}
|
||||
}
|
||||
|
||||
static class ResultSlot extends Slot {
|
||||
public ResultSlot(Container pContainer, int pSlot, int pX, int pY) {
|
||||
super(pContainer, pSlot, pX, pY);
|
||||
}
|
||||
|
||||
public boolean mayPlace(@NotNull ItemStack pStack) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public int getMaxStackSize() {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
package com.atsuishio.superbwarfare.menu;
|
||||
|
||||
import com.atsuishio.superbwarfare.init.ModMenuTypes;
|
||||
import net.minecraft.world.Container;
|
||||
import net.minecraft.world.SimpleContainer;
|
||||
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.Slot;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class VehicleMenu extends AbstractContainerMenu {
|
||||
|
||||
private final Container container;
|
||||
private final int containerRows;
|
||||
|
||||
public static final int DEFAULT_SIZE = 102;
|
||||
|
||||
public static final int X_OFFSET = 97;
|
||||
public static final int Y_OFFSET = 20;
|
||||
|
||||
public VehicleMenu(int pContainerId, Inventory pPlayerInventory) {
|
||||
this(pContainerId, pPlayerInventory, new SimpleContainer(DEFAULT_SIZE));
|
||||
}
|
||||
|
||||
public VehicleMenu(int pContainerId, Inventory pPlayerInventory, Container pContainer) {
|
||||
super(ModMenuTypes.VEHICLE_MENU.get(), pContainerId);
|
||||
|
||||
checkContainerSize(pContainer, DEFAULT_SIZE);
|
||||
this.container = pContainer;
|
||||
this.containerRows = 6;
|
||||
pContainer.startOpen(pPlayerInventory.player);
|
||||
int i = (this.containerRows - 4) * 18;
|
||||
|
||||
for (int j = 0; j < this.containerRows; ++j) {
|
||||
for (int k = 0; k < 17; ++k) {
|
||||
this.addSlot(new Slot(pContainer, k + j * 17, 8 + k * 18 + 25, 18 + j * 18));
|
||||
}
|
||||
}
|
||||
|
||||
for (int l = 0; l < 3; ++l) {
|
||||
for (int j = 0; j < 9; ++j) {
|
||||
this.addSlot(new Slot(pPlayerInventory, j + l * 9 + 9, 8 + j * 18 + X_OFFSET, 84 + l * 18 + Y_OFFSET + i));
|
||||
}
|
||||
}
|
||||
|
||||
for (int k = 0; k < 9; ++k) {
|
||||
this.addSlot(new Slot(pPlayerInventory, k, 8 + k * 18 + X_OFFSET, 142 + Y_OFFSET + i));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ItemStack quickMoveStack(@NotNull Player pPlayer, int pIndex) {
|
||||
ItemStack itemstack = ItemStack.EMPTY;
|
||||
Slot slot = this.slots.get(pIndex);
|
||||
if (slot.hasItem()) {
|
||||
ItemStack stack = slot.getItem();
|
||||
itemstack = stack.copy();
|
||||
if (pIndex < this.containerRows * 17 + 3) {
|
||||
if (!this.moveItemStackTo(stack, this.containerRows * 17 + 3, this.slots.size(), true)) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
} else if (!this.moveItemStackTo(stack, 0, this.containerRows * 17, false)) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
if (stack.isEmpty()) {
|
||||
slot.setByPlayer(ItemStack.EMPTY);
|
||||
} else {
|
||||
slot.setChanged();
|
||||
}
|
||||
}
|
||||
|
||||
return itemstack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean stillValid(@NotNull Player pPlayer) {
|
||||
return this.container.stillValid(pPlayer);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package com.atsuishio.superbwarfare.network.dataslot;
|
||||
|
||||
public interface ContainerEnergyData {
|
||||
|
||||
long get(int pIndex);
|
||||
|
||||
void set(int pIndex, long pValue);
|
||||
|
||||
int getCount();
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
package com.atsuishio.superbwarfare.network.dataslot;
|
||||
|
||||
/**
|
||||
* Code based on @GoryMoon's Chargers
|
||||
*/
|
||||
public abstract class ContainerEnergyDataSlot {
|
||||
|
||||
private long prevValue;
|
||||
|
||||
public ContainerEnergyDataSlot() {
|
||||
}
|
||||
|
||||
public static ContainerEnergyDataSlot forContainer(final ContainerEnergyData data, final int index) {
|
||||
return new ContainerEnergyDataSlot() {
|
||||
public long get() {
|
||||
return data.get(index);
|
||||
}
|
||||
|
||||
public void set(long value) {
|
||||
data.set(index, value);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public abstract long get();
|
||||
|
||||
public abstract void set(long value);
|
||||
|
||||
public boolean checkAndClearUpdateFlag() {
|
||||
long tmp = this.get();
|
||||
boolean changed = tmp != this.prevValue;
|
||||
this.prevValue = tmp;
|
||||
return changed;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package com.atsuishio.superbwarfare.network.dataslot;
|
||||
|
||||
/**
|
||||
* Code based on @GoryMoon's Chargers
|
||||
*/
|
||||
public class SimpleEnergyData implements ContainerEnergyData {
|
||||
|
||||
private final long[] data;
|
||||
|
||||
public SimpleEnergyData(int size) {
|
||||
this.data = new long[size];
|
||||
}
|
||||
|
||||
@Override
|
||||
public long get(int index) {
|
||||
return this.data[index];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(int index, long value) {
|
||||
this.data[index] = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return this.data.length;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,174 @@
|
|||
package com.atsuishio.superbwarfare.tools;
|
||||
|
||||
import com.atsuishio.superbwarfare.init.ModParticleTypes;
|
||||
import com.atsuishio.superbwarfare.init.ModSounds;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.particles.ParticleOptions;
|
||||
import net.minecraft.core.particles.ParticleTypes;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.sounds.SoundEvents;
|
||||
import net.minecraft.sounds.SoundSource;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
public class ParticleTool {
|
||||
public static <T extends ParticleOptions> void sendParticle(ServerLevel level, T particle, double x, double y, double z, int count,
|
||||
double xOffset, double yOffset, double zOffset, double speed, boolean force) {
|
||||
for (ServerPlayer serverPlayer : level.players()) {
|
||||
sendParticle(level, particle, x, y, z, count, xOffset, yOffset, zOffset, speed, force, serverPlayer);
|
||||
}
|
||||
}
|
||||
|
||||
public static <T extends ParticleOptions> void sendParticle(ServerLevel level, T particle, double x, double y, double z, int count,
|
||||
double xOffset, double yOffset, double zOffset, double speed, boolean force, ServerPlayer viewer) {
|
||||
level.sendParticles(viewer, particle, force, x, y, z, count, xOffset, yOffset, zOffset, speed);
|
||||
}
|
||||
|
||||
public static void spawnMiniExplosionParticles(Level level, Vec3 pos) {
|
||||
double x = pos.x;
|
||||
double y = pos.y;
|
||||
double z = pos.z;
|
||||
|
||||
if (!level.isClientSide()) {
|
||||
if ((level.getBlockState(BlockPos.containing(x, y, z))).getBlock() == Blocks.WATER) {
|
||||
level.playSound(null, BlockPos.containing(x, y + 1, z), ModSounds.EXPLOSION_WATER.get(), SoundSource.BLOCKS, 2, 1);
|
||||
}
|
||||
level.playSound(null, BlockPos.containing(x, y + 1, z), SoundEvents.FIREWORK_ROCKET_BLAST, SoundSource.BLOCKS, 4, 1);
|
||||
} else {
|
||||
if ((level.getBlockState(BlockPos.containing(x, y, z))).getBlock() == Blocks.WATER) {
|
||||
level.playLocalSound(x, (y + 1), z, ModSounds.EXPLOSION_WATER.get(), SoundSource.BLOCKS, 1, 1, false);
|
||||
}
|
||||
level.playLocalSound(x, (y + 1), z, SoundEvents.FIREWORK_ROCKET_BLAST, SoundSource.BLOCKS, 2, 1, false);
|
||||
}
|
||||
|
||||
if (level instanceof ServerLevel serverLevel) {
|
||||
sendParticle(serverLevel, ParticleTypes.CAMPFIRE_COSY_SMOKE, x, y, z, 3, 0.1, 0.1, 0.1, 0.02, true);
|
||||
sendParticle(serverLevel, ParticleTypes.LARGE_SMOKE, x, y, z, 4, 0.2, 0.2, 0.2, 0.02, true);
|
||||
sendParticle(serverLevel, ModParticleTypes.FIRE_STAR.get(), x, y, z, 6, 0, 0, 0, 0.2, true);
|
||||
}
|
||||
}
|
||||
|
||||
public static void spawnSmallExplosionParticles(Level level, Vec3 pos) {
|
||||
double x = pos.x;
|
||||
double y = pos.y;
|
||||
double z = pos.z;
|
||||
|
||||
if (!level.isClientSide()) {
|
||||
if ((level.getBlockState(BlockPos.containing(x, y, z))).getBlock() == Blocks.WATER) {
|
||||
level.playSound(null, BlockPos.containing(x, y + 1, z), ModSounds.EXPLOSION_WATER.get(), SoundSource.BLOCKS, 2, 1);
|
||||
}
|
||||
level.playSound(null, BlockPos.containing(x, y + 1, z), SoundEvents.FIREWORK_ROCKET_BLAST, SoundSource.BLOCKS, 4, 1);
|
||||
level.playSound(null, BlockPos.containing(x, y + 1, z), ModSounds.EXPLOSION_CLOSE.get(), SoundSource.BLOCKS, 3, 1);
|
||||
level.playSound(null, BlockPos.containing(x, y + 1, z), ModSounds.EXPLOSION_FAR.get(), SoundSource.BLOCKS, 6, 1);
|
||||
level.playSound(null, BlockPos.containing(x, y + 1, z), ModSounds.EXPLOSION_VERY_FAR.get(), SoundSource.BLOCKS, 12, 1);
|
||||
} else {
|
||||
if ((level.getBlockState(BlockPos.containing(x, y, z))).getBlock() == Blocks.WATER) {
|
||||
level.playLocalSound(x, (y + 1), z, ModSounds.EXPLOSION_WATER.get(), SoundSource.BLOCKS, 1, 1, false);
|
||||
}
|
||||
level.playLocalSound(x, (y + 1), z, SoundEvents.FIREWORK_ROCKET_BLAST, SoundSource.BLOCKS, 2, 1, false);
|
||||
level.playLocalSound(x, (y + 1), z, ModSounds.EXPLOSION_CLOSE.get(), SoundSource.BLOCKS, 1, 1, false);
|
||||
level.playLocalSound(x, (y + 1), z, ModSounds.EXPLOSION_FAR.get(), SoundSource.BLOCKS, 1, 1, false);
|
||||
level.playLocalSound(x, (y + 1), z, ModSounds.EXPLOSION_VERY_FAR.get(), SoundSource.BLOCKS, 1, 1, false);
|
||||
}
|
||||
|
||||
if (level instanceof ServerLevel serverLevel) {
|
||||
sendParticle(serverLevel, ParticleTypes.EXPLOSION, x, y, z, 2, 0.05, 0.05, 0.05, 1, true);
|
||||
sendParticle(serverLevel, ParticleTypes.CAMPFIRE_COSY_SMOKE, x, y, z, 3, 0.1, 0.1, 0.1, 0.02, true);
|
||||
sendParticle(serverLevel, ParticleTypes.LARGE_SMOKE, x, y, z, 4, 0.2, 0.2, 0.2, 0.02, true);
|
||||
sendParticle(serverLevel, ModParticleTypes.FIRE_STAR.get(), x, y, z, 20, 0, 0, 0, 0.6, true);
|
||||
sendParticle(serverLevel, ParticleTypes.FLASH, x, y, z, 5, 0.1, 0.1, 0.1, 20, true);
|
||||
}
|
||||
}
|
||||
|
||||
public static void spawnMediumExplosionParticles(Level level, Vec3 pos) {
|
||||
double x = pos.x;
|
||||
double y = pos.y;
|
||||
double z = pos.z;
|
||||
|
||||
if (!level.isClientSide()) {
|
||||
if ((level.getBlockState(BlockPos.containing(x, y, z))).getBlock() == Blocks.WATER) {
|
||||
level.playSound(null, BlockPos.containing(x, y + 1, z), ModSounds.EXPLOSION_WATER.get(), SoundSource.BLOCKS, 3, 1);
|
||||
}
|
||||
level.playSound(null, BlockPos.containing(x, y + 1, z), ModSounds.EXPLOSION_CLOSE.get(), SoundSource.BLOCKS, 6, 1);
|
||||
level.playSound(null, BlockPos.containing(x, y + 1, z), ModSounds.EXPLOSION_FAR.get(), SoundSource.BLOCKS, 12, 1);
|
||||
level.playSound(null, BlockPos.containing(x, y + 1, z), ModSounds.EXPLOSION_VERY_FAR.get(), SoundSource.BLOCKS, 32, 1);
|
||||
} else {
|
||||
if ((level.getBlockState(BlockPos.containing(x, y, z))).getBlock() == Blocks.WATER) {
|
||||
level.playLocalSound(x, (y + 1), z, ModSounds.EXPLOSION_WATER.get(), SoundSource.BLOCKS, 1, 1, false);
|
||||
}
|
||||
level.playLocalSound(x, (y + 1), z, ModSounds.EXPLOSION_CLOSE.get(), SoundSource.BLOCKS, 1, 1, false);
|
||||
level.playLocalSound(x, (y + 1), z, ModSounds.EXPLOSION_FAR.get(), SoundSource.BLOCKS, 1, 1, false);
|
||||
level.playLocalSound(x, (y + 1), z, ModSounds.EXPLOSION_VERY_FAR.get(), SoundSource.BLOCKS, 1, 1, false);
|
||||
}
|
||||
|
||||
if (level instanceof ServerLevel serverLevel) {
|
||||
if ((level.getBlockState(BlockPos.containing(x, y, z))).getBlock() == Blocks.WATER) {
|
||||
sendParticle(serverLevel, ParticleTypes.CLOUD, x, y + 3, z, 20, 1, 3, 1, 0.01, true);
|
||||
sendParticle(serverLevel, ParticleTypes.CLOUD, x, y + 3, z, 30, 2, 1, 2, 0.01, true);
|
||||
sendParticle(serverLevel, ParticleTypes.FALLING_WATER, x, y + 3, z, 50, 1.5, 4, 1.5, 1, true);
|
||||
sendParticle(serverLevel, ParticleTypes.BUBBLE_COLUMN_UP, x, y, z, 60, 3, 0.5, 3, 0.1, true);
|
||||
}
|
||||
sendParticle(serverLevel, ParticleTypes.EXPLOSION, x, y + 1, z, 5, 0.7, 0.7, 0.7, 1, true);
|
||||
sendParticle(serverLevel, ParticleTypes.CAMPFIRE_COSY_SMOKE, x, y + 1, z, 20, 0.2, 1, 0.2, 0.02, true);
|
||||
sendParticle(serverLevel, ParticleTypes.LARGE_SMOKE, x, y + 1, z, 10, 0.4, 1, 0.4, 0.02, true);
|
||||
sendParticle(serverLevel, ParticleTypes.CAMPFIRE_COSY_SMOKE, x, y + 0.25, z, 40, 2, 0.001, 2, 0.01, true);
|
||||
sendParticle(serverLevel, ModParticleTypes.FIRE_STAR.get(), x, y + 0.2, z, 50, 0, 0, 0, 0.9, true);
|
||||
sendParticle(serverLevel, ParticleTypes.FLASH, x, y + 0.5, z, 50, 0.2, 0.2, 0.2, 20, true);
|
||||
}
|
||||
}
|
||||
|
||||
public static void spawnHugeExplosionParticles(Level level, Vec3 pos) {
|
||||
double x = pos.x;
|
||||
double y = pos.y;
|
||||
double z = pos.z;
|
||||
|
||||
if (!level.isClientSide()) {
|
||||
if ((level.getBlockState(BlockPos.containing(x, y, z))).getBlock() == Blocks.WATER) {
|
||||
level.playSound(null, BlockPos.containing(x, y + 1, z), ModSounds.EXPLOSION_WATER.get(), SoundSource.BLOCKS, 3, 1);
|
||||
}
|
||||
level.playSound(null, BlockPos.containing(x, y + 1, z), ModSounds.HUGE_EXPLOSION_CLOSE.get(), SoundSource.BLOCKS, 8, 1);
|
||||
level.playSound(null, BlockPos.containing(x, y + 1, z), ModSounds.HUGE_EXPLOSION_FAR.get(), SoundSource.BLOCKS, 16, 1);
|
||||
level.playSound(null, BlockPos.containing(x, y + 1, z), ModSounds.HUGE_EXPLOSION_VERY_FAR.get(), SoundSource.BLOCKS, 32, 1);
|
||||
} else {
|
||||
if ((level.getBlockState(BlockPos.containing(x, y, z))).getBlock() == Blocks.WATER) {
|
||||
level.playLocalSound(x, (y + 1), z, ModSounds.EXPLOSION_WATER.get(), SoundSource.BLOCKS, 1, 1, false);
|
||||
}
|
||||
level.playLocalSound(x, (y + 1), z, ModSounds.HUGE_EXPLOSION_CLOSE.get(), SoundSource.BLOCKS, 1, 1, false);
|
||||
level.playLocalSound(x, (y + 1), z, ModSounds.HUGE_EXPLOSION_FAR.get(), SoundSource.BLOCKS, 1, 1, false);
|
||||
level.playLocalSound(x, (y + 1), z, ModSounds.HUGE_EXPLOSION_VERY_FAR.get(), SoundSource.BLOCKS, 1, 1, false);
|
||||
}
|
||||
|
||||
if (level instanceof ServerLevel serverLevel) {
|
||||
if ((level.getBlockState(BlockPos.containing(x, y, z))).getBlock() == Blocks.WATER) {
|
||||
sendParticle(serverLevel, ParticleTypes.CLOUD, x, y + 3, z, 100, 2, 6, 2, 0.01, true);
|
||||
sendParticle(serverLevel, ParticleTypes.CLOUD, x, y + 3, z, 200, 4, 2, 4, 0.01, true);
|
||||
sendParticle(serverLevel, ParticleTypes.FALLING_WATER, x, y + 3, z, 500, 3, 8, 3, 1, true);
|
||||
sendParticle(serverLevel, ParticleTypes.BUBBLE_COLUMN_UP, x, y, z, 350, 6, 1, 6, 0.1, true);
|
||||
}
|
||||
|
||||
sendParticle(serverLevel, ParticleTypes.EXPLOSION, x, y + 1, z, 75, 2.5, 2.5, 2.5, 1, true);
|
||||
sendParticle(serverLevel, ParticleTypes.FLASH, x, y + 1, z, 200, 5, 5, 5, 20, true);
|
||||
sendParticle(serverLevel, ModParticleTypes.FIRE_STAR.get(), x, y + 1, z, 400, 0, 0, 0, 1.5, true);
|
||||
sendParticle(serverLevel, ParticleTypes.CAMPFIRE_COSY_SMOKE, x, y + 1, z, 75, 2, 3, 2, 0.005, true);
|
||||
sendParticle(serverLevel, ParticleTypes.CAMPFIRE_COSY_SMOKE, x, y, z, 150, 7, 0.1, 7, 0.005, true);
|
||||
sendParticle(serverLevel, ParticleTypes.CLOUD, x, y + 1, z, 200, 3, 4, 3, 0.4, true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static void cannonHitParticles(Level level, Vec3 pos, Entity entity) {
|
||||
double x = pos.x + 0.5 * entity.getDeltaMovement().x;
|
||||
double y = pos.y + 0.5 * entity.getDeltaMovement().y;
|
||||
double z = pos.z + 0.5 * entity.getDeltaMovement().z;
|
||||
|
||||
if (level instanceof ServerLevel serverLevel) {
|
||||
sendParticle(serverLevel, ParticleTypes.EXPLOSION, x, y, z, 2, 0.5, 0.5, 0.5, 1, true);
|
||||
sendParticle(serverLevel, ParticleTypes.FLASH, x, y, z, 2, 0.2, 0.2, 0.2, 10, true);
|
||||
sendParticle(serverLevel, ModParticleTypes.FIRE_STAR.get(), x, y, z, 40, 0, 0, 0, 1.5, true);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"variants": {
|
||||
"": {
|
||||
"model": "superbwarfare:block/dragon_teeth"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"variants": {
|
||||
"": {
|
||||
"model": "superbwarfare:block/sandbag"
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue