Merge branch 'easyPlace' into dev
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -31,6 +31,11 @@ Vector.rejection = function rejection(a, b) { return Vector.subtract(a, Vector.p
|
||||
Vector.reflect = function reflect(v, n) { return Vector.subtract(v, Vector.multiply(n, 2 * Vector.dot(v, n))); }
|
||||
Vector.lerp = function lerp(a, b, t) { return Vector.multiply(a, 1 - t).add(Vector.multiply(b, t)); }
|
||||
Vector.distance = function distance(a, b) { return Vector.magnitude(Vector.subtract(a, b)); }
|
||||
Vector.intersect = function intersect(maxA, minA, maxB, minB) {
|
||||
return (maxA.x >= minB.x && minA.x <= maxB.x) &&
|
||||
(maxA.y >= minB.y && minA.y <= maxB.y) &&
|
||||
(maxA.z >= minB.z && minA.z <= maxB.z);
|
||||
}
|
||||
Vector.from = function from(object) {
|
||||
if (Vector.isVec3(object)) return object;
|
||||
if (Array.isArray(object)) return new Vector(object[0], object[1], object[2]);
|
||||
|
||||
@@ -19,7 +19,8 @@ function giveActionItem(playerId) {
|
||||
const player = world.getEntity(playerId);
|
||||
const container = player.getComponent(EntityComponentTypes.Inventory)?.container;
|
||||
const itemStack = new ItemStack('construct:easy_place');
|
||||
if (!container.contains(itemStack)) {
|
||||
const offhandItemStack = player.getComponent(EntityComponentTypes.Equippable).getEquipment(EquipmentSlot.Offhand);
|
||||
if (!container.contains(itemStack) && offhandItemStack?.typeId !== 'construct:easy_place') {
|
||||
const remainingItemStack = container.addItem(itemStack);
|
||||
if (remainingItemStack)
|
||||
player.dimension.spawnItem(remainingItemStack, player.location);
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
import { BuilderOption } from '../classes/Builder/BuilderOption';
|
||||
import { BlockPermutation, EntityComponentTypes, EquipmentSlot, GameMode, InputMode, ItemStack, system, world } from '@minecraft/server';
|
||||
import { BlockPermutation, EntityComponentTypes, EquipmentSlot, GameMode, ItemStack, system, world } from '@minecraft/server';
|
||||
import { bannedBlocks, bannedToValidBlockMap, whitelistedBlockStates, resetToBlockStates, bannedDimensionBlocks,
|
||||
blockIdToItemStackMap } from '../data';
|
||||
import { placeBlock } from '../utils';
|
||||
import { placeBlock, fetchMatchingItemSlot } from '../utils';
|
||||
import { Raycaster } from '../classes/Raycaster';
|
||||
import { Builders } from '../classes/Builder/Builders';
|
||||
import { Vector } from '../lib/Vector';
|
||||
|
||||
const PROCESS_INTERVAL = 2; // Fast Easy Place will attempt to place twice when at an interval of 1.
|
||||
const locationsPlacedLastTick = new Set();
|
||||
const PLAYER_COLLISION_BOX = { width: 0.6, height: 1.8 };
|
||||
|
||||
const builderOption = new BuilderOption({
|
||||
identifier: 'fastEasyPlace',
|
||||
@@ -21,7 +23,8 @@ function giveActionItem(playerId) {
|
||||
const player = world.getEntity(playerId);
|
||||
const container = player.getComponent(EntityComponentTypes.Inventory)?.container;
|
||||
const itemStack = new ItemStack('construct:easy_place');
|
||||
if (!container.contains(itemStack)) {
|
||||
const offhandItemStack = player.getComponent(EntityComponentTypes.Equippable).getEquipment(EquipmentSlot.Offhand);
|
||||
if (!container.contains(itemStack) && offhandItemStack?.typeId !== 'construct:easy_place') {
|
||||
const remainingItemStack = container.addItem(itemStack);
|
||||
if (remainingItemStack)
|
||||
player.dimension.spawnItem(remainingItemStack, player.location);
|
||||
@@ -46,7 +49,7 @@ function removeActionItem(playerId) {
|
||||
}
|
||||
}
|
||||
|
||||
system.runInterval(onTick, PROCESS_INTERVAL);
|
||||
system.runInterval(onTick);
|
||||
world.beforeEvents.playerInteractWithBlock.subscribe(onPlayerInteractWithBlock);
|
||||
|
||||
function onTick() {
|
||||
@@ -68,6 +71,12 @@ function processEasyPlace(player) {
|
||||
if (!structureBlock)
|
||||
return;
|
||||
const worldBlock = player.dimension.getBlock(structureBlock.location);
|
||||
if (locationsPlacedLastTick.has(JSON.stringify(worldBlock.location)))
|
||||
return;
|
||||
locationsPlacedLastTick.add(JSON.stringify(worldBlock.location));
|
||||
system.runTimeout(() => {
|
||||
locationsPlacedLastTick.delete(JSON.stringify(worldBlock.location));
|
||||
}, 2);
|
||||
tryPlaceBlock(player, worldBlock, structureBlock.permutation);
|
||||
}
|
||||
|
||||
@@ -86,7 +95,7 @@ function isHoldingActionItem(player) {
|
||||
}
|
||||
|
||||
function tryPlaceBlock(player, worldBlock, structureBlock) {
|
||||
if (isBannedBlock(player, structureBlock) || !locationIsPlaceable(worldBlock)) return;
|
||||
if (isBannedBlock(player, structureBlock) || !locationIsPlaceable(player, worldBlock)) return;
|
||||
structureBlock = tryConvertBannedToValidBlock(structureBlock);
|
||||
if (player.getGameMode() === GameMode.Creative) {
|
||||
placeBlock(player, worldBlock, structureBlock);
|
||||
@@ -96,8 +105,8 @@ function tryPlaceBlock(player, worldBlock, structureBlock) {
|
||||
}
|
||||
}
|
||||
|
||||
function locationIsPlaceable(worldBlock) {
|
||||
return worldBlock.isAir || worldBlock.isLiquid;
|
||||
function locationIsPlaceable(player, worldBlock) {
|
||||
return (worldBlock.isAir || worldBlock.isLiquid) && !isBlockInsidePlayer(player, worldBlock);
|
||||
}
|
||||
|
||||
function isBannedBlock(player, structureBlock) {
|
||||
@@ -149,15 +158,12 @@ function getPlaceableItemStack(structureBlock) {
|
||||
return newItemId ? new ItemStack(newItemId) : structureBlock.getItemStack();
|
||||
}
|
||||
|
||||
function fetchMatchingItemSlot(player, itemToMatchId) {
|
||||
if (!itemToMatchId)
|
||||
return void 0;
|
||||
const inventory = player.getComponent(EntityComponentTypes.Inventory)?.container;
|
||||
if (!inventory)
|
||||
return void 0;
|
||||
for (let index = 0; index < inventory.size; index++) {
|
||||
const itemSlot = inventory.getSlot(index);
|
||||
if (itemSlot.hasItem() && itemSlot?.typeId === itemToMatchId)
|
||||
return itemSlot;
|
||||
}
|
||||
function isBlockInsidePlayer(player, worldBlock) {
|
||||
const playerLocation = Vector.from(player.location);
|
||||
const blockLocation = Vector.from(worldBlock.location);
|
||||
const playerMin = playerLocation.subtract({ x: PLAYER_COLLISION_BOX.width / 2, y: -0.1, z: PLAYER_COLLISION_BOX.width / 2 });
|
||||
const playerMax = playerLocation.add({ x: PLAYER_COLLISION_BOX.width / 2, y: PLAYER_COLLISION_BOX.height, z: PLAYER_COLLISION_BOX.width / 2 });
|
||||
const blockMin = blockLocation;
|
||||
const blockMax = blockLocation.add({ x: 1, y: 1, z: 1 });
|
||||
return Vector.intersect(playerMax, playerMin, blockMax, blockMin);
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
import { system, EntityComponentTypes, LiquidType } from '@minecraft/server';
|
||||
import { FormCancelationReason } from '@minecraft/server-ui';
|
||||
import { specialItemPlacementConversions } from './data';
|
||||
import { blocks } from './blocks';
|
||||
import { blocks, block_sounds } from './blocks';
|
||||
|
||||
export async function forceShow(player, form, timeout = Infinity) {
|
||||
const startTick = system.currentTick;
|
||||
@@ -21,11 +21,15 @@ export function fetchMatchingItemSlot(entity, itemToMatchId) {
|
||||
const inventory = entity.getComponent(EntityComponentTypes.Inventory)?.container;
|
||||
if (!inventory)
|
||||
return void 0;
|
||||
let smallestItemSlot;
|
||||
for (let index = 0; index < inventory.size; index++) {
|
||||
const itemSlot = inventory.getSlot(index);
|
||||
if (itemSlot.hasItem() && itemSlot?.typeId === itemToMatchId)
|
||||
return itemSlot;
|
||||
if (itemSlot.hasItem() && itemSlot?.typeId === itemToMatchId) {
|
||||
if (!smallestItemSlot || itemSlot.amount < smallestItemSlot.amount)
|
||||
smallestItemSlot = itemSlot;
|
||||
}
|
||||
}
|
||||
return smallestItemSlot;
|
||||
}
|
||||
|
||||
export function placeBlock(player, placedBlock, blockToPlace, itemSlotToConsume = void 0) {
|
||||
@@ -58,10 +62,7 @@ function playBlockPlacementSound(player, block, structureBlock) {
|
||||
const blockId = structureBlock.type.id.replace('minecraft:', '');
|
||||
const blockData = blocks[blockId];
|
||||
let blockSound = blockData['sound'] || 'stone';
|
||||
if (['glass', 'terracotta'].includes(blockSound))
|
||||
blockSound = 'stone';
|
||||
let blockSoundId = 'dig.' + blockSound;
|
||||
if (['iron', 'calcite'].includes(blockSound))
|
||||
blockSoundId = 'place.' + blockSound;
|
||||
let blockSoundId = block_sounds[blockSound].events.place?.sound
|
||||
|| block_sounds[block_sounds[blockSound].base].events.place?.sound;
|
||||
player.dimension.playSound(blockSoundId, block.location);
|
||||
}
|
||||
Reference in New Issue
Block a user