Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add pack name setting, fix structure file extraction for completed packs #21

Merged
merged 2 commits into from
Nov 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 38 additions & 18 deletions HoloPrint.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export async function makePack(structureFiles, config = {}, resourcePackStack, p
console.info("Finished reading structure NBTs!");
console.log("NBTs:", nbts);
let structureSizes = nbts.map(nbt => nbt["size"].map(x => +x)); // Stored as Number instances: https://github.com/Offroaders123/NBTify/issues/50
let structureNames = structureFiles.map(structureFile => structureFile.name.replace(/(\.holoprint)?\.[^.]+$/, ""));
let packName = config.PACK_NAME ?? getDefaultPackName(structureFiles);

// Make the pack
let loadedStuff = await loadStuff({
Expand Down Expand Up @@ -667,9 +667,9 @@ export async function makePack(structureFiles, config = {}, resourcePackStack, p
}
})));
hudScreenUI["material_list"]["size"][1] = finalisedMaterialList.length * 12 + 12; // 12px for each item + 12px for the heading
hudScreenUI["material_list_heading"]["controls"][1]["pack_name"]["text"] += structureNames.join(", ");
hudScreenUI["material_list_heading"]["controls"][1]["pack_name"]["text"] += packName;

manifest["header"]["name"] = `§uHoloPrint:§r ${structureNames.join(", ")}`;
manifest["header"]["name"] = packName;
manifest["header"]["description"] = `§u★HoloPrint§r resource pack generated on §o${(new Date()).toLocaleString()}§r\nDeveloped by §l§6SuperLlama88888§r`;
if(config.AUTHORS.length) {
manifest["header"]["description"] += `\nStructure made by ${config.AUTHORS.join(" and ")}`;
Expand All @@ -688,10 +688,14 @@ export async function makePack(structureFiles, config = {}, resourcePackStack, p

let pack = new JSZip();
if(structureFiles.length == 1) {
pack.file(".mcstructure", structureFiles[0]);
pack.file(".mcstructure", structureFiles[0], {
comment: structureFiles[0].name
});
} else {
structureFiles.forEach((structureFile, i) => {
pack.file(`${i}.mcstructure`, structureFile);
pack.file(`${i}.mcstructure`, structureFile, {
comment: structureFile.name
});
});
}
pack.file("manifest.json", JSON.stringify(manifest));
Expand Down Expand Up @@ -734,21 +738,23 @@ export async function makePack(structureFiles, config = {}, resourcePackStack, p
});
}

