1import { Settings } from "./settings.js"; 2import { Elements } from "./elements.js"; 3import { NameButton, UsernameButton, Buttons, SetCurrentOpenedSave } from "./save.js"; 4 5export const ParticleContainer = document.getElementById("ParticleContainer"); 6export const PlaceholderContainer = document.getElementById("PlaceholderContainer"); 7 8export function Random(Max, Min) { 9 return Math.floor(Math.random() * (Max - Min + 1)) + Min; 10} 11 12export function IsMobile() { 13 const userAgent = navigator.userAgent.toLowerCase(); 14 return /android|webos|iphone|ipad|ipod|blackberry|windows phone|opera mini/i.test(userAgent); 15} 16 17export function Clear() { 18 SetCurrentOpenedSave(undefined); 19 20 ParticleContainer.innerHTML = ""; 21 NameButton.value = ""; 22 UsernameButton.value = ""; 23 24 Array.from(Buttons.getElementsByTagName("div")).forEach(Button => { 25 Button.setAttribute("disabled", false); 26 }); 27 Array.from(Buttons.getElementsByTagName("input")).forEach(Button => { 28 Button.disabled = false; 29 }); 30} 31 32export function Notify(Title, Message, MarkIcon) { 33 const Container = document.createElement("div"); 34 Container.style.position = "absolute"; 35 Container.style.left = "50%"; 36 Container.style.top = "50%"; 37 Container.style.transform = "translate(-50%, -50%)"; 38 Container.style.width = "75%"; 39 Container.style.height = "35%"; 40 Container.style.backgroundColor = "white"; 41 Container.style.color = "black"; 42 Container.style.transition = "all 0.125s ease"; 43 Container.style.overflow = "hidden"; 44 document.body.appendChild(Container); 45 46 const TitleElement = document.createElement("span"); 47 TitleElement.style.position = "absolute"; 48 TitleElement.style.display = "flex"; 49 TitleElement.style.paddingLeft = "2.5%"; 50 TitleElement.style.width = "100%"; 51 TitleElement.style.height = "10%"; 52 TitleElement.style.backgroundColor = "rgba(0, 0, 0, 0.5)"; 53 TitleElement.style.color = "white"; 54 TitleElement.style.alignItems = "center"; 55 TitleElement.style.alignContent = "center"; 56 TitleElement.innerHTML = Title; 57 Container.appendChild(TitleElement); 58 59 const CloseButton = document.createElement("div"); 60 CloseButton.style.position = "absolute"; 61 CloseButton.innerHTML = "X"; 62 CloseButton.style.right = "4.5%"; 63 CloseButton.style.cursor = "pointer"; 64 TitleElement.appendChild(CloseButton); 65 66 const Image = document.createElement("img"); 67 Image.src = MarkIcon; 68 Image.draggable = false; 69 Image.style.position = "absolute"; 70 Image.style.transform = "translate(-50%, -50%)"; 71 Image.style.width = "10%"; 72 Image.style.top = "52.5%"; 73 Image.style.left = "10%"; 74 Container.appendChild(Image); 75 76 const MessageContent = document.createElement("div"); 77 MessageContent.innerHTML = Message; 78 MessageContent.style.position = "absolute"; 79 MessageContent.style.transform = "translate(0%, -50%)"; 80 MessageContent.style.top = "52.5%"; 81 MessageContent.style.left = "20%"; 82 MessageContent.style.fontSize = "1.5rem"; 83 Container.appendChild(MessageContent); 84 85 CloseButton.addEventListener("click", () => { 86 Container.style.opacity = 0; 87 setTimeout(() => { 88 Container.remove(); 89 }, 125); 90 }); 91 92 CloseButton.addEventListener("mouseenter", () => { 93 CloseButton.style.color = "red"; 94 }); 95 96 CloseButton.addEventListener("mouseleave", () => { 97 CloseButton.style.color = "white"; 98 }); 99} 100 101export function Print(x) { 102 const LogContainer = document.getElementById("LogContainer"); 103 104 if (LogContainer) { 105 const Span = document.createElement("span"); 106 Span.innerHTML = x; 107 LogContainer.appendChild(Span); 108 109 setTimeout(() => { 110 Span.style.opacity = "0"; 111 setTimeout(() => { 112 Span.remove(); 113 }, 2000); 114 }, 3000); 115 } 116} 117 118export function PowderEffect(R, G, B, EffectStrength) { 119 return { 120 R: Random(R + EffectStrength, R), 121 G: Random(G + EffectStrength, G), 122 B: Random(B + EffectStrength, B) 123 }; 124} 125 126export function RgbString(RgbString) { 127 const RgbArray = RgbString.match(/\d+/g).map(Number); 128 return { 129 R: RgbArray[0], 130 G: RgbArray[1], 131 B: RgbArray[2] 132 }; 133} 134 135export function CombustElement(CausticPart, FlammablePart) {
136 GetAllParticles().forEach(Particle => { 137 if (Particle !== FlammablePart && Particle.dataset.flammable === "true") { 138 if (CheckCollision(FlammablePart, Particle)) { 139 CreateParticle(Elements.find(element => element.Name === "SMKE"), Particle.offsetLeft, Particle.offsetTop); 140 Particle.remove(); 141 } 142 } 143 }); 144 145 CreateParticle(Elements.find(element => element.Name === "SMKE"), FlammablePart.offsetLeft, FlammablePart.offsetTop); 146 FlammablePart.remove(); 147 CausticPart.remove(); 148} 149 150export function ExplodeParticle(Particle, Lifetime) { 151 CreateExplosion(Random(255, 200), Random(25, 0), Random(25, 0), Particle.offsetLeft, Particle.offsetTop, Lifetime); 152 Particle.remove(); 153} 154 155export function CheckCollision(E0, E1) { 156 const r1 = E0.getBoundingClientRect(); 157 const r2 = E1.getBoundingClientRect(); 158 159 return !(r1.right < r2.left || 160 r1.left > r2.right || 161 r1.bottom < r2.top || 162 r1.top > r2.bottom); 163} 164 165export function CreateParticle( 166 { 167 Name, 168 Color, 169 Flammable, 170 Caustic, 171 RadioactiveSettings, 172 Light, 173 Temp, 174 MeltingPoint, 175 BoilingPoint, 176 Type, 177 ColdType, 178 HotType 179 }, PositionX, PositionY) { 180 const ParticleContainer = document.getElementById("ParticleContainer"); 181 const PowderStrength = Type !== "Solid" ? Settings.PowderEffectStrength : Settings.PowderEffectStrength / 4; 182 const GridSize = parseFloat(document.body.getAttribute("grid-size")); 183 184 function StringToRgb(RgbString) { 185 const [R, G, B] = RgbString.match(/\d+/g).map(Number); 186 return { R, G, B }; 187 } 188 189 if (Name === "NONE") { 190 return; 191 } 192 193 if (ParticleContainer) { 194 const BaseColor = StringToRgb(Color); 195 const TargetColor = `rgb(${BaseColor.R + Random(PowderStrength, -PowderStrength) / 4}, ${BaseColor.G + Random(PowderStrength, -PowderStrength) / 4}, ${BaseColor.B + Random(PowderStrength, -PowderStrength) / 4})`; 196 197 const Particle = document.createElement("div"); 198 Particle.style.position = "absolute"; 199 Particle.style.left = `${PositionX}px`; 200 Particle.style.top = `${PositionY}px`; 201 Particle.style.width = `${GridSize}px`; 202 Particle.style.height = `${GridSize}px`; 203 Particle.style.backgroundColor = TargetColor; 204 205 Particle.style.pointerEvents = Type === "None" ? "none" : ""; 206 207 Particle.className = Name.toUpperCase(); 208 Particle.dataset.name = Name; 209 Particle.dataset.particle = "true"; 210 Particle.dataset.type = Type; 211 Particle.dataset.coldType = ColdType; 212 Particle.dataset.hotType = HotType; 213 Particle.dataset.fixedType = Type; 214 Particle.dataset.color = TargetColor; 215 Particle.dataset.fixedColor = TargetColor; 216 Particle.dataset.flammable = Flammable.toString(); 217 Particle.dataset.caustic = Caustic.toString(); 218 219 Particle.dataset.radioactive = RadioactiveSettings ? RadioactiveSettings.Radioactive.toString() : "false"; 220 Particle.dataset.fixedRadioactive = RadioactiveSettings ? RadioactiveSettings.Radioactive.toString() : "false"; 221 Particle.dataset.radioactivity = RadioactiveSettings ? RadioactiveSettings.Radioactivity.toString() : ""; 222 Particle.dataset.decayParticle = RadioactiveSettings ? RadioactiveSettings.DecayParticle : ""; 223 224 Particle.dataset.light = Light.toString(); 225 Particle.dataset.temp = Temp.toString(); 226 Particle.dataset.meltingPoint = MeltingPoint !== undefined ? MeltingPoint.toString() : ""; 227 Particle.dataset.boilingPoint = BoilingPoint !== undefined ? BoilingPoint.toString() : ""; 228 Particle.id = Name; 229 Particle.classList.add("PART"); 230 ParticleContainer.appendChild(Particle); 231 232 return Particle; 233 } 234} 235 236export function CreateRawParticle(X, Y) { 237 const GridSize = parseFloat(document.body.getAttribute("grid-size")); 238 239 const Particle = document.createElement("div"); 240 Particle.style.position = "absolute"; 241 Particle.style.left = `${X}px`; 242 Particle.style.top = `${Y}px`; 243 Particle.style.width = `${GridSize}px`; 244 Particle.style.height = `${GridSize}px`; 245 return Particle; 246} 247 248export function CreateExplosion(R, G, B, X, Y, Lifetime) { 249 const AllParticles = GetAllParticles(); 250 251 for (let Index = 0; Index < Random(9, 0); Index++) { 252 const XDirection = Random(5, -5); 253 const YDirection = Random(5, -5); 254
255 const Particle = CreateRawParticle(X, Y); 256 Particle.style.backgroundColor = `rgb(${PowderEffect(R, G, B, Settings.PowderEffectStrength).R}, ${PowderEffect(R, G, B, Settings.PowderEffectStrength).G}, ${PowderEffect(R, G, B, Settings.PowderEffectStrength).B})`; 257 document.body.appendChild(Particle); 258 259 var Time = 0; 260 261 function Update() { 262 Time += 0.15; 263 264 Particle.style.left = `${Particle.offsetLeft + XDirection}px`; 265 Particle.style.top = `${Particle.offsetTop + YDirection}px`; 266 267 Particle.style.opacity = 1 - Time / Lifetime; 268 269 if (false) { 270 AllParticles.forEach(OtherParticle => { 271 if (OtherParticle !== Particle && OtherParticle.dataset.hotType === "Explosive") { 272 if (CheckCollision(Particle, OtherParticle)) { 273 ExplodeParticle(OtherParticle, 15); 274 } 275 } 276 }); 277 } 278 279 const ParticleRect = Particle.getBoundingClientRect(); 280 const TouchingPart = document.elementFromPoint(ParticleRect.left, ParticleRect.top); 281 if (TouchingPart.dataset.hotType === "Explosive") { 282 CreateExplosion(RgbString(TouchingPart.dataset.color).R, RgbString(TouchingPart.dataset.color).G, RgbString(TouchingPart.dataset.color).B, TouchingPart.offsetLeft, TouchingPart.offsetTop, 15); 283 TouchingPart.remove(); 284 } 285 286 if (Time <= Lifetime) { 287 requestAnimationFrame(Update); 288 } else { 289 Particle.remove(); 290 } 291 } 292 293 Update(); 294 } 295} 296 297export function DrawLineParticle(Element, StartPositionX, StartPositionY, EndPositionX, EndPositionY) { 298 const GridSize = parseFloat(document.body.getAttribute("grid-size")); 299 300 const Distance = Math.sqrt(Math.pow(EndPositionX - StartPositionX, 2) + Math.pow(EndPositionY - StartPositionY, 2)); 301 const NumberOfElements = Math.floor(Distance / GridSize); 302 const DeltaX = (EndPositionX - StartPositionX) / NumberOfElements; 303 const DeltaY = (EndPositionY - StartPositionY) / NumberOfElements; 304 305 for (let Index = 0; Index < NumberOfElements; Index++) { 306 let CurrentX = StartPositionX + DeltaX * Index; 307 let CurrentY = StartPositionY + DeltaY * Index; 308 309 CurrentX = Math.round(CurrentX / GridSize) * GridSize; 310 CurrentY = Math.round(CurrentY / GridSize) * GridSize; 311 312 CreateParticle(Element, CurrentX, CurrentY); 313 } 314} 315 316export function DrawLinePlaceholder(StartPositionX, StartPositionY, EndPositionX, EndPositionY) { 317 const GridSize = parseFloat(document.body.getAttribute("grid-size")); 318 319 const Distance = Math.sqrt(Math.pow(EndPositionX - StartPositionX, 2) + Math.pow(EndPositionY - StartPositionY, 2)); 320 const NumberOfElements = Math.floor(Distance / GridSize); 321 const DeltaX = (EndPositionX - StartPositionX) / NumberOfElements; 322 const DeltaY = (EndPositionY - StartPositionY) / NumberOfElements; 323 324 PlaceholderContainer.innerHTML = ""; 325 326 for (let Index = 0; Index < NumberOfElements; Index++) { 327 let CurrentX = StartPositionX + DeltaX * Index; 328 let CurrentY = StartPositionY + DeltaY * Index; 329 330 CurrentX = Math.round(CurrentX / GridSize) * GridSize; 331 CurrentY = Math.round(CurrentY / GridSize) * GridSize; 332 333 const PlaceholderItem = document.createElement("div"); 334 PlaceholderItem.style.position = "absolute"; 335 PlaceholderItem.style.backgroundColor = "rgb(60, 60, 60)"; 336 PlaceholderItem.style.width = `${GridSize}px`; 337 PlaceholderItem.style.aspectRatio = "1 / 1"; 338 PlaceholderItem.style.left = `${CurrentX}px`; 339 PlaceholderItem.style.top = `${CurrentY}px`; 340 341 PlaceholderContainer.appendChild(PlaceholderItem); 342 } 343} 344 345export function ClearLinePlaceholder() { 346 PlaceholderContainer.innerHTML = ""; 347} 348 349export function GetAllParticles() { 350 return Array.from(ParticleContainer.getElementsByTagName("div")); 351} 352 353export function GetParticleFromPosition(X, Y) { 354 let Element = document.elementFromPoint(X, Y); 355 if (Element && Element.classList.contains("PART")) { 356 return Element; 357 } 358 return null; 359} 360 361export function GetParticleFromName(Name) { 362 const AllParticles = GetAllParticles(); 363 if (AllParticles.length > 0) { 364 return AllParticles.find(Particle => Particle.dataset.name.toUpperCase() === Name.toUpperCase()); 365 } 366} 367 368export function GetElement(Name) { 369 return Elements.find(element => element.Name === Name); 370} 371 372export function IsPlaceOccupied(X, Y, GridSize) { 373 const Particles = Array.from(ParticleContainer.children); 374 return Particles.some(Particle => { 375 const ParticleRect = Particle.getBoundingClientRect(); 376 const ParticleX = Math.floor(ParticleRect.left / GridSize) * GridSize; 377 const ParticleY = Math.floor(ParticleRect.top / GridSize) * GridSize; 378 return ParticleX === X && ParticleY === Y; 379 }); 380} 381 382export class math { 383 static Clamp(value, min, max) { 384 return Math.min(Math.max(value, min), max); 385 } 386 387 static Lerp(a, b, t) { 388 return a + (b - a) * t; 389 } 390 391 static Map(value, inMin, inMax, outMin, outMax) {
392 return (value - inMin) * (outMax - outMin) / (inMax - inMin) + outMin; 393 } 394 395 static Sign(value) { 396 return value < 0? -1 : value > 0? 1 : 0; 397 } 398 399 static Rad(degrees) { 400 return degrees * Math.PI / 180; 401 } 402 403 static Random(Max, Min) { 404 return Math.floor(Math.random() * (Max - Min + 1)) + Min; 405 } 406 407 static Gcd(A, B) { 408 while (B !== 0) { 409 var C = B; 410 B = A % B; 411 A = C; 412 } 413 return A; 414 } 415 416 static Lcm(A, B) { 417 return (A * B) / math.Gcd(A, B); 418 } 419 420 static RoundTo(X, Y) { 421 return Math.round(X / Y) * Y; 422 } 423}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.