2026-01-09 20:52:45 -05:00
|
|
|
/*Version 1.2.0 Pseudorandom world generator*/
|
2025-10-29 16:57:45 -04:00
|
|
|
function pseudorandom(key, num, max = 1){
|
|
|
|
|
return (Math.log(key)*(num*Math.log(1625.4986772154357))) % max;
|
|
|
|
|
};
|
2025-09-27 21:30:37 -04:00
|
|
|
eLists.STONEELEMS = ["rock", "gravel", "tuff", "basalt", "rock_wall"];
|
|
|
|
|
let oreChances = {
|
|
|
|
|
diamond: 0.045,
|
|
|
|
|
gold: 0.1,
|
|
|
|
|
silver: 0.2,
|
|
|
|
|
tungsten: 0.3,
|
|
|
|
|
iron: 0.4,
|
|
|
|
|
copper: 0.6,
|
|
|
|
|
charcoal: 0.8,
|
|
|
|
|
uranium: 0.805,
|
|
|
|
|
aluminum: 1
|
|
|
|
|
}
|
2026-01-09 10:57:21 -05:00
|
|
|
function makeCurve(pos, w, dir, div = 200){
|
2026-01-09 08:48:38 -05:00
|
|
|
let prevX = pos[0], prevY = pos[1];
|
|
|
|
|
let res = [];
|
|
|
|
|
for(i = w; i >= 0; i--){
|
|
|
|
|
let x2 = (dir == 1) ? pos[0]-i : pos[0]+i;
|
2026-01-09 10:57:21 -05:00
|
|
|
let y2 = height-((1/div)*(i**2));
|
2026-01-09 08:48:38 -05:00
|
|
|
res = res.concat(lineCoords(prevX, prevY, Math.round(x2), Math.round(y2), 1));
|
|
|
|
|
prevX = Math.round(x2), prevY = Math.round(y2);
|
|
|
|
|
}
|
|
|
|
|
return res;
|
|
|
|
|
}
|
2026-01-09 20:52:45 -05:00
|
|
|
|
2026-01-12 10:56:54 -05:00
|
|
|
function makePool(pos, w=1, h=1){
|
|
|
|
|
let res = [];
|
|
|
|
|
for(let i = (w*12*Math.PI); i >= 0; i--){
|
|
|
|
|
let y = ((h*35)/3)*Math.sin(i/(12*w));
|
|
|
|
|
res.push([i, y]);
|
|
|
|
|
}
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-13 10:54:39 -05:00
|
|
|
function drawTriangle(pos, height, elem, replace = null, properties = {}){
|
|
|
|
|
for(let i = 0; i < 2*height; i++){
|
|
|
|
|
drawLine(elem, pos[0]+i, pos[1], pos[0]+height, pos[1]-(height), replace, properties);
|
2026-01-13 09:15:46 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-09 20:52:45 -05:00
|
|
|
elements.sandstone = {
|
|
|
|
|
category: "solids",
|
|
|
|
|
color: ["#a89f67", "#b89c6b", "#bbad68"],
|
|
|
|
|
behavior: behaviors.SOLID,
|
|
|
|
|
breakInto: "sand",
|
|
|
|
|
tempHigh: 1700,
|
|
|
|
|
stateHigh: "molten_glass",
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
elements.packed_sand.tempHigh = 300;
|
|
|
|
|
elements.packed_sand.stateHigh = "sandstone";
|
|
|
|
|
|
2026-01-13 10:54:39 -05:00
|
|
|
function drawLine(elem,x1,y1,x2,y2, replace = null, properties = {}){
|
|
|
|
|
let coords = lineCoords(Math.round(x1),Math.round(y1),Math.round(x2),Math.round(y2), 1);
|
2026-01-09 20:52:45 -05:00
|
|
|
for(let pos of coords){
|
|
|
|
|
let res = tryCreate(elem, pos[0], pos[1]);
|
2026-01-13 10:54:39 -05:00
|
|
|
if(res != null){
|
|
|
|
|
for(let key in properties){
|
|
|
|
|
console.log(properties[key], key)
|
|
|
|
|
res[key] = properties[key];
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-01-09 20:52:45 -05:00
|
|
|
if(replace != null && res == null){
|
|
|
|
|
let pixel = getPixel(pos[0], pos[1]);
|
|
|
|
|
if(pixel != null && replace.includes(pixel.element)){
|
|
|
|
|
changePixel(pixel, elem);
|
2026-01-13 10:54:39 -05:00
|
|
|
for(let key in properties){
|
|
|
|
|
console.log(properties[key], key)
|
|
|
|
|
pixel[key] = properties[key];
|
|
|
|
|
}
|
2026-01-09 20:52:45 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-01-09 10:57:21 -05:00
|
|
|
let structureFuncs = {
|
|
|
|
|
ocean: (seed)=>{
|
|
|
|
|
let side = (pseudorandom(15, (seed/2**32)*62, 1) > 0.5) ? 0 : width;
|
|
|
|
|
let positions = makeCurve([side, 45], 90, (side == 0) ? -1 : 1, 200-(pseudorandom(82, (seed/2**32)*972, 70) - 35));
|
|
|
|
|
let obj = {};
|
|
|
|
|
for(let pos of positions){
|
|
|
|
|
if(obj[pos[0]] != undefined){
|
|
|
|
|
obj[pos[0]] = (obj[pos[0]] > pos[1]) ? obj[pos[0]] : pos[1];
|
|
|
|
|
} else {
|
|
|
|
|
obj[pos[0]] = pos[1];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
for(let key in obj){
|
|
|
|
|
for(let i = obj[key]; i > 0; i--){
|
|
|
|
|
let p = getPixel(key, i);
|
|
|
|
|
if(p != null){
|
|
|
|
|
changePixel(p, "water");
|
|
|
|
|
}
|
|
|
|
|
//tryDelete(key, i);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
},
|
2026-01-09 20:52:45 -05:00
|
|
|
pyramid: (seed)=>{
|
|
|
|
|
|
|
|
|
|
if(pseudorandom(232, 4564*(seed/2**32), 1) < 0.25){
|
|
|
|
|
let x = pseudorandom(531, 9834*(seed/2**32), width);
|
|
|
|
|
let h = pseudorandom(659, 2342*(seed/2**32), 10) + 20;
|
2026-01-13 10:54:39 -05:00
|
|
|
let y = (height-35);
|
|
|
|
|
drawTriangle([x,y], h, "sandstone", ["sand","cactus"]);
|
2026-01-09 20:52:45 -05:00
|
|
|
}
|
|
|
|
|
},
|
2026-01-12 10:56:54 -05:00
|
|
|
|
|
|
|
|
volcano: (seed)=>{
|
|
|
|
|
let x = pseudorandom(531, 9834*(seed/2**32), width);
|
2026-01-13 10:54:39 -05:00
|
|
|
let h = pseudorandom(659, 2342*(seed/2**32), 10) + 25;
|
2026-01-13 09:15:46 -05:00
|
|
|
let hwidth = h*Math.tan(0.78539816);
|
2026-01-12 10:56:54 -05:00
|
|
|
let num = 0;
|
2026-01-13 10:54:39 -05:00
|
|
|
let y = (height-35);
|
|
|
|
|
drawTriangle([x,y], h, "basalt", null, {temp: 850});
|
|
|
|
|
let w = Math.round(pseudorandom(2423,34543*(seed/2**32), 2))+1;
|
|
|
|
|
let d = Math.round(pseudorandom(1231, 54345*(seed/2**32), 12)-6);
|
|
|
|
|
let coords = lineCoords(Math.round(x+(h)+d), height-11, Math.round(x+(h)), Math.round(y-h), w);
|
|
|
|
|
for(let pos of coords){
|
|
|
|
|
let p = getPixel(pos[0],pos[1]);
|
|
|
|
|
if(p != null && p.element == "basalt"){
|
|
|
|
|
changePixel(p, "magma", 850);
|
|
|
|
|
}
|
2026-01-12 10:56:54 -05:00
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
lava_pool: (seed)=>{
|
2026-01-13 09:15:46 -05:00
|
|
|
let x = pseudorandom(455, 67854*(seed/2**32), width);
|
|
|
|
|
let y;
|
|
|
|
|
let vx = pseudorandom(531, 9834*(seed/2**32), width);
|
|
|
|
|
let vh = pseudorandom(659, 2342*(seed/2**32), 10) + 20;
|
|
|
|
|
if(x > vx-vh && x < vx+vh){
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
for(let i = height; i > 0; i--){
|
|
|
|
|
if(getPixel(Math.round(x), i-1) == null && !outOfBounds(Math.round(x), i-1)){
|
|
|
|
|
y = i;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
let positions = makePool([x,y], 1+pseudorandom(678, 3453*seed, 1), 1+pseudorandom(232, 8754*seed, 0.75));
|
|
|
|
|
for(let pos of positions){
|
|
|
|
|
for(let i = y+pos[1]; i > y-10; i--){
|
|
|
|
|
let p = getPixel(Math.round(pos[0]), Math.round(i));
|
|
|
|
|
if(p != null){
|
|
|
|
|
changePixel(p, "magma");
|
|
|
|
|
p.temp = 850;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-01-12 10:56:54 -05:00
|
|
|
}
|
2026-01-09 10:57:21 -05:00
|
|
|
};
|
2025-09-27 21:30:37 -04:00
|
|
|
class biome {
|
2026-01-09 20:52:45 -05:00
|
|
|
constructor(layersArr, yLevels, properties, afterFunc = false, genStructures = false, sp = false){
|
2025-09-27 21:30:37 -04:00
|
|
|
this.layers = layersArr;
|
|
|
|
|
this.yLevels = yLevels;
|
|
|
|
|
this.vMulti = 1;
|
2026-01-09 10:57:21 -05:00
|
|
|
this.structures = (genStructures != false) ? [].concat(genStructures) : undefined;
|
2026-01-09 20:52:45 -05:00
|
|
|
this.afterFunc = (afterFunc != false) ? afterFunc : undefined;
|
|
|
|
|
this.sPriority = sp;
|
2025-09-27 21:30:37 -04:00
|
|
|
for(let item in properties){
|
|
|
|
|
this[item] = properties[item];
|
|
|
|
|
}
|
|
|
|
|
this.generate = function(seed){
|
|
|
|
|
autoResizeCanvas();
|
Version 1.13.2 - January 11, 2026
+ Edit Mode
~ Moved Special tools to the edit tab
~ Expect more tools in the future
+ Relations - Multiple pixels as a single entity
+ Group and Ungroup tool in edit tab
+ Grouped pixels fall and move as one structure
+ Grouped pixels are ungrouped when broken or changing states
+ Grouped pixels can displace fluids (Experimental)
+ More Shift-Select functionality:
+ Battery can set a frequency to create timers
+ Image tool can set element
~ Fire begins more yellow and gets redder quicker
+ Icing (Hidden) made with Butter and Sugar
~ Liquids and Gases appear less grainy
~ Settings changes
+ Speed option in Settings to replace TPS button
+ Keybind: T to change TPS
~ Renamed E button to Elem button
~ Improved simulation speeds
- Removed World Gen
~ We recommend the PRNGworldgenlib.js mod, a much better world generator
- Removed Cheerful Mode
[Changes]
+ Escape can be pressed to cancel while drawing a line
+ Fillers can be painted and will fight other colors
+ Portals show destination lines when hovered over or selected
+ Portal In can be selected with the Elem button by typing 'Portal'
+ Lightning placed near certain elements will change color
+ Worms can break down Flour, Dough, Adobe, Paper, Confetti, Cellulose, Cheese, and Potato
+ Worms can move through Mulch
+ Radiation will radiate Batter
+ Rad Steam causes Cheese to rot
~ Filters and Gates are Acid-resistant
~ Portals no longer teleport Fuse
~ Ruler measures diagonal lines as a pixel count instead of hypotenuse
~ Unique flame colors for Nickel, Iron, and Mercury
~ Rearranged Special category
~ Opening the Info, Mods, or Settings menus will pause the game
~ Steam: All canvas sizes now stretch to the full screen width
+ Assigned densities to many solids
+ Keybind: Quote (") to toggle Edit Mode
[Bug Fixes]
~ Fixed: Dragging pixels through Filters creates ghost pixels
~ Fixed: Filters can break when transporting to Gates or Pipes
~ Fixed: Pixels are rendered in incorrect position when mixing with Pipe, Filter, or Gate
~ Fixed: Broken modded saves are loaded every bootup
~ Fixed: Precision Dot is misaligned with 2- and 4-wide brushes
~ Fixed: Portals can't transmit electricity if surrounded by pixels
~ Fixed: E-cloner can't be set to Fuse by clicking on it
~ Fixed: Some saves throw TypeError "Cannot set properties of undefined"
~ Fixed: Prop tool always unpauses after dialog
~ Fixed: Z and Backspace keys select Heat by default instead of Sand
~ Fixed: Random can't place Fire, Plasma, Ink, Bless, Rock Wall, Cold Fire, Sun, Pointer, or Art
~ Fixed: Elem dialog doesn't close if button is pressed again
~ Fixed: Wrong font when language set to Italian
~ Fixed: Magnesium melts at a much lower temperature than expected
~ Fixed: Shift-selecting Random and inputting 'random' causes errors
[Technical]
~ Note: Optimizations mean a lot of code was rewritten, please report any issues and be patient
~ Note: Don't pass an 'rgba' color to drawSquare, use the 'alpha' argument instead
+ Pixel relations system
+ Used to group pixels together
+ '_r' pixel property to identify its relation (should be an integer)
+ 'trackPaint' element property (boolean)
+ 'painted' pixel property (color code) given to these elements when painted
+ "Failed to load" message instead of hanging forever
~ 'con' contents only render if element has existing 'canContain' property
~ 'onMouseDown' element event only triggers with left clicks
~ Acid Gas 'ignore' property is now identical to Acid
~ Elements with a set density but no state are set to solid
~ Fuse no longer shows hidden element
~ Save version is now sb7
2026-01-11 13:52:44 -05:00
|
|
|
// paused = true;
|
2026-01-12 10:56:54 -05:00
|
|
|
if(seed <= 50000000){
|
|
|
|
|
seed = (seed*50000000) % (2**32);
|
|
|
|
|
}
|
2025-09-27 21:30:37 -04:00
|
|
|
let fraction = seed/(2**32);
|
2026-01-09 20:52:45 -05:00
|
|
|
if(this.sPriority){
|
|
|
|
|
if(this.structures != undefined){
|
|
|
|
|
for(let gen of this.structures){
|
|
|
|
|
gen(seed);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-09-27 21:30:37 -04:00
|
|
|
for(let level of this.yLevels){
|
2025-10-29 16:57:45 -04:00
|
|
|
for(let x = 0; x <= width+2; x++){
|
|
|
|
|
//console.log(x);
|
|
|
|
|
let heightIncrease = (fraction < 0.5) ? -3*pseudorandom(((1-fraction)*(x+1))*(100*pseudorandom(x, 1241, 500)), 1) : 3*pseudorandom(((fraction)*(x+1))*(100*pseudorandom(x, 1241, 500)), 1);
|
2025-09-27 21:30:37 -04:00
|
|
|
let h = level + heightIncrease;
|
|
|
|
|
for(let y = 0; y <= h; y++){
|
2025-10-29 16:57:45 -04:00
|
|
|
//console.log(x,y);
|
2025-09-27 21:30:37 -04:00
|
|
|
let elementsArr = this.layers[this.yLevels.indexOf(level)];
|
2025-10-29 16:57:45 -04:00
|
|
|
let elem = elementsArr[Math.floor(elementsArr.length*pseudorandom((1-fraction)*pseudorandom((x+15)*(y+5), 65343, 500), 2) % elementsArr.length)] || elementsArr[0];
|
|
|
|
|
//if(x == 0 || x == 1){console.log(elem);};
|
|
|
|
|
let placed = tryCreate(elem, x-2, height-y);
|
|
|
|
|
|
2025-09-27 21:30:37 -04:00
|
|
|
if(placed != null && this.temp != null){
|
|
|
|
|
placed.temp = this.temp;
|
|
|
|
|
}
|
|
|
|
|
if(elem == "sapling" && placed){
|
|
|
|
|
if(this.wc != null){
|
|
|
|
|
if(Array.isArray(this.wc)){
|
|
|
|
|
let c = this.wc[Math.round(Math.random()*this.wc.length)];
|
|
|
|
|
while(c == undefined){
|
|
|
|
|
c = this.wc[Math.round(Math.random()*this.wc.length)];
|
|
|
|
|
}
|
|
|
|
|
placed.wc = c;
|
|
|
|
|
} else {
|
|
|
|
|
placed.wc = this.wc;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if(this.lc != null){
|
|
|
|
|
if(Array.isArray(this.lc)){
|
|
|
|
|
let c = this.lc[Math.round(Math.random()*this.lc.length)];
|
|
|
|
|
while(c == undefined){
|
|
|
|
|
c = this.lc[Math.round(Math.random()*this.lc.length)];
|
|
|
|
|
}
|
|
|
|
|
placed.lc = c;
|
|
|
|
|
} else {
|
|
|
|
|
placed.lc = this.lc;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-01-09 20:52:45 -05:00
|
|
|
if(this.structures != undefined){
|
|
|
|
|
for(let gen of this.structures){
|
|
|
|
|
gen(seed);
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-01-13 10:54:39 -05:00
|
|
|
if(!this.noOres){
|
|
|
|
|
this.generateOreVeins(seed, this.vMulti);
|
|
|
|
|
}
|
2025-09-27 21:30:37 -04:00
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
generateOreVeins(seed, multi = 1){
|
|
|
|
|
for(let x = 0; x <= width; x++){
|
|
|
|
|
for(let y = 0; y <= height; y++){
|
2025-10-29 16:57:45 -04:00
|
|
|
let c = pseudorandom((seed/2**32)*pseudorandom(x*y, 657345, 600), 3);
|
2025-09-27 21:30:37 -04:00
|
|
|
if(c <= 0.3){
|
2025-10-29 16:57:45 -04:00
|
|
|
let c2 = pseudorandom((seed/2**32)*pseudorandom(x*y, 98755, 750), 4);
|
2025-09-27 21:30:37 -04:00
|
|
|
let ore;
|
|
|
|
|
for(let e in oreChances){
|
|
|
|
|
if(c2 <= oreChances[e]){
|
|
|
|
|
ore = e;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
let p = getPixel(x,y);
|
|
|
|
|
if(p != null && eLists.STONEELEMS.includes(p.element)){
|
|
|
|
|
tryCreate(ore, x, y, true);
|
|
|
|
|
let a = true;
|
|
|
|
|
let x2 = x, y2 = y;
|
|
|
|
|
while(a){
|
|
|
|
|
let hasStone = false;
|
|
|
|
|
for(let coords of squareCoords){
|
|
|
|
|
x2 += coords[0];
|
|
|
|
|
y2 += coords[1];
|
|
|
|
|
let p2 = getPixel(x2,y2);
|
2025-10-29 16:57:45 -04:00
|
|
|
if(p2 != null && eLists.STONEELEMS.includes(p2.element) && (pseudorandom((seed/2**32)*pseudorandom(x2,y2, 350), x2*y2) < (0.35*multi))){
|
2025-09-27 21:30:37 -04:00
|
|
|
hasStone = true;
|
|
|
|
|
tryCreate(ore, x2, y2, true);
|
|
|
|
|
}
|
2025-10-29 16:57:45 -04:00
|
|
|
if(pseudorandom((seed/2**32)*x2*y2, 6) < 0.15){
|
2025-09-27 21:30:37 -04:00
|
|
|
a = false;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
a = (hasStone) ? a : false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if(this.afterFunc != null){
|
|
|
|
|
this.afterFunc(seed);
|
|
|
|
|
}
|
2026-01-09 20:52:45 -05:00
|
|
|
|
2025-09-27 21:30:37 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
let biomes = {
|
|
|
|
|
plains: new biome([["rock", "rock", "rock", "gravel"], ["dirt", "dirt", "dirt", "dirt", "mud", "gravel"], ["grass","flower_seed","grass","grass","grass","grass","sapling","grass","grass","grass","grass","grass","grass","grass","grass"]], [25, 38, 40]),
|
2026-01-12 10:56:54 -05:00
|
|
|
desert: new biome([["rock", "rock", "rock", "gravel"], ["rock", "packed_sand","rock", "packed_sand", "sand", "sandstone", "sandstone"], ["sand"], [null, null, null, null, null, null, null, null, null, "cactus"]], [17, 26, 40, 42], {vMulti: 1.2}, false, structureFuncs.pyramid, true),
|
2025-10-30 10:32:35 -04:00
|
|
|
savanna: new biome([["rock", "rock", "rock", "gravel"], ["dirt", "dirt", "clay_soil", "dirt", "dirt"], ["grass",null,null, null, null, null, "sapling",null,null,null,null]], [25, 38, 40], {lc: ["#6fde26", "#8eed34", "#8cdb42", "#7bd12a", "#96e81c", "#a9e64e", "#a0d94c", "#a9d63e"], wc: ["#bdab7e", "#b09c6a", "#ab996d", "#998a63", "#917959", "#877051"], vMulti: 1.5}),
|
|
|
|
|
tundra: new biome([["rock", "rock", "rock", "gravel"], ["dirt", "dirt", "rock", "permafrost"], ["permafrost", "permafrost", "permafrost", "permafrost", "permafrost", "permafrost", "ice", "snow"], [null,null,null,null,null,"pinecone",null,null,null,null,null,null]], [25, 30, 38, 40], {temp: -15, vMulti: 2}),
|
2026-01-09 20:52:45 -05:00
|
|
|
beach: new biome([["rock", "rock", "rock", "gravel"], ["rock", "gravel", "sand", "sand"], ["sand"]], [7, 13, 35], {vMulti: 0.8}, (seed)=>{
|
|
|
|
|
dependOn("plants.js", ()=>{
|
2026-01-09 10:57:21 -05:00
|
|
|
for(let i = 0; i < width; i++){
|
2026-01-09 20:52:45 -05:00
|
|
|
console.log(pseudorandom((i*34), (seed/2**32)*234, 1));
|
|
|
|
|
if(pseudorandom((i*34), (seed/2**32)*234, 1) < 0.035){
|
|
|
|
|
let c = true;
|
|
|
|
|
let np = getPixel(i, 20);
|
|
|
|
|
let ny = 21;
|
|
|
|
|
while(np == null){
|
|
|
|
|
np = getPixel(i, ny);
|
|
|
|
|
if(np != null && np.element == "water"){
|
|
|
|
|
c = false;
|
|
|
|
|
};
|
|
|
|
|
ny++;
|
|
|
|
|
}
|
|
|
|
|
if(c){
|
|
|
|
|
tryCreate("banana_seed", i, 20);
|
|
|
|
|
}
|
2026-01-09 10:57:21 -05:00
|
|
|
}
|
|
|
|
|
}
|
2026-01-09 20:52:45 -05:00
|
|
|
}, false);
|
2026-01-09 10:57:21 -05:00
|
|
|
}, structureFuncs.ocean),
|
2026-01-13 10:54:39 -05:00
|
|
|
volcano: new biome([["magma", "magma", "basalt"], ["basalt", "tuff", "magma"], ["basalt"]], [13, 23, 40], {temp: 850, noOres: true}, null, [structureFuncs.volcano, structureFuncs.lava_pool]),
|
2026-01-09 10:57:21 -05:00
|
|
|
|
2025-09-27 21:30:37 -04:00
|
|
|
}
|
|
|
|
|
let seed = Math.random()*(2**32);
|
|
|
|
|
enabledMods.forEach((item)=>{
|
|
|
|
|
if(item.includes("plants.js")){
|
|
|
|
|
biomes.orchard = new biome([["rock","rock","rock","gravel"], ["dirt", "dirt", "dirt", "rock", "gravel"], ["dirt", "dirt", "dirt", "dirt", "mud", "clay_soil", "gravel"]], [25, 30, 38], {afterFunc: (seed)=>{
|
|
|
|
|
for(let i = 0; i < width; i++){
|
|
|
|
|
console.log(i, width);
|
2025-10-29 16:57:45 -04:00
|
|
|
let elem = (pseudorandom((seed/2**32)*pseudorandom(i, 6544, 500), 7) < 0.15) ? plants.tree[(Math.round(Math.random()*plants.tree.length)) % plants.tree.length] : "grass";
|
2025-09-27 21:30:37 -04:00
|
|
|
if(elem != undefined && elem != "grass"){elem += "_seed"};
|
|
|
|
|
elem = (elem == undefined) ? "apple_seed" : elem;
|
|
|
|
|
tryCreate(elem, i, 42);
|
|
|
|
|
}
|
|
|
|
|
}});
|
|
|
|
|
}
|
|
|
|
|
});
|
2026-01-09 10:57:21 -05:00
|
|
|
elements.SeedGenerate = {
|
Version 1.13.2 - January 11, 2026
+ Edit Mode
~ Moved Special tools to the edit tab
~ Expect more tools in the future
+ Relations - Multiple pixels as a single entity
+ Group and Ungroup tool in edit tab
+ Grouped pixels fall and move as one structure
+ Grouped pixels are ungrouped when broken or changing states
+ Grouped pixels can displace fluids (Experimental)
+ More Shift-Select functionality:
+ Battery can set a frequency to create timers
+ Image tool can set element
~ Fire begins more yellow and gets redder quicker
+ Icing (Hidden) made with Butter and Sugar
~ Liquids and Gases appear less grainy
~ Settings changes
+ Speed option in Settings to replace TPS button
+ Keybind: T to change TPS
~ Renamed E button to Elem button
~ Improved simulation speeds
- Removed World Gen
~ We recommend the PRNGworldgenlib.js mod, a much better world generator
- Removed Cheerful Mode
[Changes]
+ Escape can be pressed to cancel while drawing a line
+ Fillers can be painted and will fight other colors
+ Portals show destination lines when hovered over or selected
+ Portal In can be selected with the Elem button by typing 'Portal'
+ Lightning placed near certain elements will change color
+ Worms can break down Flour, Dough, Adobe, Paper, Confetti, Cellulose, Cheese, and Potato
+ Worms can move through Mulch
+ Radiation will radiate Batter
+ Rad Steam causes Cheese to rot
~ Filters and Gates are Acid-resistant
~ Portals no longer teleport Fuse
~ Ruler measures diagonal lines as a pixel count instead of hypotenuse
~ Unique flame colors for Nickel, Iron, and Mercury
~ Rearranged Special category
~ Opening the Info, Mods, or Settings menus will pause the game
~ Steam: All canvas sizes now stretch to the full screen width
+ Assigned densities to many solids
+ Keybind: Quote (") to toggle Edit Mode
[Bug Fixes]
~ Fixed: Dragging pixels through Filters creates ghost pixels
~ Fixed: Filters can break when transporting to Gates or Pipes
~ Fixed: Pixels are rendered in incorrect position when mixing with Pipe, Filter, or Gate
~ Fixed: Broken modded saves are loaded every bootup
~ Fixed: Precision Dot is misaligned with 2- and 4-wide brushes
~ Fixed: Portals can't transmit electricity if surrounded by pixels
~ Fixed: E-cloner can't be set to Fuse by clicking on it
~ Fixed: Some saves throw TypeError "Cannot set properties of undefined"
~ Fixed: Prop tool always unpauses after dialog
~ Fixed: Z and Backspace keys select Heat by default instead of Sand
~ Fixed: Random can't place Fire, Plasma, Ink, Bless, Rock Wall, Cold Fire, Sun, Pointer, or Art
~ Fixed: Elem dialog doesn't close if button is pressed again
~ Fixed: Wrong font when language set to Italian
~ Fixed: Magnesium melts at a much lower temperature than expected
~ Fixed: Shift-selecting Random and inputting 'random' causes errors
[Technical]
~ Note: Optimizations mean a lot of code was rewritten, please report any issues and be patient
~ Note: Don't pass an 'rgba' color to drawSquare, use the 'alpha' argument instead
+ Pixel relations system
+ Used to group pixels together
+ '_r' pixel property to identify its relation (should be an integer)
+ 'trackPaint' element property (boolean)
+ 'painted' pixel property (color code) given to these elements when painted
+ "Failed to load" message instead of hanging forever
~ 'con' contents only render if element has existing 'canContain' property
~ 'onMouseDown' element event only triggers with left clicks
~ Acid Gas 'ignore' property is now identical to Acid
~ Elements with a set density but no state are set to solid
~ Fuse no longer shows hidden element
~ Save version is now sb7
2026-01-11 13:52:44 -05:00
|
|
|
category: "edit",
|
2025-09-27 21:30:37 -04:00
|
|
|
onSelect: function(){
|
|
|
|
|
let arr = [];
|
2025-10-29 16:57:45 -04:00
|
|
|
let txt = shiftDown;
|
2025-10-30 10:32:35 -04:00
|
|
|
Object.keys(biomes).forEach(function(b){arr.push(b);});
|
|
|
|
|
txt = (arr.length >= 7) ? true : txt;
|
2026-01-09 10:57:21 -05:00
|
|
|
promptInput("Leave blank to generate new seed or C to keep current seed. Your current seed is: " + seed, function(i){
|
2025-10-29 16:57:45 -04:00
|
|
|
seed = (i != null && i.toLowerCase() == "c") ? seed : parseFloat(i) || Math.random()*(2**32);
|
2025-09-27 21:30:37 -04:00
|
|
|
seed = seed % (2**32);
|
2025-10-29 16:57:45 -04:00
|
|
|
if(!txt){
|
|
|
|
|
promptChoose("", arr, (choice)=>{
|
|
|
|
|
biomes[choice].generate(seed);
|
|
|
|
|
promptText("World generation complete.");
|
|
|
|
|
selectElement('dirt');
|
|
|
|
|
}, "Select a biome to generate: ");
|
|
|
|
|
} else {
|
|
|
|
|
let str = "";
|
|
|
|
|
for(let key in biomes){
|
|
|
|
|
str += `${key},`;
|
|
|
|
|
}
|
|
|
|
|
str = str.replace(/^,|,$/g, '');
|
|
|
|
|
promptInput("Enter the name of a biome (caps-insensetive) \nBiomes Available: " + str, function(inp){
|
|
|
|
|
if(!arr.includes(inp.toLowerCase())){
|
|
|
|
|
promptText("Invalid selection.");
|
|
|
|
|
}else {
|
|
|
|
|
biomes[inp.toLowerCase()].generate(seed);
|
|
|
|
|
promptText("World generation complete.");
|
|
|
|
|
selectElement('dirt');
|
|
|
|
|
}
|
|
|
|
|
}, "Enter Biome")
|
|
|
|
|
}
|
2025-09-27 21:30:37 -04:00
|
|
|
}, "Enter seed:");
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-01-09 10:57:21 -05:00
|
|
|
elements.RandomGen = {
|
Version 1.13.2 - January 11, 2026
+ Edit Mode
~ Moved Special tools to the edit tab
~ Expect more tools in the future
+ Relations - Multiple pixels as a single entity
+ Group and Ungroup tool in edit tab
+ Grouped pixels fall and move as one structure
+ Grouped pixels are ungrouped when broken or changing states
+ Grouped pixels can displace fluids (Experimental)
+ More Shift-Select functionality:
+ Battery can set a frequency to create timers
+ Image tool can set element
~ Fire begins more yellow and gets redder quicker
+ Icing (Hidden) made with Butter and Sugar
~ Liquids and Gases appear less grainy
~ Settings changes
+ Speed option in Settings to replace TPS button
+ Keybind: T to change TPS
~ Renamed E button to Elem button
~ Improved simulation speeds
- Removed World Gen
~ We recommend the PRNGworldgenlib.js mod, a much better world generator
- Removed Cheerful Mode
[Changes]
+ Escape can be pressed to cancel while drawing a line
+ Fillers can be painted and will fight other colors
+ Portals show destination lines when hovered over or selected
+ Portal In can be selected with the Elem button by typing 'Portal'
+ Lightning placed near certain elements will change color
+ Worms can break down Flour, Dough, Adobe, Paper, Confetti, Cellulose, Cheese, and Potato
+ Worms can move through Mulch
+ Radiation will radiate Batter
+ Rad Steam causes Cheese to rot
~ Filters and Gates are Acid-resistant
~ Portals no longer teleport Fuse
~ Ruler measures diagonal lines as a pixel count instead of hypotenuse
~ Unique flame colors for Nickel, Iron, and Mercury
~ Rearranged Special category
~ Opening the Info, Mods, or Settings menus will pause the game
~ Steam: All canvas sizes now stretch to the full screen width
+ Assigned densities to many solids
+ Keybind: Quote (") to toggle Edit Mode
[Bug Fixes]
~ Fixed: Dragging pixels through Filters creates ghost pixels
~ Fixed: Filters can break when transporting to Gates or Pipes
~ Fixed: Pixels are rendered in incorrect position when mixing with Pipe, Filter, or Gate
~ Fixed: Broken modded saves are loaded every bootup
~ Fixed: Precision Dot is misaligned with 2- and 4-wide brushes
~ Fixed: Portals can't transmit electricity if surrounded by pixels
~ Fixed: E-cloner can't be set to Fuse by clicking on it
~ Fixed: Some saves throw TypeError "Cannot set properties of undefined"
~ Fixed: Prop tool always unpauses after dialog
~ Fixed: Z and Backspace keys select Heat by default instead of Sand
~ Fixed: Random can't place Fire, Plasma, Ink, Bless, Rock Wall, Cold Fire, Sun, Pointer, or Art
~ Fixed: Elem dialog doesn't close if button is pressed again
~ Fixed: Wrong font when language set to Italian
~ Fixed: Magnesium melts at a much lower temperature than expected
~ Fixed: Shift-selecting Random and inputting 'random' causes errors
[Technical]
~ Note: Optimizations mean a lot of code was rewritten, please report any issues and be patient
~ Note: Don't pass an 'rgba' color to drawSquare, use the 'alpha' argument instead
+ Pixel relations system
+ Used to group pixels together
+ '_r' pixel property to identify its relation (should be an integer)
+ 'trackPaint' element property (boolean)
+ 'painted' pixel property (color code) given to these elements when painted
+ "Failed to load" message instead of hanging forever
~ 'con' contents only render if element has existing 'canContain' property
~ 'onMouseDown' element event only triggers with left clicks
~ Acid Gas 'ignore' property is now identical to Acid
~ Elements with a set density but no state are set to solid
~ Fuse no longer shows hidden element
~ Save version is now sb7
2026-01-11 13:52:44 -05:00
|
|
|
category: "edit",
|
2026-01-09 10:57:21 -05:00
|
|
|
onSelect: function(){
|
|
|
|
|
let arr = [];
|
|
|
|
|
let txt = shiftDown;
|
|
|
|
|
Object.keys(biomes).forEach(function(b){arr.push(b);});
|
|
|
|
|
txt = (arr.length >= 7) ? true : txt;
|
|
|
|
|
seed = Math.random()*(2**32);
|
|
|
|
|
//seed %= 2**32;
|
|
|
|
|
if(txt){
|
|
|
|
|
let str = "";
|
|
|
|
|
for(let key in biomes){
|
|
|
|
|
str += `${key}, `;
|
|
|
|
|
}
|
|
|
|
|
str = str.replace(/^,|,$/g, '');
|
|
|
|
|
promptInput("Enter the name of a biome to generate (caps-insensetive)\nBiomes available: \n" + str, function(inp){
|
|
|
|
|
let choice = inp.toLowerCase();
|
|
|
|
|
if(!arr.includes(choice)){
|
|
|
|
|
promptText("Invalid selection.");
|
|
|
|
|
selectElement("dirt");
|
|
|
|
|
} else {
|
|
|
|
|
biomes[choice].generate(seed);
|
|
|
|
|
selectElement("dirt");
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}, "Enter Biome Name: ");
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
promptChoose("", arr, (choice)=>{
|
|
|
|
|
biomes[choice].generate(seed);
|
|
|
|
|
selectElement("dirt");
|
|
|
|
|
}, "Biome Selection");
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
}
|
2025-09-27 22:02:22 -04:00
|
|
|
elements.view_seed = {
|
Version 1.13.2 - January 11, 2026
+ Edit Mode
~ Moved Special tools to the edit tab
~ Expect more tools in the future
+ Relations - Multiple pixels as a single entity
+ Group and Ungroup tool in edit tab
+ Grouped pixels fall and move as one structure
+ Grouped pixels are ungrouped when broken or changing states
+ Grouped pixels can displace fluids (Experimental)
+ More Shift-Select functionality:
+ Battery can set a frequency to create timers
+ Image tool can set element
~ Fire begins more yellow and gets redder quicker
+ Icing (Hidden) made with Butter and Sugar
~ Liquids and Gases appear less grainy
~ Settings changes
+ Speed option in Settings to replace TPS button
+ Keybind: T to change TPS
~ Renamed E button to Elem button
~ Improved simulation speeds
- Removed World Gen
~ We recommend the PRNGworldgenlib.js mod, a much better world generator
- Removed Cheerful Mode
[Changes]
+ Escape can be pressed to cancel while drawing a line
+ Fillers can be painted and will fight other colors
+ Portals show destination lines when hovered over or selected
+ Portal In can be selected with the Elem button by typing 'Portal'
+ Lightning placed near certain elements will change color
+ Worms can break down Flour, Dough, Adobe, Paper, Confetti, Cellulose, Cheese, and Potato
+ Worms can move through Mulch
+ Radiation will radiate Batter
+ Rad Steam causes Cheese to rot
~ Filters and Gates are Acid-resistant
~ Portals no longer teleport Fuse
~ Ruler measures diagonal lines as a pixel count instead of hypotenuse
~ Unique flame colors for Nickel, Iron, and Mercury
~ Rearranged Special category
~ Opening the Info, Mods, or Settings menus will pause the game
~ Steam: All canvas sizes now stretch to the full screen width
+ Assigned densities to many solids
+ Keybind: Quote (") to toggle Edit Mode
[Bug Fixes]
~ Fixed: Dragging pixels through Filters creates ghost pixels
~ Fixed: Filters can break when transporting to Gates or Pipes
~ Fixed: Pixels are rendered in incorrect position when mixing with Pipe, Filter, or Gate
~ Fixed: Broken modded saves are loaded every bootup
~ Fixed: Precision Dot is misaligned with 2- and 4-wide brushes
~ Fixed: Portals can't transmit electricity if surrounded by pixels
~ Fixed: E-cloner can't be set to Fuse by clicking on it
~ Fixed: Some saves throw TypeError "Cannot set properties of undefined"
~ Fixed: Prop tool always unpauses after dialog
~ Fixed: Z and Backspace keys select Heat by default instead of Sand
~ Fixed: Random can't place Fire, Plasma, Ink, Bless, Rock Wall, Cold Fire, Sun, Pointer, or Art
~ Fixed: Elem dialog doesn't close if button is pressed again
~ Fixed: Wrong font when language set to Italian
~ Fixed: Magnesium melts at a much lower temperature than expected
~ Fixed: Shift-selecting Random and inputting 'random' causes errors
[Technical]
~ Note: Optimizations mean a lot of code was rewritten, please report any issues and be patient
~ Note: Don't pass an 'rgba' color to drawSquare, use the 'alpha' argument instead
+ Pixel relations system
+ Used to group pixels together
+ '_r' pixel property to identify its relation (should be an integer)
+ 'trackPaint' element property (boolean)
+ 'painted' pixel property (color code) given to these elements when painted
+ "Failed to load" message instead of hanging forever
~ 'con' contents only render if element has existing 'canContain' property
~ 'onMouseDown' element event only triggers with left clicks
~ Acid Gas 'ignore' property is now identical to Acid
~ Elements with a set density but no state are set to solid
~ Fuse no longer shows hidden element
~ Save version is now sb7
2026-01-11 13:52:44 -05:00
|
|
|
category: "edit",
|
2025-09-27 22:02:22 -04:00
|
|
|
onSelect: function(){
|
|
|
|
|
alert(seed);
|
|
|
|
|
selectElement("dirt");
|
|
|
|
|
}
|
|
|
|
|
}
|