Merge branch '1.21.90-support'

This commit is contained in:
ForestOfLight
2025-06-18 12:06:10 -07:00
Unverified
9 changed files with 70 additions and 79 deletions
+5 -5
View File
@@ -1,11 +1,11 @@
{ {
"format_version": 2, "format_version": 2,
"header": { "header": {
"name": "Construct [BP] v1.0.0", "name": "Construct [BP] v1.0.1",
"description": "Survival building addon by §aForestOfLight§r.", "description": "Survival building addon by §aForestOfLight§r.",
"uuid": "8c0c0153-d8b9-482a-889f-aef922b8fe58", "uuid": "8c0c0153-d8b9-482a-889f-aef922b8fe58",
"min_engine_version": [1, 21, 80], "min_engine_version": [1, 21, 90],
"version": [1, 0, 0] "version": [1, 0, 1]
}, },
"modules": [ "modules": [
{ {
@@ -26,11 +26,11 @@
"dependencies": [ "dependencies": [
{ {
"module_name": "@minecraft/server", "module_name": "@minecraft/server",
"version": "2.0.0-beta" "version": "2.1.0-beta"
}, },
{ {
"module_name": "@minecraft/server-ui", "module_name": "@minecraft/server-ui",
"version": "2.0.0-beta" "version": "2.1.0-beta"
}, },
{ {
"uuid": "375ec465-3dc1-429f-8b4c-a337889e1ed4", // Construct RP "uuid": "375ec465-3dc1-429f-8b4c-a337889e1ed4", // Construct RP
+13 -1
View File
@@ -2098,6 +2098,18 @@ export const blocks = {
"sound" : "stone", "sound" : "stone",
"textures" : "skull" "textures" : "skull"
}, },
"dried_ghast" : {
"carried_textures" : "dried_ghast_tentacles",
"sound" : "dried_ghast",
"textures" : {
"down" : "dried_ghast_bottom",
"east" : "dried_ghast_left",
"north" : "dried_ghast_back",
"south" : "dried_ghast_front",
"up" : "dried_ghast_top",
"west" : "dried_ghast_right"
}
},
"dried_kelp_block" : { "dried_kelp_block" : {
"carried_textures" : { "carried_textures" : {
"down" : "dried_kelp_block_top", "down" : "dried_kelp_block_top",
@@ -6338,4 +6350,4 @@ export const blocks = {
"sound" : "stone", "sound" : "stone",
"textures" : "skull" "textures" : "skull"
} }
} }
+1 -1
View File
@@ -45,7 +45,7 @@ class BlockInfo {
static getSupplyMessage(player, block) { static getSupplyMessage(player, block) {
const itemStack = fetchMatchingItemSlot(player, block.getItemStack()?.typeId); const itemStack = fetchMatchingItemSlot(player, block.getItemStack()?.typeId);
const isInSurvival = player.getGameMode() === GameMode.survival; const isInSurvival = player.getGameMode() === GameMode.Survival;
if (!itemStack && isInSurvival) if (!itemStack && isInSurvival)
return ' §c[No Supply]'; return ' §c[No Supply]';
return ''; return '';
+1 -1
View File
@@ -8,7 +8,7 @@ const ACTION_ITEM = 'construct:menu';
const menuCmd = new Command({ const menuCmd = new Command({
name: 'construct', name: 'construct',
description: { text: 'Gives you the Construct item. Use it to open the Construct menu.' }, description: { text: 'Opens the Construct menu.' },
usage: 'construct', usage: 'construct',
callback: (sender) => openMenu(sender) callback: (sender) => openMenu(sender)
}); });
+1 -1
View File
@@ -3,7 +3,7 @@ export const bannedBlocks = [
'wooden_door', 'spruce_door', 'birch_door', 'jungle_door', 'acacia_door', 'dark_oak_door', 'mangrove_door', 'cherry_door', 'pale_oak_door', 'wooden_door', 'spruce_door', 'birch_door', 'jungle_door', 'acacia_door', 'dark_oak_door', 'mangrove_door', 'cherry_door', 'pale_oak_door',
'bamboo_door', 'iron_door', 'crimson_door', 'warped_door', 'copper_door', 'exposed_copper_door', 'weathered_copper_door', 'oxidized_copper_door', 'bamboo_door', 'iron_door', 'crimson_door', 'warped_door', 'copper_door', 'exposed_copper_door', 'weathered_copper_door', 'oxidized_copper_door',
'waxed_copper_door', 'waxed_exposed_copper_door', 'waxed_weathered_copper_door', 'waxed_oxidized_copper_door', 'waxed_copper_door', 'waxed_exposed_copper_door', 'waxed_weathered_copper_door', 'waxed_oxidized_copper_door',
'seagrass', 'kelp' 'seagrass', 'kelp', 'dried_ghast'
]; ];
export const bannedDimensionBlocks = { export const bannedDimensionBlocks = {
+8 -31
View File
@@ -1,9 +1,9 @@
import { BuilderOption } from '../classes/Builder/BuilderOption'; import { BuilderOption } from '../classes/Builder/BuilderOption';
import { BlockPermutation, EntityComponentTypes, EquipmentSlot, GameMode, ItemStack, system, world } from '@minecraft/server'; import { BlockPermutation, EntityComponentTypes, EquipmentSlot, GameMode, ItemStack, system, world } from '@minecraft/server';
import { structureCollection } from '../classes/Structure/StructureCollection'; import { structureCollection } from '../classes/Structure/StructureCollection';
import { bannedBlocks, bannedToValidBlockMap, whitelistedBlockStates, resetToBlockStates, bannedDimensionBlocks, specialItemPlacementConversions, import { bannedBlocks, bannedToValidBlockMap, whitelistedBlockStates, resetToBlockStates, bannedDimensionBlocks,
blockIdToItemStackMap } from '../data'; blockIdToItemStackMap } from '../data';
import { fetchMatchingItemSlot } from '../utils'; import { fetchMatchingItemSlot, placeBlock } from '../utils';
import { Builders } from '../classes/Builder/Builders'; import { Builders } from '../classes/Builder/Builders';
const builderOption = new BuilderOption({ const builderOption = new BuilderOption({
@@ -66,9 +66,10 @@ function tryPlaceBlock(event, player, block, structureBlock) {
if (shouldPreventAction(player, structureBlock)) if (shouldPreventAction(player, structureBlock))
return preventAction(event, player); return preventAction(event, player);
structureBlock = tryConvertBannedToValidBlock(structureBlock); structureBlock = tryConvertBannedToValidBlock(structureBlock);
if (player.getGameMode() === GameMode.creative) { if (player.getGameMode() === GameMode.Creative) {
placeBlock(block, structureBlock); event.cancel = true;
} else if (player.getGameMode() === GameMode.survival) { placeBlock(player, block, structureBlock);
} else if (player.getGameMode() === GameMode.Survival) {
structureBlock = tryConvertToDefaultState(structureBlock); structureBlock = tryConvertToDefaultState(structureBlock);
tryPlaceBlockSurvival(event, player, block, structureBlock); tryPlaceBlockSurvival(event, player, block, structureBlock);
} }
@@ -124,7 +125,7 @@ function tryPlaceBlockSurvival(event, player, block, structureBlock) {
const itemSlotToUse = fetchMatchingItemSlot(player, placeableItemStack?.typeId); const itemSlotToUse = fetchMatchingItemSlot(player, placeableItemStack?.typeId);
if (itemSlotToUse) { if (itemSlotToUse) {
event.cancel = true; event.cancel = true;
placeBlock(block, structureBlock, itemSlotToUse); placeBlock(player, block, structureBlock, itemSlotToUse);
} else { } else {
preventAction(event, player); preventAction(event, player);
} }
@@ -134,28 +135,4 @@ function getPlaceableItemStack(structureBlock) {
const blockId = structureBlock.type.id.replace('minecraft:', ''); const blockId = structureBlock.type.id.replace('minecraft:', '');
const newItemId = blockIdToItemStackMap[blockId]; const newItemId = blockIdToItemStackMap[blockId];
return newItemId ? new ItemStack(newItemId) : structureBlock.getItemStack(); return newItemId ? new ItemStack(newItemId) : structureBlock.getItemStack();
} }
function placeBlock(block, structureBlock, itemSlot) {
system.run(() => {
if (itemSlot) {
consumeItem(itemSlot);
}
block.setPermutation(structureBlock);
});
}
function consumeItem(itemSlot) {
if (specialItemPlacementConversions[itemSlot.typeId.replace('minecraft:', '')]) {
consumeSpecial(itemSlot);
} else {
if (itemSlot.amount === 1)
itemSlot.setItem(void 0);
else
itemSlot.amount--;
}
}
function consumeSpecial(itemSlot) {
itemSlot.setItem(new ItemStack(specialItemPlacementConversions[itemSlot.typeId.replace('minecraft:', '')]));
}
+5 -37
View File
@@ -1,10 +1,10 @@
import { BuilderOption } from '../classes/Builder/BuilderOption'; import { BuilderOption } from '../classes/Builder/BuilderOption';
import { BlockPermutation, EntityComponentTypes, EquipmentSlot, GameMode, InputMode, ItemStack, system, world } from '@minecraft/server'; import { BlockPermutation, EntityComponentTypes, EquipmentSlot, GameMode, InputMode, ItemStack, system, world } from '@minecraft/server';
import { bannedBlocks, bannedToValidBlockMap, whitelistedBlockStates, resetToBlockStates, bannedDimensionBlocks, specialItemPlacementConversions, import { bannedBlocks, bannedToValidBlockMap, whitelistedBlockStates, resetToBlockStates, bannedDimensionBlocks,
blockIdToItemStackMap } from '../data'; blockIdToItemStackMap } from '../data';
import { placeBlock } from '../utils';
import { Raycaster } from '../classes/Raycaster'; import { Raycaster } from '../classes/Raycaster';
import { Builders } from '../classes/Builder/Builders'; import { Builders } from '../classes/Builder/Builders';
import { blocks } from '../blocks';
const PROCESS_INTERVAL = 2; // Fast Easy Place will attempt to place twice when at an interval of 1. const PROCESS_INTERVAL = 2; // Fast Easy Place will attempt to place twice when at an interval of 1.
@@ -88,9 +88,9 @@ function isHoldingActionItem(player) {
function tryPlaceBlock(player, worldBlock, structureBlock) { function tryPlaceBlock(player, worldBlock, structureBlock) {
if (isBannedBlock(player, structureBlock) || !locationIsPlaceable(worldBlock)) return; if (isBannedBlock(player, structureBlock) || !locationIsPlaceable(worldBlock)) return;
structureBlock = tryConvertBannedToValidBlock(structureBlock); structureBlock = tryConvertBannedToValidBlock(structureBlock);
if (player.getGameMode() === GameMode.creative) { if (player.getGameMode() === GameMode.Creative) {
placeBlock(player, worldBlock, structureBlock); placeBlock(player, worldBlock, structureBlock);
} else if (player.getGameMode() === GameMode.survival) { } else if (player.getGameMode() === GameMode.Survival) {
structureBlock = tryConvertToDefaultState(structureBlock); structureBlock = tryConvertToDefaultState(structureBlock);
tryPlaceBlockSurvival(player, worldBlock, structureBlock); tryPlaceBlockSurvival(player, worldBlock, structureBlock);
} }
@@ -139,9 +139,8 @@ function tryConvertToDefaultState(structureBlock) {
function tryPlaceBlockSurvival(player, block, structureBlock) { function tryPlaceBlockSurvival(player, block, structureBlock) {
const placeableItemStack = getPlaceableItemStack(structureBlock); const placeableItemStack = getPlaceableItemStack(structureBlock);
const itemSlotToUse = fetchMatchingItemSlot(player, placeableItemStack?.typeId); const itemSlotToUse = fetchMatchingItemSlot(player, placeableItemStack?.typeId);
if (itemSlotToUse) { if (itemSlotToUse)
placeBlock(player, block, structureBlock, itemSlotToUse); placeBlock(player, block, structureBlock, itemSlotToUse);
}
} }
function getPlaceableItemStack(structureBlock) { function getPlaceableItemStack(structureBlock) {
@@ -161,35 +160,4 @@ function fetchMatchingItemSlot(player, itemToMatchId) {
if (itemSlot.hasItem() && itemSlot?.typeId === itemToMatchId) if (itemSlot.hasItem() && itemSlot?.typeId === itemToMatchId)
return itemSlot; return itemSlot;
} }
}
function placeBlock(player, block, structureBlock, itemSlot) {
system.run(() => {
if (itemSlot)
consumeItem(itemSlot);
block.setPermutation(structureBlock);
playSoundEffect(player, structureBlock);
});
}
function consumeItem(itemSlot) {
if (specialItemPlacementConversions[itemSlot.typeId.replace('minecraft:', '')]) {
consumeSpecial(itemSlot);
} else {
if (itemSlot.amount === 1)
itemSlot.setItem(void 0);
else
itemSlot.amount--;
}
}
function consumeSpecial(itemSlot) {
itemSlot.setItem(new ItemStack(specialItemPlacementConversions[itemSlot.typeId.replace('minecraft:', '')]));
}
function playSoundEffect(player, structureBlock) {
const blockId = structureBlock.type.id.replace('minecraft:', '');
const blockData = blocks[blockId];
const blockSound = blockData['sound'] || 'stone';
player.dimension.playSound('dig.' + blockSound, player.location);
} }
+34
View File
@@ -1,5 +1,7 @@
import { system, EntityComponentTypes } from '@minecraft/server'; import { system, EntityComponentTypes } from '@minecraft/server';
import { FormCancelationReason } from '@minecraft/server-ui'; import { FormCancelationReason } from '@minecraft/server-ui';
import { specialItemPlacementConversions } from './data';
import { blocks } from './blocks';
export async function forceShow(player, form, timeout = Infinity) { export async function forceShow(player, form, timeout = Infinity) {
const startTick = system.currentTick; const startTick = system.currentTick;
@@ -24,4 +26,36 @@ export function fetchMatchingItemSlot(entity, itemToMatchId) {
if (itemSlot.hasItem() && itemSlot?.typeId === itemToMatchId) if (itemSlot.hasItem() && itemSlot?.typeId === itemToMatchId)
return itemSlot; return itemSlot;
} }
}
export function placeBlock(player, placedBlock, blockToPlace, itemSlotToConsume = void 0) {
system.run(() => {
if (itemSlotToConsume)
consumeItem(itemSlotToConsume);
placedBlock.setPermutation(blockToPlace);
playBlockPlacementSound(player, placedBlock, blockToPlace);
});
}
function consumeItem(itemSlot) {
if (specialItemPlacementConversions[itemSlot.typeId.replace('minecraft:', '')]) {
itemSlot.setItem(new ItemStack(specialItemPlacementConversions[itemSlot.typeId.replace('minecraft:', '')]));
} else {
if (itemSlot.amount === 1)
itemSlot.setItem(void 0);
else
itemSlot.amount--;
}
}
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;
player.dimension.playSound(blockSoundId, block.location);
} }
+2 -2
View File
@@ -6,7 +6,7 @@
[![GitHub Downloads](https://img.shields.io/github/downloads/ForestOfLight/Construct/total?label=Github%20downloads&logo=github)](https://github.com/ForestOfLight/Construct/releases) [![GitHub Downloads](https://img.shields.io/github/downloads/ForestOfLight/Construct/total?label=Github%20downloads&logo=github)](https://github.com/ForestOfLight/Construct/releases)
[![Curseforge Downloads](https://cf.way2muchnoise.eu/full_1283139_downloads.svg)](https://www.curseforge.com/minecraft-bedrock/addons/construct) [![Curseforge Downloads](https://cf.way2muchnoise.eu/full_1283139_downloads.svg)](https://www.curseforge.com/minecraft-bedrock/addons/construct)
[![Minecraft - Version](https://img.shields.io/badge/Minecraft-v1.21.80_(Bedrock)-brightgreen)](https://feedback.minecraft.net/hc/en-us/sections/360001186971-Release-Changelogs) [![Minecraft - Version](https://img.shields.io/badge/Minecraft-v1.21.90_(Bedrock)-brightgreen)](https://feedback.minecraft.net/hc/en-us/sections/360001186971-Release-Changelogs)
[![Discord](https://badgen.net/discord/members/9KGche8fxm?icon=discord&label=Discord&list=what)](https://discord.gg/9KGche8fxm) [![Discord](https://badgen.net/discord/members/9KGche8fxm?icon=discord&label=Discord&list=what)](https://discord.gg/9KGche8fxm)
</div> </div>
@@ -56,7 +56,7 @@ Construct uses Minecraft's vanilla structure system so that you can easily creat
Gives you the Construct item. Use it to open the Construct menu. Gives you the Construct item. Use it to open the Construct menu.
**Usage: `./construct`** **Usage: `./construct`**
Shows the construct form. Only available while **Canopy** is installed. Shows the Construct menu. Only available while **Canopy** is installed.
## Join the Community ## Join the Community