移植部分Capability、方块、菜单

This commit is contained in:
Light_Quanta 2025-03-26 00:36:37 +08:00
parent 85d5e741e7
commit 47896a82fe
No known key found for this signature in database
GPG key ID: 11A39A1B8C890959
40 changed files with 3980 additions and 15 deletions

View file

@ -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);
}

View file

@ -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);
}
}

View file

@ -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;
}
}

View file

@ -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());
}
}

View file

@ -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;

View 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);
}
}

View file

@ -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));
// }
}

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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
}
}

View file

@ -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;
});
}
}
}

View file

@ -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);
}
}
}

View file

@ -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;
}
}

View file

@ -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);
}

View file

@ -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;
}
}

View file

@ -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);
}
}

View file

@ -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;
}
}

View file

@ -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);
}
}

View file

@ -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;
}
}

View file

@ -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());
}

View file

@ -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);
}
}
}

View file

@ -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);
}
}

View file

@ -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));
}

View file

@ -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);
}

View 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());
}
}

View file

@ -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);
//

View file

@ -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)));
}

View 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);
}
}

View 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;
}
}

View file

@ -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);
}
}
}

View file

@ -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);
// }
// }
}

View 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));
}
}
}

View file

@ -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;
}
}
}

View file

@ -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);
}
}

View file

@ -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();
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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);
}
}
}

View file

@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "superbwarfare:block/dragon_teeth"
}
}
}

View file

@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "superbwarfare:block/sandbag"
}
}
}