translation complete but not tested

This commit is contained in:
ForestOfLight
2025-12-12 16:38:26 -08:00
Unverified
parent 50f542220d
commit dcc9704078
15 changed files with 168 additions and 89 deletions
+22 -10
View File
@@ -16,29 +16,41 @@ class BlockInfo {
static showStructureBlockInfo(player) {
const block = Raycaster.getTargetedStructureBlock(player, { isFirst: true, collideWithWorldBlocks: true, useActiveLayer: true });
if (!block && this.shownToLastTick.has(player.id)) {
player.onScreenDisplay.setActionBar({ text: 'Structure:\n§7None' });
player.onScreenDisplay.setActionBar({ rawtext: [
{ translate: 'construct.blockinfo.header' },
{ text: '\n' },
{ translate: 'construct.blockinfo.none' }
]});
this.shownToLastTick.delete(player.id);
}
if (!block)
return;
player.onScreenDisplay.setActionBar({ text: this.getFormattedBlockInfo(player, block.permutation) });
player.onScreenDisplay.setActionBar(this.getFormattedBlockInfo(player, block.permutation));
this.shownToLastTick.add(player.id);
}
static getFormattedBlockInfo(player, block) {
return 'Structure:' + this.getSupplyMessage(player, block) + '\n' + this.getBlockMessage(block);
return { rawtext: [
{ translate: 'construct.blockinfo.header' },
this.getSupplyMessage(player, block),
{ text: '\n' },
this.getBlockMessage(block)
] };
}
static getBlockMessage(block) {
if (!block)
return '§7Unknown';
let output = `§a${block.type.id}`;
return { translate: 'construct.blockinfo.unknown' };
const message = { rawtext: [{ text: '§a' }, { translate: block.type.id }]};
const states = block.getAllStates();
if (Object.keys(states).length > 0)
output += `\n§7${this.getFormattedStates(states)}`;
message.rawtext.push({ text: `\n§7${this.getFormattedStates(states)}` });
if (block.isWaterlogged)
output += `\n§7isWaterlogged: §3true`;
return output;
message.rawtext.push({ rawtext: [
{ text: '\n§7' },
{ translate: 'construct.blockinfo.waterlogged' }
]});
return message;
}
static getFormattedStates(states) {
@@ -49,8 +61,8 @@ class BlockInfo {
const itemStack = fetchMatchingItemSlot(player, block.getItemStack()?.typeId);
const isInSurvival = player.getGameMode() === GameMode.Survival;
if (!itemStack && isInSurvival)
return ' §c[No Supply]';
return '';
return { translate: 'construct.blockinfo.nosupply' };
return { text: '' };
}
}
@@ -68,14 +68,14 @@ export class InstanceFormBuilder {
form.body({ translate: 'construct.instance.materials.noinventory' });
return form;
}
bodyText.rawtext.push({ translate: 'construct.instance.materials.missing' });
bodyText.rawtext.push({ translate: 'construct.instance.materials.missing.header' });
if (instance.hasLayerSelected())
bodyText.rawtext.push({ translate: 'construct.instance.materials.layer', with: [String(instance.getLayer())] });
bodyText.rawtext.push({ text: `§f\n\n` });
bodyText.rawtext.push(materials.formatString(materials.getMaterialsDifference(inventoryContainer)));
buttonText = "construct.instance.materials.all.button";
} else {
bodyText.rawtext.push({ translate: `construct.instance.materials.all` });
bodyText.rawtext.push({ translate: `construct.instance.materials.all.header` });
if (instance.hasLayerSelected())
bodyText.rawtext.push({ translate: 'construct.instance.materials.layer', with: [String(instance.getLayer())] });
bodyText.rawtext.push({ text: `§f\n\n` });
@@ -17,7 +17,7 @@ export class MaterialGrabberForm {
const selectedInstanceName = structureCollection.getInstanceNames()[response.selection];
if (selectedInstanceName) {
this.setActiveInstance(selectedInstanceName);
this.player.sendMessage(`§7Selected instance for material grabber: §2${selectedInstanceName}`);
this.player.sendMessage({ translate: 'construct.materials.grabber.menu.success' });
return;
}
});
@@ -10,12 +10,13 @@ export class MaterialGrabberFormBuilder {
const allInstanceNameForm = new ActionFormData()
.title(this.menuTitle);
const currInstanceName = Builders.get(player.id).materialInstanceName;
let body = '§7Current instance: ';
const body = { rawtext: [{ translate: 'construct.materials.grabber.menu.header' }] };
if (currInstanceName)
body += `§2${currInstanceName}`;
body.rawtext.push({ text: `§2${currInstanceName}` });
else
body += '§7None';
body += '\n§7Select an instance:';
body.rawtext.push({ translate: 'construct.materials.grabber.menu.noinstance' });
body.rawtext.push({ text: '\n' });
body.rawtext.push({ translate: 'construct.materials.grabber.menu.selectinstance' });
allInstanceNameForm.body(body);
structureCollection.getInstanceNames().forEach(instanceName => {
allInstanceNameForm.button(`§2${instanceName}`);
+2 -2
View File
@@ -63,11 +63,11 @@ export class MenuForm {
structureCollection.add(instanceName, structureId);
} catch (e) {
if (e.name === 'InvalidInstanceError') {
this.player.sendMessage(`§cInstance '${instanceName}' already exists. Try again with a new name.`);
this.player.sendMessage({ translate: 'construct.mainmenu.instance.exists', with: [instanceName] });
return void 0;
}
if (e.name === 'InvalidStructureError') {
this.player.sendMessage(`§cStructure ID '${structureId}' not found. If you're looking for a structure that you put in the structures folder, please restart your world and try again.`);
this.player.sendMessage({ translate: 'construct.mainmenu.instance.notfound', with: [structureId] });
return void 0;
}
throw e;
+20 -18
View File
@@ -2,56 +2,58 @@ import { ActionFormData, ModalFormData } from '@minecraft/server-ui';
import { structureCollection } from './Structure/StructureCollection';
export class MenuFormBuilder {
static menuTitle = '§l§2Construct';
static menuTitle = { translate: 'construct.mainmenu.title' };
static buildAllInstanceName() {
const allInstanceNameForm = new ActionFormData()
.title(this.menuTitle)
.body('Select an instance:');
allInstanceNameForm.button('Builder Settings');
.body({ translate: 'construct.mainmenu.selectinstance' });
allInstanceNameForm.button({ translate: 'construct.mainmenu.settings' });
structureCollection.getInstanceNames().forEach(instanceName => {
allInstanceNameForm.button(`${structureCollection.get(instanceName).isEnabled() ? '§2' : '§c'}${instanceName}`);
});
allInstanceNameForm.button('Create New Instance');
allInstanceNameForm.button({ translate: 'construct.mainmenu.newinstance' });
return allInstanceNameForm;
}
static buildNewInstance() {
return new ModalFormData()
.title(this.menuTitle)
.textField('Enter a name for the new instance:', 'example_instance')
.submitButton('Submit');
.textField({ translate: 'construct.mainmenu.newinstance.prompt' }, { translate: 'construct.mainmenu.newinstance.placeholder' })
.submitButton({ translate: 'construct.menu.submit' });
}
static buildAllStructures() {
const allStructuresForm = new ActionFormData()
.title(this.menuTitle)
.body('Select a structure:');
.body({ translate: construct.mainmenu.selectstructure.header });
structureCollection.getWorldStructureIds().forEach(structureId => {
const structureName = structureId.replace('mystructure:', '');
allStructuresForm.button(`§2${structureName}`);
});
allStructuresForm.button('Other');
allStructuresForm.button('How to Add/Remove Structures');
allStructuresForm.button({ translate: 'construct.mainmenu.selectstructure.other' });
allStructuresForm.button({ translate: 'construct.mainmenu.selectstructure.howto' });
return allStructuresForm;
}
static buildOtherStructure() {
return new ModalFormData()
.title(this.menuTitle)
.textField('Enter the Structure ID:', 'example_structure')
.submitButton('Submit');
.textField({ translate: 'construct.mainmenu.selectstructure.other.prompt' }, { translate: 'construct.mainmenu.selectstructure.other.placeholder' })
.submitButton({ translate: 'construct.menu.submit' });
}
static buildHowTo() {
let body = "§aHow to Add Structures:\n"
body += "§7- Save a structure using a §fstructure block§7 or the §f/structure§7 command.\n"
body += "§7§lOR§r\n"
body += "§7- Add a §f.mcstructure§7 file to this pack's §fstructures folder§7. When selecting your structure, select the §fOther§7 option and then use the filename (without '.mcstructure') as the §fStructure ID§7. After its first use, it will be added to the list of structures.";
body += "\n\n§cHow to Remove Structures:\n"
body += "§7- Use the §f/structure delete§7 command to remove a structure from the world.\n"
const message = { rawtext: [
{ translate: 'construct.mainmenu.selectstructure.howto.add.header' }, { text: '\n' },
{ translate: 'construct.mainmenu.selectstructure.howto.add.structureblock' }, { text: '\n' },
{ translate: 'construct.mainmenu.selectstructure.howto.add.or' }, { text: '\n' },
{ translate: 'construct.mainmenu.selectstructure.howto.add.mcstructure' }, { text: '\n' },
{ text: '\n' }, { translate: 'construct.mainmenu.selectstructure.howto.remove.header' }, { text: '\n' },
{ translate: 'construct.mainmenu.selectstructure.howto.remove.body' }, { text: '\n' },
] };
return new ActionFormData()
.title(this.menuTitle)
.body(body);
.body(message);
}
}
@@ -43,18 +43,22 @@ export class StructureStatistics {
}
getMessage() {
let message = '';
message += `§fStatistics for §a${this.instance.getName()}§f:`;
const message = { rawtext: [] };
message.rawtext.push({ translate: 'construct.structure.statistics.header', with: [this.instance.getName()] });
if (this.instance.hasLayerSelected())
message += ` §7(layer ${this.instance.getLayer()})`;
message += `\n§7Blocks: §2${this.getNonAirBlocks()}\n`;
message.rawtext.push({ translate: 'construct.instance.materials.layer', with: [String(instance.getLayer())] });
message.rawtext.push({ rawtext: [
{ text: '\n' },
{ translate: 'construct.structure.statistics.blocks', with: [String(this.getNonAirBlocks())] },
{ text: '\n' }
]});
const skipped = this.getSkipped();
if (skipped > 0)
message += `§c[!] This analysis skipped ${skipped} blocks.\n`;
message += `§7Correct: §a${this.formatStat(this.getStat(BlockVerificationLevel.Match))}\n`;
message += `§7Block State Incorrect: §e${this.formatStat(this.getStat(BlockVerificationLevel.TypeMatch))}\n`;
message += `§7Incorrect: §c${this.formatStat(this.getStat(BlockVerificationLevel.NoMatch))}\n`;
message += `§7Missing: §3${this.formatStat(this.getStat(BlockVerificationLevel.Missing))}\n`;
message.rawtext.push({ rawtext: [{ translate: 'construct.structure.statistics.skipped', with: [String(skipped)] }, { text: '\n' }] });
message.rawtext.push({ rawtext: [{ translate: 'construct.structure.statistics.correct', with: [this.formatStat(this.getStat(BlockVerificationLevel.Match))] }, { text: '\n' }] });
message.rawtext.push({ rawtext: [{ translate: 'construct.structure.statistics.stateincorrect', with: [this.formatStat(this.getStat(BlockVerificationLevel.TypeMatch))] }, { text: '\n' }] });
message.rawtext.push({ rawtext: [{ translate: 'construct.structure.statistics.incorrect', with: [this.formatStat(this.getStat(BlockVerificationLevel.NoMatch))] }, { text: '\n' }] });
message.rawtext.push({ rawtext: [{ translate: 'construct.structure.statistics.missing', with: [this.formatStat(this.getStat(BlockVerificationLevel.Missing))] }, { text: '\n' }] });
return message;
}
+5 -5
View File
@@ -9,7 +9,7 @@ export const MENU_ITEM = 'construct:menu';
const menuCmd = new Command({
name: 'construct',
description: { text: 'Opens the Construct menu.' },
description: { translate: 'construct.commands.construct' },
usage: 'construct',
callback: (sender) => openMenu(sender)
});
@@ -18,7 +18,7 @@ extension.addCommand(menuCmd);
system.beforeEvents.startup.subscribe((event) => {
const command = {
name: 'construct:item',
description: 'Gives you the Construct item. Use it to open the Construct menu.',
description: 'construct.commands.item',
permissionLevel: CommandPermissionLevel.Any,
cheatsRequired: false
};
@@ -28,13 +28,13 @@ system.beforeEvents.startup.subscribe((event) => {
function givePlayerConstructItem(origin) {
const player = origin.sourceEntity;
if (player instanceof Player === false)
return { status: CustomCommandStatus.Failure, message: 'This command can only be used by players.' };
return { status: CustomCommandStatus.Failure, message: 'construct.commands.item.denyorigin' };
system.run(() => {
const givenItemStack = player.getComponent(EntityComponentTypes.Inventory)?.container?.addItem(new ItemStack(MENU_ITEM));
if (givenItemStack)
player.sendMessage('§cFailed to give you the Construct item.');
player.sendMessage({ translate: 'construct.commands.item.fail' });
else
player.sendMessage('§aYou recieved the Construct item! Use it to open the Construct menu.');
player.sendMessage({ translate: 'construct.commands.item.success' });
});
return { status: CustomCommandStatus.Success };
}
+5 -6
View File
@@ -1,16 +1,15 @@
import { BuilderOption } from '../classes/Builder/BuilderOption';
import { BlockPermutation, EntityComponentTypes, EquipmentSlot, GameMode, ItemStack, system, world } from '@minecraft/server';
import { structureCollection } from '../classes/Structure/StructureCollection';
import { bannedBlocks, bannedToValidBlockMap, whitelistedBlockStates, resetToBlockStates, bannedDimensionBlocks,
blockIdToItemStackMap } from '../data';
import { bannedBlocks, bannedToValidBlockMap, whitelistedBlockStates, resetToBlockStates, bannedDimensionBlocks, blockIdToItemStackMap } from '../data';
import { fetchMatchingItemSlot, placeBlock } from '../utils';
import { Builders } from '../classes/Builder/Builders';
const builderOption = new BuilderOption({
identifier: 'easyPlace',
displayName: 'Easy Place',
description: 'Always place the correct structure block.',
howToUse: "Hold the Easy Place item in your offhand and place blocks in a structure to have them be corrected automatically.",
displayName: { translate: 'construct.option.easyplace.name' },
description: { translate: 'construct.option.easyplace.description' },
howToUse: { translate: 'construct.option.easyplace.howto' },
onEnableCallback: (playerId) => giveActionItem(playerId),
onDisableCallback: (playerId) => removeActionItem(playerId)
});
@@ -83,7 +82,7 @@ function shouldPreventAction(player, structureBlock) {
function preventAction(event, player) {
event.cancel = true;
system.run(() => {
player.onScreenDisplay.setActionBar('§cAction prevented by Easy Place.');
player.onScreenDisplay.setActionBar({ translate: 'construct.option.easyplace.actionprevented' });
});
}
+5 -5
View File
@@ -8,15 +8,15 @@ import { Builders } from '../classes/Builder/Builders';
import { Vector } from '../lib/Vector';
const locationsPlacedLastTick = new Set();
const PLAYER_COLLISION_BOX = { width: 0.6, height: 1.8 };
const ACTION_ITEM = 'construct:easy_place';
const PLAYER_COLLISION_BOX = { width: 0.6, height: 1.8 };
const runnerByPlayer = {};
const builderOption = new BuilderOption({
identifier: 'fastEasyPlace',
displayName: 'Fast Easy Place',
description: 'Place correct structure blocks just by clicking on them.',
howToUse: "Hold the Easy Place item in your main hand and use it on missing blocks in a structure to place them.",
displayName: { translate: 'construct.option.fasteasyplace.name' },
description: { translate: 'construct.option.fasteasyplace.description' },
howToUse: { translate: 'construct.option.fasteasyplace.howto' },
onEnableCallback: (playerId) => giveActionItem(playerId),
onDisableCallback: (playerId) => removeActionItem(playerId)
});
@@ -99,7 +99,7 @@ function processEasyPlace(player) {
function preventAction(event, player) {
event.cancel = true;
system.run(() => {
player.onScreenDisplay.setActionBar('§cAction prevented by Easy Place.');
player.onScreenDisplay.setActionBar({ translate: 'construct.option.easyplace.actionprevented' });
});
}
+9 -10
View File
@@ -6,9 +6,9 @@ import { structureCollection } from '../classes/Structure/StructureCollection';
const builderOption = new BuilderOption({
identifier: 'materialGrabber',
displayName: 'Material Grabber',
description: 'Pulls structure items from inventories.',
howToUse: "Interact with inventories using the Material Grabber item to pull structure items from them.",
displayName: { translate: 'construct.option.materialgrabber.name' },
description: { translate: 'construct.option.materialgrabber.description' },
howToUse: { translate: 'construct.option.materialgrabber.howto' },
onEnableCallback: (playerId) => giveActionItem(playerId),
onDisableCallback: (playerId) => removeActionItem(playerId)
});
@@ -113,13 +113,12 @@ function ignoreAlreadyGathered(materials, playerContainer) {
}
function sendTransferMessage(player, transferCount) {
if (transferCount === 0) {
player.onScreenDisplay.setActionBar('§7Grabbed 0 items.');
} else if (transferCount === 1) {
player.onScreenDisplay.setActionBar('§aGrabbed 1 item.');
} else {
player.onScreenDisplay.setActionBar(`§aGrabbed ${transferCount} item(s).`);
}
if (transferCount === 0)
player.onScreenDisplay.setActionBar({ translate: 'construct.option.materialgrabber.grabbed.zero' });
else if (transferCount === 1)
player.onScreenDisplay.setActionBar({ translate: 'construct.option.materialgrabber.grabbed.one' });
else
player.onScreenDisplay.setActionBar({ translate: 'construct.option.materialgrabber.grabbed.many', with: [String(transferCount)] });
}
function tryTransferToPlayer(slot, playerContainer, materials) {
+1 -1
View File
@@ -8,7 +8,7 @@ export async function forceShow(player, form, timeout = Infinity) {
while ((system.currentTick - startTick) < timeout) {
const response = await form.show(player);
if (startTick + 1 === system.currentTick && response.cancelationReason === FormCancelationReason.UserBusy)
player.sendMessage({ translate: 'construct.menu.open.closeChat' });
player.sendMessage({ translate: 'construct.menu.open.closechat' });
if (response.cancelationReason !== FormCancelationReason.UserBusy)
return response;
}