···3434 return compressed;
3535}
36363737+function compressBytes(input) {
3838+ const compressed = pako.deflate(input);
3939+ const compressedBase64 = btoa(String.fromCharCode.apply(null, compressed));
4040+ return compressedBase64.replaceAll("=", "");
4141+}
4242+3743function decompressString(compressedBase64) {
3844 const compressed = Uint8Array.from(atob(compressedBase64), (c) =>
3945 c.charCodeAt(0)
···4349 return decompressedString;
4450}
45515252+function decompressStringNoBase64(compressed) {
5353+ compressed = Uint8Array.from(compressed, (c) =>
5454+ c.charCodeAt(0)
5555+ );
5656+ const decompressed = pako.inflate(compressed);
5757+ const decompressedString = new TextDecoder().decode(decompressed);
5858+ return decompressedString;
5959+}
6060+4661function decompressStringFromBytes(compressed) {
4762 const decompressed = pako.inflate(compressed);
4863 const decompressedString = new TextDecoder().decode(decompressed);
···6075 a.click();
6176 document.body.removeChild(a);
6277 URL.revokeObjectURL(url);
6363-}
7878+}
7979+64806581async function openAndLoadFileAsBytes() {
6682 return new Promise((resolve, reject) => {
6783 const input = document.createElement("input");
6884 input.type = "file";
6969- input.accept = ".izl";
8585+ // accept izl and izl2
8686+ input.accept = ".izl,.izl2";
7087 input.onchange = () => {
7188 const file = input.files[0];
7289 const reader = new FileReader();
···8299 input.click();
83100 });
84101}
102102+103103+async function fileToLevelData() {
104104+ return "=" + compressString(decompressStringFromBytes(await openAndLoadFileAsBytes())); // i hate this and want to fix it but its 4 am and i need to sleep. fuck text encoding
105105+}
106106+8510786108function cloneFromPlants(name, sun, screenshot) {
87109 name = name
+13
game/level/izombiecustommenu.js
···4747 buttonElement.setAttribute("value", "LOAD LEVEL");
4848 buttonElement.id = "btnNextLevel"; // not actually a next level button, but it's the same style
4949 buttonElement.style.top = "60%";
5050+ buttonElement.style.left = "calc(50% - 120px)";
5151+ let buttonElementUpload = document.createElement("input");
5252+ buttonElementUpload.setAttribute("type", "button");
5353+ buttonElementUpload.setAttribute("value", "SELECT FILE");
5454+ buttonElementUpload.id = "btnNextLevel"; // not actually a next level button, but it's the same style
5555+ buttonElementUpload.style.top = "60%";
5656+ buttonElementUpload.style.left = "calc(50% + 5px)";
5757+ buttonElementUpload.onclick = async function () {
5858+ let levelData = await fileToLevelData();
5959+ inputDataElement.value = levelData;
6060+ buttonElement.click();
6161+ }
6262+ $("dAll").appendChild(buttonElementUpload);
5063 buttonElement.onclick = function () {
5164 // store the input value and disable it, then make it say "Loading..."
5265 let levelData = inputDataElement.value;
+55-8
game/level/izombieleveleditor.js
···295295 $("dAll").appendChild(
296296 copyButtonElement
297297 );
298298- let buttonElement =
298298+ let closeButton =
299299 document.createElement("input");
300300- buttonElement.setAttribute(
300300+ closeButton.setAttribute(
301301 "type",
302302 "button"
303303 );
304304- buttonElement.setAttribute(
304304+ closeButton.setAttribute(
305305 "value",
306306 "EXIT"
307307 );
308308- buttonElement.id = "btnNextLevel"; // not actually a next level button, but it's the same style
309309- buttonElement.style.top = "60%";
310310- buttonElement.onclick = function () {
308308+ closeButton.id = "btnNextLevel"; // not actually a next level button, but it's the same style
309309+ closeButton.style.top = "60%";
310310+ closeButton.style.left = "calc(50% - 120px)"; // "calc(33.333% - 56.5px)";
311311+ closeButton.onclick = function () {
311312 $("dAll").style.zIndex = "";
312313 let oldLv = oS.Lvl;
313314 SelectModal(0);
···317318 );
318319 oS.Lvl = oldLv;
319320 };
320320- buttonElement.style.zIndex = "1000";
321321+ closeButton.style.zIndex = "1000";
322322+323323+ let uploadButton =
324324+ document.createElement("input");
325325+ uploadButton.setAttribute(
326326+ "type",
327327+ "button"
328328+ );
329329+ uploadButton.setAttribute(
330330+ "value",
331331+ "UPLOAD"
332332+ );
333333+ uploadButton.id = "btnNextLevel"; // not actually a next level button, but it's the same style
334334+ uploadButton.style.top = "60%";
335335+ uploadButton.style.left = "calc(50% - 56.5px)";
336336+ uploadButton.onclick = function () {
337337+ // nothing for now
338338+ };
339339+ uploadButton.style.zIndex = "1000";
340340+ uploadButton.style.display = "none"; // hide for now
341341+342342+ let downloadButton =
343343+ document.createElement("input");
344344+ downloadButton.setAttribute(
345345+ "type",
346346+ "button"
347347+ );
348348+ downloadButton.setAttribute(
349349+ "value",
350350+ "DOWNLOAD"
351351+ );
352352+ downloadButton.id = "btnNextLevel"; // not actually a next level button, but it's the same style
353353+ downloadButton.style.top = "60%";
354354+ downloadButton.style.left = "calc(50% + 5px)"; // "calc(66.666% - 56.5px)";
355355+ downloadButton.onclick = function () {
356356+ downloadBytesAsFile(
357357+ compressStringAsBytes(
358358+ tinyifyClone(
359359+ cloneFromPlants(l, f)
360360+ )
361361+ ), l + ".izl2"
362362+ )
363363+ };
364364+ downloadButton.style.zIndex = "1000";
365365+321366 // put in #dAll
322322- $("dAll").appendChild(buttonElement);
367367+ $("dAll").appendChild(closeButton);
368368+ $("dAll").appendChild(uploadButton);
369369+ $("dAll").appendChild(downloadButton);
323370 let coverElement =
324371 document.createElement("div");
325372 coverElement.style.position =