return new File([zippedPack], `${structureNames.join("+")}.holoprint.mcpack`);
return new File([zippedPack], `${packName}.holoprint.mcpack`);
}
/**
* Retrieves the structure file from a completed HoloPrint resource pack
* Retrieves the structure files from a completed HoloPrint resource pack.
* @param {File} resourcePack HoloPrint resource pack (`*.mcpack)
* @returns {Promise<File>}
* @returns {Promise<Array<File>>}
*/
export async function extractStructureFileFromPack(resourcePack) {
export async function extractStructureFilesFromPack(resourcePack) {
let packFolder = await JSZip.loadAsync(resourcePack);
let structureBlob = await packFolder.file(".mcstructure")?.async("blob");
if(!structureBlob) {
return undefined;
}
let structureZipObjects = Object.values(packFolder.files).filter(file => file.name.endsWith(".mcstructure"));
let structureBlobs = await Promise.all(structureZipObjects.map(async zipObject => await zipObject.async("blob")));
let packName = resourcePack.name.slice(0, resourcePack.name.indexOf("."));
return new File([structureBlob], `${packName}.mcstructure`);
if(structureBlobs.length == 1) {
return [new File([structureBlobs[0]], structureZipObjects[0].comment ?? `${packName}.mcstructure`)];
} else {
return await Promise.all(structureBlobs.map(async (structureBlob, i) => new File([structureBlob], structureZipObjects[i].comment ?? `${packName}_${i}.mcstructure`)));
}
}
/**
* Updates a HoloPrint resource pack by remaking it.
Expand All @@ -759,11 +765,23 @@ export async function extractStructureFileFromPack(resourcePack) {
* @returns {Promise<File>}
*/
export async function updatePack(resourcePack, config, resourcePackStack, previewCont) {
let structureFile = extractStructureFileFromPack(resourcePack);
if(!structureFile) {
throw new Error(`No structure file found inside resource pack ${resourcePack.name}; cannot update pack!`);
let structureFiles = extractStructureFilesFromPack(resourcePack);
if(!structureFiles) {
throw new Error(`No structure files found inside resource pack ${resourcePack.name}; cannot update pack!`);
}
return await makePack(structureFiles, config, resourcePackStack, previewCont);
}
/**
* Returns the default pack name that would be used if no pack name is specified.
* @param {Array<File>} structureFiles
* @returns {String}
*/
export function getDefaultPackName(structureFiles) {
let defaultName = structureFiles.map(structureFile => structureFile.name.replace(/(\.holoprint)?\.[^.]+$/, "")).join(", ");
if(defaultName.length > 40) {
defaultName = `${defaultName.slice(0, 19)}...${defaultName.slice(-19)}`
}
return await makePack(structureFile, config, resourcePackStack, previewCont);
return defaultName;
}

/**
Expand Down Expand Up @@ -791,6 +809,7 @@ function addDefaultConfig(config) {
SPAWN_ANIMATION_LENGTH: 0.4, // in seconds
WRONG_BLOCK_OVERLAY_COLOR: [1, 0, 0, 0.3],
MATERIAL_LIST_LANGUAGE: "en_US",
PACK_NAME: undefined,
PACK_ICON_BLOB: undefined,
AUTHORS: [],
DESCRIPTION: undefined,
Expand Down Expand Up @@ -1266,6 +1285,7 @@ function stringifyWithFixedDecimals(value) {
* @property {Number} SPAWN_ANIMATION_LENGTH Length of each individual block's spawn animation (seconds)
* @property {Array<Number>} WRONG_BLOCK_OVERLAY_COLOR Clamped colour quartet
* @property {String} MATERIAL_LIST_LANGUAGE The language code, as appearing in `texts/languages.json`
* @property {String|undefined} PACK_NAME The name of the completed pack; will default to the structure file names
* @property {Blob} PACK_ICON_BLOB Blob for `pack_icon.png`
* @property {Array<String>} AUTHORS
* @property {String|undefined} DESCRIPTION
Expand Down
3 changes: 3 additions & 0 deletions index.css
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,9 @@ input[type="number"], input[type="text"], textarea {
outline-width: thin;
accent-color: auto;
}
input[type="text"]::placeholder {
text-overflow: ellipsis;
}
button:not(:disabled):hover, input[type="file"]:not(:disabled):hover::file-selector-button, select:not(:disabled):hover, .buttonlike:hover {
background: #E8C8E8;
}
Expand Down
1 change: 1 addition & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ <h1>HoloPrint</h1>
<label for="metadataTab" class="buttonlike">Metadata</label>
<fieldset>
<legend>Metadata</legend>
<label>Pack name: <code><input type="text" name="packName"/></code></label>
<label>Pack icon (<code>*.png</code>): <input type="file" accept=".png" name="packIcon"/></label>
<label>Structure author: <input type="text" placeholder="MinecraftLover123" name="author"/></label>
<label>Description:<br/><textarea placeholder="This is my epic house!" rows="3" cols="20" name="description"></textarea></label>
Expand Down
22 changes: 10 additions & 12 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ let dropFileNotice;
let generatePackForm;
let generatePackFormSubmitButton;
let structureFilesInput;
let packNameInput;
let logger;

let supabaseLogger;
Expand All @@ -47,6 +48,8 @@ document.onEvent("DOMContentLoaded", async () => {
generatePackForm = selectEl("#generatePackForm");
dropFileNotice = selectEl("#dropFileNotice");
structureFilesInput = generatePackForm.elements.namedItem("structureFiles");
packNameInput = generatePackForm.elements.namedItem("packName");
structureFilesInput.onEventAndNow("input", updatePackNameInputPlaceholder);

if(location.search == "?loadFile") {
window.launchQueue?.setConsumer(async launchParams => {
Expand Down Expand Up @@ -142,26 +145,20 @@ async function handleInputFiles(files) {
let resourcePacks = files.filter(file => file.name.endsWith(".mcpack"));

for(let resourcePack of resourcePacks) {
let structureFile = await HoloPrint.extractStructureFileFromPack(resourcePack);
if(structureFile) {
structureFiles.push(structureFile);
}
let extractedStructureFiles = await HoloPrint.extractStructureFilesFromPack(resourcePack);
structureFiles.push(...extractedStructureFiles);
}
if(structureFiles.length) {
let dataTransfer = new DataTransfer();
[...structureFilesInput.files, ...structureFiles].forEach(structureFile => dataTransfer.items.add(structureFile));
structureFilesInput.files = dataTransfer.files;
}
updatePackNameInputPlaceholder();
}

async function handleLaunchFile(file) {
if(!file.name.endsWith(".mcstructure")) {
console.error(`File is not a structure file: ${file.name}`);
return;
}
let pack = await makePack([file]);
return pack;
function updatePackNameInputPlaceholder() {
packNameInput.setAttribute("placeholder", HoloPrint.getDefaultPackName([...structureFilesInput.files]));
}

async function temporarilyChangeText(el, text, duration = 2000) {
let originalText = el.innerText;
el.innerText = text;
Expand All @@ -188,6 +185,7 @@ async function makePack(structureFiles, localResourcePacks) {
TEXTURE_OUTLINE_ALPHA_DIFFERENCE_MODE: formData.get("textureOutlineAlphaDifferenceMode"),
DO_SPAWN_ANIMATION: formData.get("spawnAnimationEnabled"),
MATERIAL_LIST_LANGUAGE: formData.get("materialListLanguage"),
PACK_NAME: formData.get("packName") || undefined,
PACK_ICON_BLOB: formData.get("packIcon").size? formData.get("packIcon") : undefined,
AUTHORS: authors,
DESCRIPTION: formData.get("description") || undefined
Expand Down