BCLib/src/main/java/org/betterx/bclib/items/DebugDataItem.java
2023-06-07 18:57:25 +02:00

284 lines
11 KiB
Java

package org.betterx.bclib.items;
import org.betterx.bclib.client.models.ModelsHelper;
import org.betterx.bclib.commands.PlaceCommand;
import org.betterx.bclib.interfaces.ItemModelProvider;
import org.betterx.bclib.util.BlocksHelper;
import org.betterx.ui.ColorUtil;
import net.minecraft.client.renderer.block.model.BlockModel;
import net.minecraft.commands.arguments.blocks.BlockStateParser;
import net.minecraft.core.BlockPos;
import net.minecraft.core.FrontAndTop;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.data.worldgen.Pools;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.Style;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.util.Mth;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.InteractionResultHolder;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.context.UseOnContext;
import net.minecraft.world.level.ClipBlockStateContext;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.JigsawBlock;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.JigsawBlockEntity;
import net.minecraft.world.level.block.entity.RandomizableContainerBlockEntity;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.levelgen.structure.pools.StructureTemplatePool;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.Vec3;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
public class DebugDataItem extends Item implements ItemModelProvider {
public static final ResourceLocation DEFAULT_ICON = new ResourceLocation("stick");
interface DebugInteraction {
InteractionResult use(UseOnContext useOnContext);
}
interface DebugEntityInteraction extends DebugInteraction {
@Override
default InteractionResult use(UseOnContext useOnContext) {
var entity = useOnContext.getLevel().getBlockEntity(useOnContext.getClickedPos());
if (entity != null) {
return use(useOnContext.getPlayer(), entity, useOnContext);
}
return InteractionResult.FAIL;
}
InteractionResult use(Player player, BlockEntity entity, UseOnContext useOnContext);
}
protected final DebugInteraction interaction;
protected final ResourceLocation icon;
public final boolean placeInAir;
public DebugDataItem(DebugEntityInteraction interaction, boolean placeInAir, ResourceLocation icon) {
this((DebugInteraction) interaction, placeInAir, icon);
}
public DebugDataItem(DebugInteraction interaction, boolean placeInAir, ResourceLocation icon) {
super(new Item.Properties().fireResistant().stacksTo(1));
this.interaction = interaction;
this.icon = (icon == null ? DEFAULT_ICON : icon);
this.placeInAir = placeInAir;
}
@Override
public boolean isFoil(ItemStack itemStack) {
return true;
}
@Override
@Environment(EnvType.CLIENT)
public BlockModel getItemModel(ResourceLocation resourceLocation) {
return ModelsHelper.createItemModel(icon);
}
@Override
public InteractionResult useOn(UseOnContext useOnContext) {
if (!useOnContext.getPlayer().canUseGameMasterBlocks()) {
return InteractionResult.FAIL;
}
return interaction.use(useOnContext);
}
public static void message(Player player, String text) {
message(player, text, ColorUtil.GRAY);
}
public static void message(Player player, String text, int color) {
message(player, Component.literal(text).withStyle(Style.EMPTY.withColor(color)));
}
public static void message(Player player, Component component) {
if (player instanceof ServerPlayer sp) {
sp.sendSystemMessage(component, true);
}
}
@Override
public boolean canAttackBlock(BlockState blockState, Level level, BlockPos blockPos, Player player) {
return false;
}
@Override
public InteractionResultHolder<ItemStack> use(Level level, Player player, InteractionHand interactionHand) {
if (placeInAir) {
final var vec = new Vec3(0, 0, 1)
.xRot(-player.getXRot() * Mth.DEG_TO_RAD)
.yRot(-player.getYHeadRot() * Mth.DEG_TO_RAD);
BlockHitResult hit = level.isBlockInLine(new ClipBlockStateContext(
player.getEyePosition(),
player.getEyePosition().add(vec.scale(6.0)),
BlockBehaviour.BlockStateBase::isAir
));
if (hit != null) {
var result = this.useOn(new UseOnContext(player, interactionHand, hit));
if (result == InteractionResult.SUCCESS)
return InteractionResultHolder.success(player.getItemInHand(interactionHand));
else if (result == InteractionResult.FAIL)
return InteractionResultHolder.fail(player.getItemInHand(interactionHand));
else if (result == InteractionResult.PASS)
return InteractionResultHolder.pass(player.getItemInHand(interactionHand));
else if (result == InteractionResult.CONSUME)
return InteractionResultHolder.consume(player.getItemInHand(interactionHand));
}
}
return InteractionResultHolder.pass(player.getItemInHand(interactionHand));
}
public static DebugDataItem forLootTable(ResourceLocation table, Item icon) {
ResourceLocation iconId = BuiltInRegistries.ITEM.getKey(icon);
return new DebugDataItem(
(player, entity, ctx) -> {
CompoundTag tag = entity.saveWithoutMetadata();
tag.remove(RandomizableContainerBlockEntity.LOOT_TABLE_SEED_TAG);
tag.remove("Items");
tag.putString(RandomizableContainerBlockEntity.LOOT_TABLE_TAG, table.toString());
entity.load(tag);
message(player, "Did set Loot Table to " + table.toString());
return InteractionResult.SUCCESS;
},
false,
iconId
);
}
public static DebugDataItem forSteetJigSaw(
String modID,
ResourceKey<StructureTemplatePool> pool,
Item icon
) {
return forJigsaw(
pool == null ? Pools.EMPTY : pool,
new ResourceLocation(modID, "street"),
JigsawBlockEntity.JointType.ALIGNED,
null,
null,
icon
);
}
public static DebugDataItem forHouseEntranceJigSaw(
String modID,
ResourceKey<StructureTemplatePool> pool,
Item icon
) {
return forJigsaw(
pool == null ? Pools.EMPTY : pool,
new ResourceLocation(modID, "building_entrance"),
JigsawBlockEntity.JointType.ALIGNED,
null,
null,
icon
);
}
public static DebugDataItem forDecorationJigSaw(
String modID,
ResourceKey<StructureTemplatePool> pool,
Item icon
) {
return forJigsaw(
pool == null ? Pools.EMPTY : pool,
new ResourceLocation(modID, "bottom"),
pool == null ? new ResourceLocation("empty") : new ResourceLocation(modID, "bottom"),
JigsawBlockEntity.JointType.ROLLABLE,
null,
pool == null ? FrontAndTop.NORTH_UP : null,
icon
);
}
public static DebugDataItem forJigsaw(
ResourceKey<StructureTemplatePool> pool,
ResourceLocation connector,
JigsawBlockEntity.JointType type,
BlockState finalState,
FrontAndTop forceOrientation,
Item icon
) {
return forJigsaw(pool, connector, connector, type, finalState, forceOrientation, icon);
}
public static DebugDataItem forJigsaw(
ResourceKey<StructureTemplatePool> pool,
ResourceLocation name,
ResourceLocation target,
JigsawBlockEntity.JointType type,
BlockState finalState,
FrontAndTop forceOrientation,
Item icon
) {
ResourceLocation iconId = BuiltInRegistries.ITEM.getKey(icon);
return new DebugDataItem(
(ctx) -> {
final var player = ctx.getPlayer();
final var level = ctx.getLevel();
final var pos = ctx.getClickedPos();
var state = level.getBlockState(pos);
var entity = level.getBlockEntity(pos);
var targetState = finalState;
if (!(entity instanceof JigsawBlockEntity)) {
if (targetState == null)
targetState = state;
state = Blocks.JIGSAW.defaultBlockState();
level.setBlock(pos, state, BlocksHelper.SET_SILENT);
entity = level.getBlockEntity(pos);
message(player, "Created JigSaw at " + pos.toString());
}
if (entity instanceof JigsawBlockEntity e) {
if (forceOrientation == null) {
state = PlaceCommand.setJigsawOrientation(
JigsawBlockEntity.JointType.ROLLABLE != type,
player, pos, state
);
} else {
state = state.setValue(JigsawBlock.ORIENTATION, forceOrientation);
}
level.setBlock(pos, state, BlocksHelper.SET_SILENT);
if (pool != null) e.setName(name);
if (pool != null) e.setTarget(target);
if (pool != null) e.setPool(pool);
if (targetState != null) e.setFinalState(BlockStateParser.serialize(targetState));
e.setJoint(type);
message(player, "Did update Jigsaw at " + pos.toString());
return InteractionResult.SUCCESS;
}
return InteractionResult.FAIL;
},
true,
iconId
);
}
}