src: add 2 files
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
package com.hypixel.hytale.server.core.event.events.ecs;
|
||||
|
||||
import com.hypixel.hytale.component.system.CancellableEcsEvent;
|
||||
import com.hypixel.hytale.math.vector.Vector3i;
|
||||
import com.hypixel.hytale.server.core.asset.type.blocktype.config.BlockType;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* Event fired when a player attempts to gather (harvest) a block.
|
||||
* This event is cancellable - if cancelled, the block will not be gathered.
|
||||
*/
|
||||
public class GatherBlockEvent extends CancellableEcsEvent {
|
||||
@Nonnull
|
||||
private final Vector3i targetBlock;
|
||||
@Nonnull
|
||||
private final BlockType blockType;
|
||||
|
||||
public GatherBlockEvent(@Nonnull Vector3i targetBlock, @Nonnull BlockType blockType) {
|
||||
this.targetBlock = targetBlock;
|
||||
this.blockType = blockType;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public Vector3i getTargetBlock() {
|
||||
return this.targetBlock;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public BlockType getBlockType() {
|
||||
return this.blockType;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,892 @@
|
||||
package com.hypixel.hytale.server.core.modules.interaction;
|
||||
|
||||
import com.hypixel.hytale.component.AddReason;
|
||||
import com.hypixel.hytale.component.CommandBuffer;
|
||||
import com.hypixel.hytale.component.ComponentAccessor;
|
||||
import com.hypixel.hytale.component.ComponentType;
|
||||
import com.hypixel.hytale.component.Holder;
|
||||
import com.hypixel.hytale.component.Ref;
|
||||
import com.hypixel.hytale.component.spatial.SpatialResource;
|
||||
import com.hypixel.hytale.math.util.ChunkUtil;
|
||||
import com.hypixel.hytale.math.vector.Vector3d;
|
||||
import com.hypixel.hytale.math.vector.Vector3f;
|
||||
import com.hypixel.hytale.math.vector.Vector3i;
|
||||
import com.hypixel.hytale.protocol.BlockSoundEvent;
|
||||
import com.hypixel.hytale.protocol.SoundCategory;
|
||||
import com.hypixel.hytale.server.core.asset.type.blockhitbox.BlockBoundingBoxes;
|
||||
import com.hypixel.hytale.server.core.asset.type.blocksound.config.BlockSoundSet;
|
||||
import com.hypixel.hytale.server.core.asset.type.blocktype.config.BlockBreakingDropType;
|
||||
import com.hypixel.hytale.server.core.asset.type.blocktype.config.BlockGathering;
|
||||
import com.hypixel.hytale.server.core.asset.type.blocktype.config.BlockType;
|
||||
import com.hypixel.hytale.server.core.asset.type.blocktype.config.HarvestingDropType;
|
||||
import com.hypixel.hytale.server.core.asset.type.blocktype.config.PhysicsDropType;
|
||||
import com.hypixel.hytale.server.core.asset.type.blocktype.config.RotationTuple;
|
||||
import com.hypixel.hytale.server.core.asset.type.blocktype.config.SoftBlockDropType;
|
||||
import com.hypixel.hytale.server.core.asset.type.environment.config.Environment;
|
||||
import com.hypixel.hytale.server.core.asset.type.gameplay.BrokenPenalties;
|
||||
import com.hypixel.hytale.server.core.asset.type.gameplay.GameplayConfig;
|
||||
import com.hypixel.hytale.server.core.asset.type.gameplay.GatheringEffectsConfig;
|
||||
import com.hypixel.hytale.server.core.asset.type.item.config.Item;
|
||||
import com.hypixel.hytale.server.core.asset.type.item.config.ItemTool;
|
||||
import com.hypixel.hytale.server.core.asset.type.item.config.ItemToolSpec;
|
||||
import com.hypixel.hytale.server.core.blocktype.component.BlockPhysics;
|
||||
import com.hypixel.hytale.server.core.entity.ItemUtils;
|
||||
import com.hypixel.hytale.server.core.entity.LivingEntity;
|
||||
import com.hypixel.hytale.server.core.event.events.ecs.BreakBlockEvent;
|
||||
import com.hypixel.hytale.server.core.event.events.ecs.DamageBlockEvent;
|
||||
import com.hypixel.hytale.server.core.event.events.ecs.GatherBlockEvent;
|
||||
import com.hypixel.hytale.server.core.inventory.ItemStack;
|
||||
import com.hypixel.hytale.server.core.inventory.container.ItemContainer;
|
||||
import com.hypixel.hytale.server.core.modules.blockhealth.BlockHealth;
|
||||
import com.hypixel.hytale.server.core.modules.blockhealth.BlockHealthChunk;
|
||||
import com.hypixel.hytale.server.core.modules.blockhealth.BlockHealthModule;
|
||||
import com.hypixel.hytale.server.core.modules.blockset.BlockSetModule;
|
||||
import com.hypixel.hytale.server.core.modules.entity.EntityModule;
|
||||
import com.hypixel.hytale.server.core.modules.entity.item.ItemComponent;
|
||||
import com.hypixel.hytale.server.core.modules.item.ItemModule;
|
||||
import com.hypixel.hytale.server.core.modules.time.TimeResource;
|
||||
import com.hypixel.hytale.server.core.universe.world.ParticleUtil;
|
||||
import com.hypixel.hytale.server.core.universe.world.SoundUtil;
|
||||
import com.hypixel.hytale.server.core.universe.world.World;
|
||||
import com.hypixel.hytale.server.core.universe.world.chunk.BlockChunk;
|
||||
import com.hypixel.hytale.server.core.universe.world.chunk.ChunkColumn;
|
||||
import com.hypixel.hytale.server.core.universe.world.chunk.WorldChunk;
|
||||
import com.hypixel.hytale.server.core.universe.world.chunk.section.BlockSection;
|
||||
import com.hypixel.hytale.server.core.universe.world.connectedblocks.ConnectedBlocksUtil;
|
||||
import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore;
|
||||
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
|
||||
import com.hypixel.hytale.server.core.util.FillerBlockUtil;
|
||||
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
||||
import it.unimi.dsi.fastutil.objects.ObjectList;
|
||||
import it.unimi.dsi.fastutil.objects.ObjectLists;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class BlockHarvestUtils {
|
||||
public BlockHarvestUtils() {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static ItemToolSpec getSpecPowerDamageBlock(@Nullable Item item, @Nullable BlockType blockType, @Nullable ItemTool tool) {
|
||||
if (blockType == null) {
|
||||
return null;
|
||||
} else {
|
||||
BlockGathering gathering = blockType.getGathering();
|
||||
if (gathering == null) {
|
||||
return null;
|
||||
} else {
|
||||
BlockBreakingDropType breaking = gathering.getBreaking();
|
||||
if (breaking == null) {
|
||||
return null;
|
||||
} else {
|
||||
String gatherType = breaking.getGatherType();
|
||||
if (gatherType == null) {
|
||||
return null;
|
||||
} else if (item == null || item.getWeapon() == null && item.getBuilderToolData() == null) {
|
||||
int requiredQuality = breaking.getQuality();
|
||||
if (tool == null) {
|
||||
ItemToolSpec defaultSpec = ItemToolSpec.getAssetMap().getAsset(gatherType);
|
||||
return defaultSpec != null && defaultSpec.getQuality() < requiredQuality ? null : defaultSpec;
|
||||
} else {
|
||||
if (tool.getSpecs() != null) {
|
||||
for (ItemToolSpec spec : tool.getSpecs()) {
|
||||
if (Objects.equals(spec.getGatherType(), gatherType)) {
|
||||
if (spec.getQuality() < requiredQuality) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return spec;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static double calculateDurabilityUse(@Nonnull Item item, @Nullable BlockType blockType) {
|
||||
if (blockType == null) {
|
||||
return 0.0;
|
||||
} else if (blockType.getGathering().isSoft()) {
|
||||
return 0.0;
|
||||
} else if (item.getTool() == null) {
|
||||
return 0.0;
|
||||
} else {
|
||||
ItemTool itemTool = item.getTool();
|
||||
ItemTool.DurabilityLossBlockTypes[] durabilityLossBlockTypes = itemTool.getDurabilityLossBlockTypes();
|
||||
if (durabilityLossBlockTypes == null) {
|
||||
return item.getDurabilityLossOnHit();
|
||||
} else {
|
||||
String hitBlockTypeId = blockType.getId();
|
||||
int hitBlockTypeIndex = BlockType.getAssetMap().getIndex(hitBlockTypeId);
|
||||
if (hitBlockTypeIndex == Integer.MIN_VALUE) {
|
||||
throw new IllegalArgumentException("Unknown key! " + hitBlockTypeId);
|
||||
} else {
|
||||
BlockSetModule blockSetModule = BlockSetModule.getInstance();
|
||||
|
||||
for (ItemTool.DurabilityLossBlockTypes durabilityLossBlockType : durabilityLossBlockTypes) {
|
||||
int[] blockTypeIndexes = durabilityLossBlockType.getBlockTypeIndexes();
|
||||
if (blockTypeIndexes != null) {
|
||||
for (int blockTypeIndex : blockTypeIndexes) {
|
||||
if (blockTypeIndex == hitBlockTypeIndex) {
|
||||
return durabilityLossBlockType.getDurabilityLossOnHit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int[] blockSetIndexes = durabilityLossBlockType.getBlockSetIndexes();
|
||||
if (blockSetIndexes != null) {
|
||||
for (int blockSetIndex : blockSetIndexes) {
|
||||
if (blockSetModule.blockInSet(blockSetIndex, hitBlockTypeId)) {
|
||||
return durabilityLossBlockType.getDurabilityLossOnHit();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return item.getDurabilityLossOnHit();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean performBlockDamage(
|
||||
@Nonnull Vector3i targetBlock,
|
||||
@Nullable ItemStack itemStack,
|
||||
@Nullable ItemTool tool,
|
||||
float damageScale,
|
||||
int setBlockSettings,
|
||||
@Nonnull Ref<ChunkStore> chunkReference,
|
||||
@Nonnull CommandBuffer<EntityStore> commandBuffer,
|
||||
@Nonnull ComponentAccessor<ChunkStore> chunkStore
|
||||
) {
|
||||
return performBlockDamage(null, null, targetBlock, itemStack, tool, null, false, damageScale, setBlockSettings, chunkReference, commandBuffer, chunkStore);
|
||||
}
|
||||
|
||||
public static boolean performBlockDamage(
|
||||
@Nullable LivingEntity entity,
|
||||
@Nullable Ref<EntityStore> ref,
|
||||
@Nonnull Vector3i targetBlockPos,
|
||||
@Nullable ItemStack itemStack,
|
||||
@Nullable ItemTool tool,
|
||||
@Nullable String toolId,
|
||||
boolean matchTool,
|
||||
float damageScale,
|
||||
int setBlockSettings,
|
||||
@Nonnull Ref<ChunkStore> chunkReference,
|
||||
@Nonnull ComponentAccessor<EntityStore> entityStore,
|
||||
@Nonnull ComponentAccessor<ChunkStore> chunkStore
|
||||
) {
|
||||
World world = entityStore.getExternalData().getWorld();
|
||||
GameplayConfig gameplayConfig = world.getGameplayConfig();
|
||||
WorldChunk worldChunkComponent = chunkStore.getComponent(chunkReference, WorldChunk.getComponentType());
|
||||
if (worldChunkComponent == null) {
|
||||
return false;
|
||||
} else {
|
||||
BlockChunk blockChunkComponent = chunkStore.getComponent(chunkReference, BlockChunk.getComponentType());
|
||||
|
||||
assert blockChunkComponent != null;
|
||||
|
||||
BlockSection targetSection = blockChunkComponent.getSectionAtBlockY(targetBlockPos.y);
|
||||
int targetRotationIndex = targetSection.getRotationIndex(targetBlockPos.x, targetBlockPos.y, targetBlockPos.z);
|
||||
boolean brokeBlock = false;
|
||||
int environmentId = blockChunkComponent.getEnvironment(targetBlockPos.x, targetBlockPos.y, targetBlockPos.z);
|
||||
Environment environmentAsset = Environment.getAssetMap().getAsset(environmentId);
|
||||
SpatialResource<Ref<EntityStore>, EntityStore> playerSpatialResource = entityStore.getResource(EntityModule.get().getPlayerSpatialResourceType());
|
||||
if (environmentAsset != null && !environmentAsset.isBlockModificationAllowed()) {
|
||||
targetSection.invalidateBlock(targetBlockPos.x, targetBlockPos.y, targetBlockPos.z);
|
||||
return false;
|
||||
} else {
|
||||
BlockType targetBlockType = worldChunkComponent.getBlockType(targetBlockPos.x, targetBlockPos.y, targetBlockPos.z);
|
||||
if (targetBlockType == null) {
|
||||
return false;
|
||||
} else {
|
||||
BlockGathering blockGathering = targetBlockType.getGathering();
|
||||
if (blockGathering == null) {
|
||||
return false;
|
||||
} else if (matchTool && !blockGathering.getToolData().containsKey(toolId)) {
|
||||
return false;
|
||||
} else {
|
||||
Vector3d targetBlockCenterPos = new Vector3d();
|
||||
targetBlockType.getBlockCenter(targetRotationIndex, targetBlockCenterPos);
|
||||
targetBlockCenterPos.add(targetBlockPos);
|
||||
Vector3i originBlock = new Vector3i(targetBlockPos.x, targetBlockPos.y, targetBlockPos.z);
|
||||
if (!targetBlockType.isUnknown()) {
|
||||
int filler = targetSection.getFiller(targetBlockPos.x, targetBlockPos.y, targetBlockPos.z);
|
||||
int fillerX = FillerBlockUtil.unpackX(filler);
|
||||
int fillerY = FillerBlockUtil.unpackY(filler);
|
||||
int fillerZ = FillerBlockUtil.unpackZ(filler);
|
||||
if (fillerX != 0 || fillerY != 0 || fillerZ != 0) {
|
||||
originBlock = originBlock.clone().subtract(fillerX, fillerY, fillerZ);
|
||||
String oldBlockTypeKey = targetBlockType.getId();
|
||||
targetBlockType = world.getBlockType(originBlock.getX(), originBlock.getY(), originBlock.getZ());
|
||||
if (targetBlockType == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!oldBlockTypeKey.equals(targetBlockType.getId())) {
|
||||
worldChunkComponent.breakBlock(targetBlockPos.x, targetBlockPos.y, targetBlockPos.z);
|
||||
return true;
|
||||
}
|
||||
|
||||
blockGathering = targetBlockType.getGathering();
|
||||
if (blockGathering == null) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item heldItem = itemStack != null ? itemStack.getItem() : null;
|
||||
if (tool == null && heldItem != null) {
|
||||
tool = heldItem.getTool();
|
||||
}
|
||||
|
||||
ItemToolSpec itemToolSpec = getSpecPowerDamageBlock(heldItem, targetBlockType, tool);
|
||||
float specPower = itemToolSpec != null ? itemToolSpec.getPower() : 0.0F;
|
||||
boolean canApplyItemStackPenalties = entity != null && entity.canApplyItemStackPenalties(ref, entityStore);
|
||||
if (specPower != 0.0F && heldItem != null && heldItem.getTool() != null && itemStack.isBroken() && canApplyItemStackPenalties) {
|
||||
BrokenPenalties brokenPenalties = gameplayConfig.getItemDurabilityConfig().getBrokenPenalties();
|
||||
specPower *= 1.0F - (float)brokenPenalties.getTool(0.0);
|
||||
}
|
||||
|
||||
int dropQuantity = 1;
|
||||
String itemId;
|
||||
String dropListId;
|
||||
float damage;
|
||||
if (specPower != 0.0F) {
|
||||
BlockBreakingDropType breaking = blockGathering.getBreaking();
|
||||
damage = specPower;
|
||||
dropQuantity = breaking.getQuantity();
|
||||
itemId = breaking.getItemId();
|
||||
dropListId = breaking.getDropListId();
|
||||
} else {
|
||||
if (!blockGathering.isSoft()) {
|
||||
if (heldItem != null && heldItem.getWeapon() == null) {
|
||||
if (ref != null && entity != null) {
|
||||
GatheringEffectsConfig unbreakableBlockConfig = gameplayConfig.getGatheringConfig().getUnbreakableBlockConfig();
|
||||
if ((setBlockSettings & 4) == 0) {
|
||||
String particleSystemId = unbreakableBlockConfig.getParticleSystemId();
|
||||
if (particleSystemId != null) {
|
||||
ObjectList<Ref<EntityStore>> results = SpatialResource.getThreadLocalReferenceList();
|
||||
playerSpatialResource.getSpatialStructure().collect(targetBlockCenterPos, 75.0, results);
|
||||
ParticleUtil.spawnParticleEffect(particleSystemId, targetBlockCenterPos, results, entityStore);
|
||||
}
|
||||
}
|
||||
|
||||
if ((setBlockSettings & 1024) == 0) {
|
||||
int soundEventIndex = unbreakableBlockConfig.getSoundEventIndex();
|
||||
if (soundEventIndex != 0) {
|
||||
SoundUtil.playSoundEvent3d(ref, soundEventIndex, targetBlockCenterPos, entityStore);
|
||||
}
|
||||
|
||||
if (heldItem.getTool() != null) {
|
||||
int hitSoundEventLayerIndex = heldItem.getTool().getIncorrectMaterialSoundLayerIndex();
|
||||
if (hitSoundEventLayerIndex != 0) {
|
||||
SoundUtil.playSoundEvent3d(ref, hitSoundEventLayerIndex, targetBlockCenterPos, entityStore);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
SoftBlockDropType soft = blockGathering.getSoft();
|
||||
if (!soft.isWeaponBreakable() && heldItem != null && heldItem.getWeapon() != null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
damage = 1.0F;
|
||||
itemId = soft.getItemId();
|
||||
dropListId = soft.getDropListId();
|
||||
damageScale = 1.0F;
|
||||
}
|
||||
|
||||
damage *= damageScale;
|
||||
ChunkColumn chunkColumnComponent = chunkStore.getComponent(chunkReference, ChunkColumn.getComponentType());
|
||||
Ref<ChunkStore> chunkSectionRef = chunkColumnComponent != null
|
||||
? chunkColumnComponent.getSection(ChunkUtil.chunkCoordinate(targetBlockPos.y))
|
||||
: null;
|
||||
if (targetBlockType.getGathering().shouldUseDefaultDropWhenPlaced()) {
|
||||
BlockPhysics decoBlocks = chunkSectionRef != null ? chunkStore.getComponent(chunkSectionRef, BlockPhysics.getComponentType()) : null;
|
||||
boolean isDeco = decoBlocks != null && decoBlocks.isDeco(targetBlockPos.x, targetBlockPos.y, targetBlockPos.z);
|
||||
if (isDeco) {
|
||||
itemId = null;
|
||||
dropListId = null;
|
||||
}
|
||||
}
|
||||
|
||||
TimeResource timeResource = entityStore.getResource(TimeResource.getResourceType());
|
||||
BlockHealthChunk blockHealthComponent = chunkStore.getComponent(chunkReference, BlockHealthModule.get().getBlockHealthChunkComponentType());
|
||||
|
||||
assert blockHealthComponent != null;
|
||||
|
||||
float current = blockHealthComponent.getBlockHealth(originBlock);
|
||||
DamageBlockEvent event = new DamageBlockEvent(itemStack, originBlock, targetBlockType, current, damage);
|
||||
if (ref != null) {
|
||||
entityStore.invoke(ref, event);
|
||||
} else {
|
||||
entityStore.invoke(event);
|
||||
}
|
||||
|
||||
if (event.isCancelled()) {
|
||||
targetSection.invalidateBlock(targetBlockPos.x, targetBlockPos.y, targetBlockPos.z);
|
||||
return false;
|
||||
} else {
|
||||
damage = event.getDamage();
|
||||
targetBlockType = event.getBlockType();
|
||||
targetBlockPos = event.getTargetBlock();
|
||||
targetSection = blockChunkComponent.getSectionAtBlockY(targetBlockPos.y);
|
||||
targetRotationIndex = targetSection.getRotationIndex(targetBlockPos.x, targetBlockPos.y, targetBlockPos.z);
|
||||
targetBlockType.getBlockCenter(targetRotationIndex, targetBlockCenterPos);
|
||||
targetBlockCenterPos.add(targetBlockPos);
|
||||
BlockHealth blockDamage = blockHealthComponent.damageBlock(timeResource.getNow(), world, targetBlockPos, damage);
|
||||
if (blockHealthComponent.isBlockFragile(targetBlockPos) || blockDamage.isDestroyed()) {
|
||||
BlockGathering.BlockToolData requiredTool = blockGathering.getToolData().get(toolId);
|
||||
boolean toolsMatch = requiredTool != null;
|
||||
if (!toolsMatch) {
|
||||
performBlockBreak(
|
||||
world,
|
||||
targetBlockPos,
|
||||
targetBlockType,
|
||||
itemStack,
|
||||
dropQuantity,
|
||||
itemId,
|
||||
dropListId,
|
||||
setBlockSettings,
|
||||
ref,
|
||||
chunkReference,
|
||||
entityStore,
|
||||
chunkStore
|
||||
);
|
||||
brokeBlock = true;
|
||||
} else {
|
||||
String toolStateId = requiredTool.getStateId();
|
||||
BlockType newBlockType = toolStateId != null ? targetBlockType.getBlockForState(toolStateId) : null;
|
||||
boolean shouldChangeState = newBlockType != null && !targetBlockType.getId().equals(newBlockType.getId());
|
||||
if (shouldChangeState) {
|
||||
blockDamage.setHealth(1.0F);
|
||||
worldChunkComponent.setBlock(targetBlockPos.x, targetBlockPos.y, targetBlockPos.z, newBlockType);
|
||||
if ((setBlockSettings & 1024) == 0) {
|
||||
BlockSoundSet soundSet = BlockSoundSet.getAssetMap().getAsset(targetBlockType.getBlockSoundSetIndex());
|
||||
if (soundSet != null) {
|
||||
int soundEventIndexx = soundSet.getSoundEventIndices().getOrDefault(BlockSoundEvent.Break, 0);
|
||||
if (soundEventIndexx != 0) {
|
||||
SoundUtil.playSoundEvent3d(soundEventIndexx, SoundCategory.SFX, targetBlockCenterPos, entityStore);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((setBlockSettings & 2048) == 0) {
|
||||
List<ItemStack> itemStacks = getDrops(targetBlockType, 1, requiredTool.getItemId(), requiredTool.getDropListId());
|
||||
Vector3d dropPosition = new Vector3d(targetBlockPos.x + 0.5, targetBlockPos.y, targetBlockPos.z + 0.5);
|
||||
Holder<EntityStore>[] itemEntityHolders = ItemComponent.generateItemDrops(entityStore, itemStacks, dropPosition, Vector3f.ZERO);
|
||||
entityStore.addEntities(itemEntityHolders, AddReason.SPAWN);
|
||||
}
|
||||
} else {
|
||||
performBlockBreak(
|
||||
world,
|
||||
targetBlockPos,
|
||||
targetBlockType,
|
||||
itemStack,
|
||||
dropQuantity,
|
||||
itemId,
|
||||
dropListId,
|
||||
setBlockSettings | 2048,
|
||||
ref,
|
||||
chunkReference,
|
||||
entityStore,
|
||||
chunkStore
|
||||
);
|
||||
brokeBlock = true;
|
||||
if ((setBlockSettings & 2048) == 0) {
|
||||
List<ItemStack> toolDrops = getDrops(targetBlockType, 1, requiredTool.getItemId(), requiredTool.getDropListId());
|
||||
if (!toolDrops.isEmpty()) {
|
||||
Vector3d dropPosition = new Vector3d(targetBlockPos.x + 0.5, targetBlockPos.y, targetBlockPos.z + 0.5);
|
||||
Holder<EntityStore>[] itemEntityHolders = ItemComponent.generateItemDrops(
|
||||
entityStore, toolDrops, dropPosition, Vector3f.ZERO
|
||||
);
|
||||
entityStore.addEntities(itemEntityHolders, AddReason.SPAWN);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if ((setBlockSettings & 1024) == 0) {
|
||||
BlockSoundSet soundSet = BlockSoundSet.getAssetMap().getAsset(targetBlockType.getBlockSoundSetIndex());
|
||||
if (soundSet != null) {
|
||||
int soundEventIndexx = soundSet.getSoundEventIndices().getOrDefault(BlockSoundEvent.Hit, 0);
|
||||
if (soundEventIndexx != 0) {
|
||||
SoundUtil.playSoundEvent3d(soundEventIndexx, SoundCategory.SFX, targetBlockCenterPos, entityStore);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ref != null && entity != null) {
|
||||
if ((setBlockSettings & 1024) == 0 && !targetBlockCenterPos.equals(Vector3d.MAX)) {
|
||||
int hitSoundEventLayerIndex = 0;
|
||||
if (itemToolSpec != null) {
|
||||
hitSoundEventLayerIndex = itemToolSpec.getHitSoundLayerIndex();
|
||||
}
|
||||
|
||||
if (hitSoundEventLayerIndex == 0 && heldItem != null && heldItem.getTool() != null) {
|
||||
hitSoundEventLayerIndex = heldItem.getTool().getHitSoundLayerIndex();
|
||||
}
|
||||
|
||||
if (hitSoundEventLayerIndex != 0) {
|
||||
SoundUtil.playSoundEvent3d(
|
||||
ref,
|
||||
hitSoundEventLayerIndex,
|
||||
targetBlockCenterPos.getX(),
|
||||
targetBlockCenterPos.getY(),
|
||||
targetBlockCenterPos.getZ(),
|
||||
entityStore
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (itemToolSpec != null && itemToolSpec.isIncorrect()) {
|
||||
GatheringEffectsConfig incorrectToolConfig = gameplayConfig.getGatheringConfig().getIncorrectToolConfig();
|
||||
if (incorrectToolConfig != null) {
|
||||
if ((setBlockSettings & 4) == 0) {
|
||||
String particleSystemId = incorrectToolConfig.getParticleSystemId();
|
||||
if (particleSystemId != null) {
|
||||
ObjectList<Ref<EntityStore>> results = SpatialResource.getThreadLocalReferenceList();
|
||||
playerSpatialResource.getSpatialStructure().collect(targetBlockCenterPos, 75.0, results);
|
||||
ParticleUtil.spawnParticleEffect(particleSystemId, targetBlockCenterPos, results, entityStore);
|
||||
}
|
||||
}
|
||||
|
||||
if ((setBlockSettings & 1024) == 0) {
|
||||
int soundEventIndexx = incorrectToolConfig.getSoundEventIndex();
|
||||
if (soundEventIndexx != 0) {
|
||||
SoundUtil.playSoundEvent3d(ref, soundEventIndexx, targetBlockCenterPos, entityStore);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (entity != null
|
||||
&& ref != null
|
||||
&& entity.canDecreaseItemStackDurability(ref, entityStore)
|
||||
&& itemStack != null
|
||||
&& !itemStack.isUnbreakable()) {
|
||||
byte activeHotbarSlot = entity.getInventory().getActiveHotbarSlot();
|
||||
if (activeHotbarSlot != -1) {
|
||||
double durability = calculateDurabilityUse(heldItem, targetBlockType);
|
||||
ItemContainer hotbar = entity.getInventory().getHotbar();
|
||||
entity.updateItemStackDurability(ref, itemStack, hotbar, activeHotbarSlot, -durability, entityStore);
|
||||
}
|
||||
}
|
||||
|
||||
return brokeBlock;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void performBlockBreak(
|
||||
@Nullable Ref<EntityStore> ref,
|
||||
@Nullable ItemStack heldItemStack,
|
||||
@Nonnull Vector3i targetBlock,
|
||||
@Nonnull Ref<ChunkStore> chunkReference,
|
||||
@Nonnull ComponentAccessor<EntityStore> entityStore,
|
||||
@Nonnull ComponentAccessor<ChunkStore> chunkStore
|
||||
) {
|
||||
performBlockBreak(ref, heldItemStack, targetBlock, 0, chunkReference, entityStore, chunkStore);
|
||||
}
|
||||
|
||||
public static void performBlockBreak(
|
||||
@Nullable Ref<EntityStore> ref,
|
||||
@Nullable ItemStack heldItemStack,
|
||||
@Nonnull Vector3i targetBlock,
|
||||
int setBlockSettings,
|
||||
@Nonnull Ref<ChunkStore> chunkReference,
|
||||
@Nonnull ComponentAccessor<EntityStore> entityStore,
|
||||
@Nonnull ComponentAccessor<ChunkStore> chunkStore
|
||||
) {
|
||||
World world = chunkStore.getExternalData().getWorld();
|
||||
int targetBlockX = targetBlock.getX();
|
||||
int targetBlockY = targetBlock.getY();
|
||||
int targetBlockZ = targetBlock.getZ();
|
||||
WorldChunk worldChunkComponent = chunkStore.getComponent(chunkReference, WorldChunk.getComponentType());
|
||||
|
||||
assert worldChunkComponent != null;
|
||||
|
||||
int targetBlockTypeIndex = worldChunkComponent.getBlock(targetBlockX, targetBlockY, targetBlockZ);
|
||||
BlockType targetBlockTypeAsset = BlockType.getAssetMap().getAsset(targetBlockTypeIndex);
|
||||
if (targetBlockTypeAsset != null) {
|
||||
Vector3i affectedBlock = targetBlock;
|
||||
if (!targetBlockTypeAsset.isUnknown()) {
|
||||
BlockChunk blockChunkComponent = chunkStore.getComponent(chunkReference, BlockChunk.getComponentType());
|
||||
|
||||
assert blockChunkComponent != null;
|
||||
|
||||
BlockSection targetBlockSection = blockChunkComponent.getSectionAtBlockY(targetBlockY);
|
||||
int filler = targetBlockSection.getFiller(targetBlockX, targetBlockY, targetBlockZ);
|
||||
int fillerX = FillerBlockUtil.unpackX(filler);
|
||||
int fillerY = FillerBlockUtil.unpackY(filler);
|
||||
int fillerZ = FillerBlockUtil.unpackZ(filler);
|
||||
if (fillerX != 0 || fillerY != 0 || fillerZ != 0) {
|
||||
affectedBlock = targetBlock.clone().subtract(fillerX, fillerY, fillerZ);
|
||||
BlockType originBlock = world.getBlockType(affectedBlock);
|
||||
if (originBlock != null && !targetBlockTypeAsset.getId().equals(originBlock.getId())) {
|
||||
world.breakBlock(targetBlockX, targetBlockY, targetBlockZ, setBlockSettings);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
performBlockBreak(
|
||||
world, affectedBlock, targetBlockTypeAsset, heldItemStack, 0, null, null, setBlockSettings, ref, chunkReference, entityStore, chunkStore
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public static void performBlockBreak(
|
||||
@Nonnull World world,
|
||||
@Nonnull Vector3i blockPosition,
|
||||
@Nonnull BlockType targetBlockTypeKey,
|
||||
@Nullable ItemStack heldItemStack,
|
||||
int dropQuantity,
|
||||
@Nullable String dropItemId,
|
||||
@Nullable String dropListId,
|
||||
int setBlockSettings,
|
||||
@Nullable Ref<EntityStore> ref,
|
||||
@Nonnull Ref<ChunkStore> chunkReference,
|
||||
@Nonnull ComponentAccessor<EntityStore> entityStore,
|
||||
@Nonnull ComponentAccessor<ChunkStore> chunkStore
|
||||
) {
|
||||
Vector3i targetBlockPosition = blockPosition;
|
||||
Ref<ChunkStore> targetChunkReference = chunkReference;
|
||||
ComponentAccessor<ChunkStore> targetChunkStore = chunkStore;
|
||||
if (ref != null) {
|
||||
BreakBlockEvent event = new BreakBlockEvent(heldItemStack, blockPosition, targetBlockTypeKey);
|
||||
entityStore.invoke(ref, event);
|
||||
if (event.isCancelled()) {
|
||||
BlockChunk blockChunkComponent = chunkStore.getComponent(chunkReference, BlockChunk.getComponentType());
|
||||
|
||||
assert blockChunkComponent != null;
|
||||
|
||||
BlockSection blockSection = blockChunkComponent.getSectionAtBlockY(blockPosition.getY());
|
||||
blockSection.invalidateBlock(blockPosition.getX(), blockPosition.getY(), blockPosition.getZ());
|
||||
return;
|
||||
}
|
||||
|
||||
targetBlockPosition = event.getTargetBlock();
|
||||
targetChunkStore = world.getChunkStore().getStore();
|
||||
long chunkIndex = ChunkUtil.indexChunkFromBlock(targetBlockPosition.x, targetBlockPosition.z);
|
||||
targetChunkReference = targetChunkStore.getExternalData().getChunkReference(chunkIndex);
|
||||
if (targetChunkReference == null || !targetChunkReference.isValid()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!targetBlockPosition.equals(blockPosition) || !world.equals(world)) {
|
||||
BlockChunk blockChunkComponent = chunkStore.getComponent(chunkReference, BlockChunk.getComponentType());
|
||||
|
||||
assert blockChunkComponent != null;
|
||||
|
||||
BlockSection blockSection = blockChunkComponent.getSectionAtBlockY(blockPosition.getY());
|
||||
blockSection.invalidateBlock(blockPosition.getX(), blockPosition.getY(), blockPosition.getZ());
|
||||
}
|
||||
|
||||
int x = blockPosition.getX();
|
||||
int y = blockPosition.getY();
|
||||
int z = blockPosition.getZ();
|
||||
BlockChunk blockChunkComponent = chunkStore.getComponent(targetChunkReference, BlockChunk.getComponentType());
|
||||
|
||||
assert blockChunkComponent != null;
|
||||
|
||||
BlockSection blockSection = blockChunkComponent.getSectionAtBlockY(y);
|
||||
int filler = blockSection.getFiller(x, y, z);
|
||||
int blockTypeIndex = blockSection.get(x, y, z);
|
||||
BlockType blockTypeAsset = BlockType.getAssetMap().getAsset(blockTypeIndex);
|
||||
boolean isNaturalBlockBreak = BlockInteractionUtils.isNaturalAction(ref, entityStore);
|
||||
setBlockSettings |= 256;
|
||||
if (!isNaturalBlockBreak) {
|
||||
setBlockSettings |= 2048;
|
||||
}
|
||||
|
||||
naturallyRemoveBlock(
|
||||
targetBlockPosition,
|
||||
blockTypeAsset,
|
||||
filler,
|
||||
dropQuantity,
|
||||
dropItemId,
|
||||
dropListId,
|
||||
setBlockSettings,
|
||||
targetChunkReference,
|
||||
entityStore,
|
||||
targetChunkStore
|
||||
);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static void naturallyRemoveBlockByPhysics(
|
||||
@Nonnull Vector3i blockPosition,
|
||||
@Nonnull BlockType blockType,
|
||||
int filler,
|
||||
int setBlockSettings,
|
||||
@Nonnull Ref<ChunkStore> chunkReference,
|
||||
@Nonnull ComponentAccessor<EntityStore> entityStore,
|
||||
@Nonnull ComponentAccessor<ChunkStore> chunkStore
|
||||
) {
|
||||
int quantity = 1;
|
||||
String itemId = null;
|
||||
String dropListId = null;
|
||||
BlockGathering blockGathering = blockType.getGathering();
|
||||
if (blockGathering != null) {
|
||||
PhysicsDropType physics = blockGathering.getPhysics();
|
||||
BlockBreakingDropType breaking = blockGathering.getBreaking();
|
||||
SoftBlockDropType soft = blockGathering.getSoft();
|
||||
HarvestingDropType harvest = blockGathering.getHarvest();
|
||||
if (physics != null) {
|
||||
itemId = physics.getItemId();
|
||||
dropListId = physics.getDropListId();
|
||||
} else if (breaking != null) {
|
||||
quantity = breaking.getQuantity();
|
||||
itemId = breaking.getItemId();
|
||||
dropListId = breaking.getDropListId();
|
||||
} else if (soft != null) {
|
||||
itemId = soft.getItemId();
|
||||
dropListId = soft.getDropListId();
|
||||
} else if (harvest != null) {
|
||||
itemId = harvest.getItemId();
|
||||
dropListId = harvest.getDropListId();
|
||||
}
|
||||
}
|
||||
|
||||
setBlockSettings |= 32;
|
||||
naturallyRemoveBlock(blockPosition, blockType, filler, quantity, itemId, dropListId, setBlockSettings, chunkReference, entityStore, chunkStore);
|
||||
}
|
||||
|
||||
public static void naturallyRemoveBlock(
|
||||
@Nonnull Vector3i blockPosition,
|
||||
@Nullable BlockType blockType,
|
||||
int filler,
|
||||
int quantity,
|
||||
String itemId,
|
||||
String dropListId,
|
||||
int setBlockSettings,
|
||||
@Nonnull Ref<ChunkStore> chunkReference,
|
||||
@Nonnull ComponentAccessor<EntityStore> entityStore,
|
||||
@Nonnull ComponentAccessor<ChunkStore> chunkStore
|
||||
) {
|
||||
if (blockType != null) {
|
||||
WorldChunk worldChunkComponent = chunkStore.getComponent(chunkReference, WorldChunk.getComponentType());
|
||||
|
||||
assert worldChunkComponent != null;
|
||||
|
||||
BlockChunk blockChunkComponent = chunkStore.getComponent(chunkReference, BlockChunk.getComponentType());
|
||||
|
||||
assert blockChunkComponent != null;
|
||||
|
||||
Vector3i affectedBlock = blockPosition;
|
||||
if (!blockType.isUnknown()) {
|
||||
int fillerX = FillerBlockUtil.unpackX(filler);
|
||||
int fillerY = FillerBlockUtil.unpackY(filler);
|
||||
int fillerZ = FillerBlockUtil.unpackZ(filler);
|
||||
if (fillerX != 0 || fillerY != 0 || fillerZ != 0) {
|
||||
affectedBlock = blockPosition.clone().subtract(fillerX, fillerY, fillerZ);
|
||||
String oldBlockTypeKey = blockType.getId();
|
||||
blockType = worldChunkComponent.getBlockType(affectedBlock.getX(), affectedBlock.getY(), affectedBlock.getZ());
|
||||
if (blockType == null) {
|
||||
throw new IllegalStateException("Null block type fetched for " + affectedBlock + " during block break");
|
||||
}
|
||||
|
||||
if (!oldBlockTypeKey.equals(blockType.getId())) {
|
||||
worldChunkComponent.breakBlock(blockPosition.getX(), blockPosition.getY(), blockPosition.getZ(), setBlockSettings);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((setBlockSettings & 1024) == 0) {
|
||||
BlockSoundSet soundSet = BlockSoundSet.getAssetMap().getAsset(blockType.getBlockSoundSetIndex());
|
||||
if (soundSet != null) {
|
||||
int soundEventIndex = soundSet.getSoundEventIndices().getOrDefault(BlockSoundEvent.Break, 0);
|
||||
if (soundEventIndex != 0) {
|
||||
BlockSection section = blockChunkComponent.getSectionAtBlockY(blockPosition.getY());
|
||||
int rotationIndex = section.getRotationIndex(blockPosition.getX(), blockPosition.getY(), blockPosition.getZ());
|
||||
Vector3d centerPosition = new Vector3d();
|
||||
blockType.getBlockCenter(rotationIndex, centerPosition);
|
||||
centerPosition.add(blockPosition);
|
||||
SoundUtil.playSoundEvent3d(soundEventIndex, SoundCategory.SFX, centerPosition, entityStore);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
removeBlock(affectedBlock, blockType, setBlockSettings, chunkReference, chunkStore);
|
||||
if ((setBlockSettings & 2048) == 0 && quantity > 0) {
|
||||
Vector3d dropPosition = blockPosition.toVector3d().add(0.5, 0.0, 0.5);
|
||||
List<ItemStack> itemStacks = getDrops(blockType, quantity, itemId, dropListId);
|
||||
Holder<EntityStore>[] itemEntityHolders = ItemComponent.generateItemDrops(entityStore, itemStacks, dropPosition, Vector3f.ZERO);
|
||||
entityStore.addEntities(itemEntityHolders, AddReason.SPAWN);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean shouldPickupByInteraction(@Nullable BlockType blockType) {
|
||||
return blockType != null && blockType.getGathering() != null && blockType.getGathering().isHarvestable();
|
||||
}
|
||||
|
||||
public static void performPickupByInteraction(
|
||||
@Nonnull Ref<EntityStore> ref,
|
||||
@Nonnull Vector3i targetBlock,
|
||||
@Nonnull BlockType blockType,
|
||||
int filler,
|
||||
@Nonnull Ref<ChunkStore> chunkReference,
|
||||
@Nonnull ComponentAccessor<EntityStore> entityStore,
|
||||
@Nonnull ComponentAccessor<ChunkStore> chunkStore
|
||||
) {
|
||||
// Fire GatherBlockEvent before proceeding - allows cancellation
|
||||
GatherBlockEvent gatherEvent = new GatherBlockEvent(targetBlock, blockType);
|
||||
entityStore.invoke(ref, gatherEvent);
|
||||
if (gatherEvent.isCancelled()) {
|
||||
// Invalidate block to sync client state
|
||||
BlockChunk blockChunkComponent = chunkStore.getComponent(chunkReference, BlockChunk.getComponentType());
|
||||
if (blockChunkComponent != null) {
|
||||
BlockSection section = blockChunkComponent.getSectionAtBlockY(targetBlock.getY());
|
||||
section.invalidateBlock(targetBlock.getX(), targetBlock.getY(), targetBlock.getZ());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
WorldChunk worldChunkComponent = chunkStore.getComponent(chunkReference, WorldChunk.getComponentType());
|
||||
|
||||
assert worldChunkComponent != null;
|
||||
|
||||
BlockChunk blockChunkComponent = chunkStore.getComponent(chunkReference, BlockChunk.getComponentType());
|
||||
|
||||
assert blockChunkComponent != null;
|
||||
|
||||
Vector3i affectedBlock = targetBlock;
|
||||
if (!blockType.isUnknown()) {
|
||||
int fillerX = FillerBlockUtil.unpackX(filler);
|
||||
int fillerY = FillerBlockUtil.unpackY(filler);
|
||||
int fillerZ = FillerBlockUtil.unpackZ(filler);
|
||||
if (fillerX != 0 || fillerY != 0 || fillerZ != 0) {
|
||||
affectedBlock = targetBlock.clone().subtract(fillerX, fillerY, fillerZ);
|
||||
String oldBlockTypeKey = blockType.getId();
|
||||
blockType = worldChunkComponent.getBlockType(affectedBlock.getX(), affectedBlock.getY(), affectedBlock.getZ());
|
||||
if (blockType == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!oldBlockTypeKey.equals(blockType.getId())) {
|
||||
worldChunkComponent.breakBlock(targetBlock.getX(), targetBlock.getY(), targetBlock.getZ());
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BlockSection section = blockChunkComponent.getSectionAtBlockY(targetBlock.getY());
|
||||
Vector3d centerPosition = new Vector3d();
|
||||
int rotationIndex = section.getRotationIndex(targetBlock.getX(), targetBlock.getY(), targetBlock.getZ());
|
||||
blockType.getBlockCenter(rotationIndex, centerPosition);
|
||||
centerPosition.add(targetBlock);
|
||||
int setBlockSettings = 0;
|
||||
setBlockSettings |= 256;
|
||||
if (!BlockInteractionUtils.isNaturalAction(ref, entityStore)) {
|
||||
setBlockSettings |= 2048;
|
||||
}
|
||||
|
||||
removeBlock(affectedBlock, blockType, setBlockSettings, chunkReference, chunkStore);
|
||||
HarvestingDropType harvest = blockType.getGathering().getHarvest();
|
||||
String itemId = harvest.getItemId();
|
||||
String dropListId = harvest.getDropListId();
|
||||
|
||||
for (ItemStack itemStack : getDrops(blockType, 1, itemId, dropListId)) {
|
||||
ItemUtils.interactivelyPickupItem(ref, itemStack, centerPosition, entityStore);
|
||||
}
|
||||
|
||||
if ((setBlockSettings & 1024) == 0) {
|
||||
BlockSoundSet soundSet = BlockSoundSet.getAssetMap().getAsset(blockType.getBlockSoundSetIndex());
|
||||
if (soundSet != null) {
|
||||
int soundEventIndex = soundSet.getSoundEventIndices().getOrDefault(BlockSoundEvent.Harvest, 0);
|
||||
if (soundEventIndex != 0) {
|
||||
SoundUtil.playSoundEvent3d(soundEventIndex, SoundCategory.SFX, centerPosition, entityStore);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected static void removeBlock(
|
||||
@Nonnull Vector3i blockPosition,
|
||||
@Nonnull BlockType blockType,
|
||||
int setBlockSettings,
|
||||
@Nonnull Ref<ChunkStore> chunkReference,
|
||||
@Nonnull ComponentAccessor<ChunkStore> chunkStore
|
||||
) {
|
||||
World world = chunkStore.getExternalData().getWorld();
|
||||
ComponentType<ChunkStore, BlockHealthChunk> blockHealthComponentType = BlockHealthModule.get().getBlockHealthChunkComponentType();
|
||||
BlockHealthChunk blockHealthComponent = chunkStore.getComponent(chunkReference, blockHealthComponentType);
|
||||
|
||||
assert blockHealthComponent != null;
|
||||
|
||||
blockHealthComponent.removeBlock(world, blockPosition);
|
||||
WorldChunk worldChunkComponent = chunkStore.getComponent(chunkReference, WorldChunk.getComponentType());
|
||||
|
||||
assert worldChunkComponent != null;
|
||||
|
||||
BlockChunk blockChunkComponent = chunkStore.getComponent(chunkReference, BlockChunk.getComponentType());
|
||||
|
||||
assert blockChunkComponent != null;
|
||||
|
||||
worldChunkComponent.breakBlock(blockPosition.getX(), blockPosition.getY(), blockPosition.getZ(), setBlockSettings);
|
||||
if ((setBlockSettings & 256) != 0) {
|
||||
BlockSection section = blockChunkComponent.getSectionAtBlockY(blockPosition.y);
|
||||
int rotationIndex = section.getRotationIndex(blockPosition.x, blockPosition.y, blockPosition.z);
|
||||
BlockBoundingBoxes hitBoxType = BlockBoundingBoxes.getAssetMap().getAsset(blockType.getHitboxTypeIndex());
|
||||
if (hitBoxType != null) {
|
||||
FillerBlockUtil.forEachFillerBlock(
|
||||
hitBoxType.get(rotationIndex),
|
||||
(x, y, z) -> world.performBlockUpdate(blockPosition.getX() + x, blockPosition.getY() + y, blockPosition.getZ() + z, false)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ConnectedBlocksUtil.setConnectedBlockAndNotifyNeighbors(
|
||||
BlockType.getAssetMap().getIndex("Empty"), RotationTuple.NONE, Vector3i.ZERO, blockPosition, worldChunkComponent, blockChunkComponent
|
||||
);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static List<ItemStack> getDrops(@Nonnull BlockType blockType, int quantity, @Nullable String itemId, @Nullable String dropListId) {
|
||||
if (dropListId == null && itemId == null) {
|
||||
Item item = blockType.getItem();
|
||||
return item == null ? ObjectLists.emptyList() : ObjectLists.singleton(new ItemStack(item.getId(), quantity));
|
||||
} else {
|
||||
List<ItemStack> randomItemDrops = new ObjectArrayList<>();
|
||||
if (dropListId != null) {
|
||||
ItemModule itemModule = ItemModule.get();
|
||||
if (itemModule.isEnabled()) {
|
||||
for (int i = 0; i < quantity; i++) {
|
||||
List<ItemStack> randomItemsToDrop = itemModule.getRandomItemDrops(dropListId);
|
||||
randomItemDrops.addAll(randomItemsToDrop);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (itemId != null) {
|
||||
randomItemDrops.add(new ItemStack(itemId, quantity));
|
||||
}
|
||||
|
||||
return randomItemDrops;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user