sandboxels/index.html

5870 lines
240 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Sandboxels</title>
<meta name="description" content="A falling sand simulation game.">
<meta name="keywords" content="falling sand, elements, pixel art, simulator, powder">
<meta name="author" content="R74n">
<meta name="copyright" content="R74n">
<link href="https://fonts.googleapis.com/css?family=Press+Start+2P" rel="stylesheet">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="robots" content="follow">
<!--Favicons-->
<link rel="apple-touch-icon" sizes="180x180" href="icons/apple-touch-icon.png?v=2">
<link rel="icon" type="image/png" sizes="32x32" href="icons/favicon-32x32.png?v=2">
<link rel="icon" type="image/png" sizes="16x16" href="icons/favicon-16x16.png?v=2">
<link rel="manifest" href="manifest.json">
<link rel="mask-icon" href="icons/safari-pinned-tab.svg?v=2" color="#2167ff">
<link rel="shortcut icon" href="icons/favicon.ico?v=2">
<meta name="msapplication-TileColor" content="#e6d577">
<meta name="theme-color" content="#000000">
<!--OpenGraph-->
<meta property="og:locale" content="en_US">
<meta property="og:type" content="website">
<meta property="og:title" content="Sandboxels">
<meta property="og:description" content="A falling sand simulation game.">
<meta property="og:url" content="https://sandboxels.r74n.com">
<meta property="og:site_name" content="Sandboxels">
<meta property="og:image" content="icons/wallpaper.png">
<meta property="og:image:width" content="1980">
<meta property="og:image:height" content="971">
<meta property="og:image:type" content="image/png">
<meta property="og:image:alt" content="A rainforest made in Sandboxels">
<!--Twitter-->
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:description" content="A falling sand simulation game.">
<meta name="twitter:title" content="Sandboxels">
<meta name="twitter:site:id" content="1436857621827530753">
<meta name="twitter:image" content="icons/card.png">
<meta name="twitter:image:alt" content="A rainforest made in Sandboxels">
<meta name="twitter:creator:id" content="1436857621827530753">
<script src="https://R74n.com/load.js"></script>
<style>
html, body {
width: 100%;
height: 100%;
margin: 0;
}
body {
font-family: 'Press Start 2P';
background-color: #000000;
color: #ffffff;
}
h1 {
padding: 10px;
padding-bottom: 0px;
}
a {color: rgb(255, 0, 255);text-decoration: none;}
a:hover {color: rgb(255, 121, 255);}
a:active, a:hover:active {color: rgb(255, 179, 255);}
#gameDiv { /*game canvas*/
border: 1px solid #ffffff;
position: absolute;
left: 50%;
transform: translate(-50%, -0%);
-webkit-touch-callout: none; /* iOS Safari */
-webkit-user-select: none; /* Safari */
-khtml-user-select: none; /* Konqueror HTML */
-moz-user-select: none; /* Old versions of Firefox */
-ms-user-select: none; /* Internet Explorer/Edge */
user-select: none;
}
#infoParent, #modParent {
display: none;
}
#infoScreen, #modManager {
border: 1px solid #ffffff;
position: absolute;
left: 50%;
transform: translate(-50%, 8%);
width: 95%;
height: 50%;
max-width: 700px;
padding: 10px;
background-color: rgb(31, 31, 31);
overflow-x: hidden;
}
.menuTitle {
font-size: 1.5em;
text-decoration: underline;
}
.menuText {
margin-top: 5px;
line-height: 1.5em;
}
#infoText {
white-space: pre-wrap;
}
.XButton {
position: absolute;
right: 0px;
top: 0px;
font-size: 2em;
background-color: rgb(100, 33, 33);
padding:5px;
text-align:center;
border: 1px solid #ffffff;
}
.XButton:hover {
background-color: rgb(200, 33, 33);
}
#infoSearch, #modManagerUrl {
position: absolute;
bottom: 50%;
width: 95%;
max-width: 700px;
height: 50px;
left: 50%;
transform: translate(-50%, 198.5%);
background-color: rgb(66, 66, 66);
color: white;
font-size: 1.5em;
padding: 8px;
font-family: 'Press Start 2P';
}
#infoSearch:focus, #modManagerUrl:focus {
outline: none;
}
/*#modManagerAdd {
position: absolute;
bottom: 25%;
right: 25%;
height: 50px;
width: 50px;
transform: translate(-25%, -25%);
background-color: rgb(0, 190, 32);
color: white;
font-size: 2em;
padding: 10px;
font-family: 'Press Start 2P';
}*/
#modManagerList {
margin-top: 20px;
}
#modManagerList li {
list-style-type: none;
position: relative;
}
#modManagerList li::before {
content: '•';
position: absolute;
left: -1.5em;
font-size: 1em;
font-family: 'Press Start 2P';
}
.removeModX {
color: red;
cursor: pointer;
}
.removeModX:hover {
color: rgb(255, 107, 107);
}
.infoLink {
color: rgb(116, 140, 221);
cursor: pointer;
text-decoration: underline;
}
button, input[type="submit"], input[type="reset"] {
background: none;
color: inherit;
border: none;
padding: 0;
font: inherit;
cursor: pointer;
outline: inherit;
}
#underBox {
position: absolute;
left: 50%;
transform: translate(-50%, -0%);
margin-top: 10px;
width: 100%;
}
#controls button {
padding: 5px 10px;
border-radius: 5px;
font-size: 1em;
text-shadow: 0.5px 1px 4px #000000;
color: rgba(255, 255, 255, 0.75);
border: 1px solid #797979;
margin: 0px 5px 5px 5px;
font-variant: small-caps;
}
#controls button.bright {
text-shadow: 0.5px 1px 4px #ffffff;
color: rgba(0, 0, 0, 0.75);
}
/*Darken when active*/
#controls button:active, #controls button:active:hover {
filter: brightness(60%);
}
#controls button:hover {
filter: brightness(90%);
}
#controls button:disabled {
cursor: not-allowed;
}
#controls button[current="true"], #controls button[on="true"] {
border: 1px solid #ffffff;
filter: brightness(110%);
box-shadow: 0 5px 15px rgba(255, 255, 255, .4);
color: rgba(255, 255, 255, 1);
}
#controls button.bright[current="true"] {
color: rgba(0, 0, 0, 1);
}
#controls button[on="true"] {
border-color:lime;
color:lime;
}
#controls div {
display:block;
}
.stat {
margin-right: 25px;
margin-bottom: 5px;
float:right;
}
#stats {
margin: 0px 5px 5px 5px;
font-size: 0.75em;
height: 2em;
width:100%;
}
/* screen size < 700px */
@media screen and (max-width: 700px) {
#stats {padding-bottom:2em;}
h1 {font-size: 1em;}
}
#stat-pos, #stat-pixels, #stat-shift, #stat-tps, #stat-ticks {
float:left;
}
.categoryName {
font-size: 0.75em;
text-transform: uppercase;
margin-left: 5px;
vertical-align: middle;
}
#extraInfo {
margin:5px
}
#categoryControls {
margin-top: 5px;
margin-bottom: 5px;
background-color: rgba(255, 255, 255, 0.125);
white-space: nowrap;
overflow-x: scroll;
overflow-y: hidden;
width: 100%;
position: absolute;
z-index: 0;
padding-bottom:1px;
}
#categoryControls button {
/* Borderless buttons */
border: none;
border-radius: 0;
padding-right: 8px;
margin: 0;
padding-top: 5px;
padding-bottom: 5px;
display: inline-block;
position: relative;
z-index:1;
}
#categoryControls button:not(:last-child) {
border-right: 1px solid rgba(255, 255, 255, 0.4);
}
#categoryControls button[current="true"] {
border: none;
background-color: rgba(255, 255, 255, 0.4);
}
/* Dark Gray X Scrollbar for categoryControls */
#categoryControls::-webkit-scrollbar {
width: 5px;
height: 8px;
background-color: rgba(255, 255, 255, 0.15);
}
#categoryControls::-webkit-scrollbar-thumb {
background-color: rgba(255, 255, 255, 0.25);
border-radius: 5px;
}
#categoryControls::-webkit-scrollbar-track {
box-shadow: inset 0 0 5px rgba(255, 255, 255, 0.15);
border-radius: 10px;
}
#categoryControls::-webkit-scrollbar-thumb:hover {
background-color: rgba(255, 255, 255, 0.3);
}
.category {
margin-top:3.1em;
position:relative;
display:flex;
flex-direction: column;
flex-wrap:wrap;
text-align:center;
}
button, input { /*Disable double tap zoom on mobile devices*/
touch-action: manipulation;
}
</style>
<script>
// replaceAll polyfill
if (!String.prototype.replaceAll) {String.prototype.replaceAll = function(str, newStr){if (Object.prototype.toString.call(str).toLowerCase() === '[object regexp]') {return this.replace(str, newStr);}return this.replace(new RegExp(str, 'g'), newStr);};}
// requestFullScreen
function requestFullScreen(element) { /* Supports most browsers and their versions.*/ var requestMethod = element.requestFullScreen || element.webkitRequestFullScreen || element.mozRequestFullScreen || element.msRequestFullScreen; if (requestMethod) { /*Native full screen.*/ requestMethod.call(element); } else if (typeof window.ActiveXObject !== "undefined") { /*Older IE.*/ var wscript = new ActiveXObject("WScript.Shell"); if (wscript !== null) { wscript.SendKeys("{F11}"); } } }
</script>
<script> // Mod Loader
runAfterLoadList = [];
// runAfterLoad() takes a function and adds it to the runAfterLoadList.
function runAfterLoad(func) {
runAfterLoadList.push(func);
}
// If the localStorage key "enabledMods" exists, load it as an array.
// If it doesn't exist, create an empty array.
enabledMods = localStorage.getItem("enabledMods") ? JSON.parse(localStorage.getItem("enabledMods")) : [];
// Run all scripts in the enabledMods array, if it fails print to console
for (var i = 0; i < enabledMods.length; i++) {
try {
var script = document.createElement('script');
var src = enabledMods[i];
script.src = src;
document.head.appendChild(script);
} catch (e) {
console.log("Error in mod: " + enabledMods[i]);
console.log(e);
}
}
</script>
<script>
behaviors = {
POWDER: [
"XX|XX|XX",
"XX|XX|XX",
"M2|M1|M2",
],
AGPOWDER: [
"M2|M1|M2",
"XX|XX|XX",
"XX|XX|XX",
],
LIQUID: [
"XX|XX|XX",
"M2|XX|M2",
"M1|M1|M1",
],
AGLIQUID: [
"M1|M1|M1",
"M2|XX|M2",
"XX|XX|XX",
],
WALL: [
"XX|XX|XX",
"XX|XX|XX",
"XX|XX|XX",
],
UL_UR: [
"M1|M1|M1",
"M2|XX|M2",
"XX|M2|XX",
],
GAS: [
"M2|M1|M2",
"M1|XX|M1",
"M2|M1|M2",
],
DGAS: [
"M2|M1|M2",
"M1|DL%5|M1",
"M2|M1|M2",
],
SUPPORT: [
"XX|XX|XX",
"SP|XX|SP",
"XX|M1|XX",
],
SUPPORTPOWDER: [
"XX|XX|XX",
"SP|XX|SP",
"M2|M1|M2",
],
DELETE: [
"XX|DL|XX",
"DL|XX|DL",
"XX|DL|XX",
],
FILL: [
"XX|CL|XX",
"CL|XX|CL",
"XX|CL|XX",
],
CLONER: [
"XX|CF|XX",
"CF|XX|CF",
"XX|CF|XX",
],
STURDYPOWDER: [
"XX|XX|XX",
"XX|XX|XX",
"XX|M1|XX",
],
SELFDELETE: [
"XX|XX|XX",
"XX|DL|XX",
"XX|XX|XX",
],
FOAM: [
"XX|XX|XX",
"XX|DL%5|XX",
"M2%25|M1%25|M2%25",
],
BUBBLE: [
"XX|XX|XX",
"XX|DL%0.25 AND FX%1|M1%5",
"XX|M1%1|M1%2",
],
STICKY: [
"XX|ST|XX",
"ST|XX|ST",
"XX|ST AND M1|XX",
],
MOLTEN: [
"XX|CR:fire%2.5|XX",
"M2|XX|M2",
"M1|M1|M1",
],
RADPOWDER: [
"XX|CR:radiation%2|XX",
"CR:radiation%2|XX|CR:radiation%2",
"M2|M1|M2",
],
RADMOLTEN: [
"XX|CR:fire,radiation%4.5|XX",
"M2 AND CR:radiation%2|XX|M2 AND CR:radiation%2",
"M1|M1|M1",
],
RADLIQUID: [
"XX|CR:radiation%2|XX",
"M2 AND CR:radiation%2|XX|M2 AND CR:radiation%2",
"M1|M1|M1",
],
}
eLists = {
"ANIMAL": ["flea","ant","fly","firefly","bee","frog","fish","worm","termite","rat","slug","snail"],
"CLEANANIMAL": ["ant","firefly","bee","frog","fish"],
}
//airDensity = 1.225; // kg/m^3
airTemp = 20; // Celsius
// Element Properties
// name - display name of the element [optional]
// color - color of the element's pixel
// behavior - behavior of the element
// ignore - elements to ignore in behavior [must be an array]
// category - category in which the element will show up in
// density - density of the element [only used for movable elements] (kg/m^3)
// state - solid, liquid, or gas [only used for movable elements]
// reactions - instructions for when elements attempt to move onto each other (object)
// conduct - conductivity of the element (0-1)
// behaviorOn - behavior to override when powered
// colorOn - color to change to when powered
// temp - default temperature of the element (Celsius)
// tempHigh - highest temperature before state change (Celsius)
// tempLow - lowest temperature before state change (Celsius)
// stateHigh - element transformed into when tempHigh is reached
// stateLow - element transformed into when tempLow is reached
// viscosity - how slow a liquid will move (higher = slower) (cps)
// burn - chance of burning per tick (0-100) (%)
// burnTime - time to burn (ticks)
// burnInto - element to turn into after burning
// fireColor - color of the flame given off when burning
// burning - whether the element is burning on creation
// charge - charge of the element on creation
// hardness - chance of resisting damage (0-1)
elements = {
"heat": { //hard-coded
color: "#ff0000",
behavior: [
"HT:2|HT:2|HT:2",
"HT:2|HT:2|HT:2",
"HT:2|HT:2|HT:2",
],
temp: 2,
category: "tools",
insulate:true,
},
"cool": { //hard-coded
color: "#0000ff",
behavior: [
"CO:2|CO:2|CO:2",
"CO:2|CO:2|CO:2",
"CO:2|CO:2|CO:2",
],
temp: -2,
category: "tools",
insulate:true,
},
"erase": { //hard-coded
color: "#fdb5ff",
behavior: [
"DL|DL|DL",
"DL|DL|DL",
"DL|DL|DL",
],
category: "tools",
},
"pick": { //hard-coded
color: ["#fa9b9b","#fae99b","#9bfab7","#9b9dfa"],
behavior: [
"CF|CF|CF",
"CF|DL%5|CF",
"CF|CF|CF",
],
category: "tools",
},
"mix": { //hard-coded
color: ["#fff4b5","#a6a6a6"],
behavior: [
"SW|SW|SW",
"SW|DL%5|SW",
"SW|SW|SW",
],
category: "tools",
},
"lookup": { //hard-coded
color: ["#919c9c","#72abab","#919c9c"],
behavior: behaviors.WALL,
category: "tools",
},
"shock": { //hard-coded
color: "#ffff00",
behavior: [
"SH|SH|SH",
"SH|DL%5|SH",
"SH|SH|SH",
],
category: "tools",
},
"sand": {
color: "#e6d577",
behavior: behaviors.POWDER,
tempHigh: 1700,
stateHigh: "molten_glass",
category: "land",
state: "solid",
density: 1602,
},
"water": {
color: "#2167ff",
behavior: behaviors.LIQUID,
tempHigh: 100,
stateHigh: "steam",
tempLow: 0,
stateLow: "ice",
viscosity: 1,
category: "liquids",
reactions: {
"dirt": { // React with (water reacts with dirt to make mud)
"elem1": null, // First element transforms into; in this case, water deletes itself
"elem2": "mud", // Second element transforms into; in this case, dirt turns to mud
},
"sand": { "elem1": null, "elem2": "wet_sand", },
"salt": { "elem1": "salt_water", "elem2": null, },
"sugar": { "elem1": "sugar_water", "elem2": null, },
"dust": { "elem1": "dirty_water", "elem2": null, },
"ash": { "elem1": "dirty_water", "elem2": null, },
"cyanide": { "elem1": "dirty_water", "elem2": null, },
"carbon_dioxide": { "elem1": "dirty_water", "elem2": null, },
"sulfur": { "elem1": "dirty_water", "elem2": null, },
"rat": { "elem1": "dirty_water", chance:0.005 },
"plague": { "elem1": "dirty_water", "elem2": null, },
"rust": { "elem1": "dirty_water", chance:0.005 },
"fallout": { "elem1": "dirty_water", chance:0.25 },
"radiation": { "elem1": "dirty_water", chance:0.25 },
"quicklime": { "elem1": null, "elem2": "slaked_lime", },
"rock": { "elem2": "wet_sand", "chance": 0.00035 },
"ruins": { "elem2": "rock", "chance": 0.00035 },
},
state: "liquid",
density: 997,
conduct: 0.02,
},
"salt_water": {
color: "#4d85ff",
behavior: behaviors.LIQUID,
tempHigh: 102,
stateHigh: ["steam","salt"],
tempLow: -2,
stateLow: "ice",
viscosity: 2,
category: "liquids",
reactions: {
"dirt": { "elem1": null, "elem2": "mud" },
"sand": { "elem1": null, "elem2": "wet_sand", },
"dust": { "elem1": "dirty_water", "elem2": null, },
"ash": { "elem1": "dirty_water", "elem2": null, },
"carbon_dioxide": { "elem1": "dirty_water", "elem2": null, },
"sulfur": { "elem1": "dirty_water", "elem2": null, },
"charcoal": { "elem1": "dirty_water", chance:0.005 },
"rat": { "elem1": "dirty_water", chance:0.005 },
"plague": { "elem1": "dirty_water", "elem2": null, },
"fallout": { "elem1": "dirty_water", chance:0.25 },
"radiation": { "elem1": "dirty_water", chance:0.25 },
"rust": { "elem1": "dirty_water", chance:0.005 },
"quicklime": { "elem1": null, "elem2": "slaked_lime", },
"rock": { "elem2": "wet_sand", "chance": 0.0005 },
},
state: "liquid",
density: 1026,
conduct: 0.1,
},
"sugar_water": {
color: "#8eaae6",
behavior: behaviors.LIQUID,
tempHigh: 105,
stateHigh: ["steam","sugar"],
tempLow: -5,
stateLow: "ice",
viscosity: 5,
category: "liquids",
reactions: {
"dirt": { "elem1": null, "elem2": "mud" },
"sand": { "elem1": null, "elem2": "wet_sand", },
"dust": { "elem1": "dirty_water", "elem2": null, },
"ash": { "elem1": "dirty_water", "elem2": null, },
"carbon_dioxide": { "elem1": "dirty_water", "elem2": null, },
"sulfur": { "elem1": "dirty_water", "elem2": null, },
"charcoal": { "elem1": "dirty_water", chance:0.005 },
"rat": { "elem1": "dirty_water", chance:0.005 },
"plague": { "elem1": "dirty_water", "elem2": null, },
"fallout": { "elem1": "dirty_water", chance:0.25 },
"radiation": { "elem1": "dirty_water", chance:0.25 },
"rust": { "elem1": "dirty_water", chance:0.005 },
"rock": { "elem2": "wet_sand", "chance": 0.0004 },
},
hidden: true,
state: "liquid",
density: 1026,
conduct: 0.05,
},
"dirty_water": {
color: ["#0e824e","#07755a","#0c6934"],
behavior: behaviors.LIQUID,
tempHigh: 105,
stateHigh: ["steam","carbon_dioxide"],
tempLow: -5,
stateLow: "ice",
viscosity: 10,
category: "liquids",
reactions: {
"dirt": { "elem1": null, "elem2": "mud" },
"sand": { "elem1": null, "elem2": "wet_sand", },
"rock": { "elem2": "wet_sand", "chance": 0.0004 },
"plant": { "elem1":"water", "chance":0.05 },
"algae": { "elem1":"water", "chance":0.05 },
"charcoal": { "elem1":"water", "chance":0.02 },
"gravel": { "elem1":"water", "chance":0.01 },
},
hidden: true,
state: "liquid",
density: 1050,
conduct: 0.1,
},
"dirt": {
color: ["#9e6b4b","#9e6b4b","#9e6b4b","#9e6b4b","#9e6b4b","#9e6b4b","#9e6b4b","#9e6b4b","#9e6b4b","#9e6b4b","#9e6b4b","#9e6b4b","#9e6b4b","#9e6b4b","#a88c7b"],
behavior: behaviors.POWDER,
tempHigh:1200,
tempLow: -50,
stateLow: "permafrost",
category:"land",
state: "solid",
density: 1220,
},
"mud": {
color: "#382417",
behavior: behaviors.STURDYPOWDER,
reactions: {
"dirt": { "elem1":"dirt", "elem2":"mud", "chance":0.0005, "oneway":true },
},
tempHigh: 100,
stateHigh: "mudstone",
tempLow: -50,
stateLow: "permafrost",
category: "land",
state: "solid",
density: 1730,
},
"wet_sand": {
color: "#b5a85e",
behavior: behaviors.STURDYPOWDER,
reactions: {
"sand": { "elem1":"sand", "elem2":"wet_sand", "chance":0.0005, "oneway":true },
},
tempHigh: 100,
stateHigh: "packed_sand",
category: "land",
state: "solid",
density: 1905,
},
"rock": {
color: ["#808080","#4f4f4f","#949494"],
behavior: behaviors.POWDER,
tempHigh: 950,
stateHigh: "magma",
category: "land",
state: "solid",
density: 2550,
hardness: 0.5,
},
"mudstone": {
color: "#4a341e",
behavior: behaviors.SUPPORT,
tempHigh:1200,
stateHigh: "molten_dirt",
category: "land",
state: "solid",
density: 1250,
},
"packed_sand": {
color: "#948b5a",
behavior: behaviors.SUPPORT,
tempHigh:1700,
stateHigh: "molten_glass",
category: "land",
state: "solid",
density: 1682,
},
"plant": {
color: "#00bf00",
behavior: behaviors.WALL,
category:"life",
tempHigh: 300,
stateHigh: "fire",
burn:65,
burnTime:50,
state: "solid",
density: 1050,
},
"grass": {
color: ["#439809","#258B08","#118511","#127B12","#136D14"],
behavior: [
"XX|XX|XX",
"XX|XX|XX",
"XX|M1|XX",
],
tempHigh: 400,
stateHigh: "fire",
burn:50,
burnTime:20,
category:"life",
state: "solid",
density: 1400,
},
"algae": {
color: ["#395706","#6F9315","#9DCA19"],
behavior: [
"XX|XX|XX",
"SW:water,salt_water,sugar_water,dirty_water%1|XX|SW:water,salt_water,sugar_water,dirty_water%1",
"SW:water,salt_water,sugar_water,dirty_water%10|M1|SW:water,salt_water,sugar_water,dirty_water%10",
],
reactions: {
"wood": { "elem1":"lichen" }
},
category:"life",
tempHigh: 225,
stateHigh: "fire",
burn:95,
burnTime:20,
state: "solid",
density: 920,
},
"concrete": {
color: "#ababab",
behavior: behaviors.SUPPORT,
tempHigh: 1500,
stateHigh: "magma",
category: "powders",
state: "solid",
density: 2400,
hardness: 0.5,
},
"wall": {
color: "#808080",
behavior: behaviors.WALL,
category: "solids",
insulate: true,
hardness: 1,
},
"fire": {
color: ["#ff6b21","#ffa600","#ff4000"],
behavior: behaviors.UL_UR,
reactions: {
"water": { "elem1": "smoke" },
},
temp:600,
tempLow:100,
stateLow: "smoke",
tempHigh: 7000,
stateHigh: "plasma",
category: "energy",
burning: true,
burnTime: 25,
burnInto: "smoke",
state: "gas",
density: 0.1,
},
"steam": {
color: "#abd6ff",
behavior: behaviors.GAS,
reactions: {
"steam": { "elem1": null, "elem2": "rain_cloud", "chance":0.3, "y":[0,15] },
"rain_cloud": { "elem1": "rain_cloud", "chance":0.4, "y":[0,15] },
"snow_cloud": { "elem1": "rain_cloud", "chance":0.4, "y":[0,15] },
"pyrocumulus": { "elem1": "rain_cloud", "chance":0.4, "y":[0,15] },
"fire_cloud": { "elem1": "rain_cloud", "elem2": "pyrocumulus", "chance":0.4, "y":[0,15] },
},
temp: 100,
tempLow: 95,
stateLow: "water",
category: "gases",
state: "gas",
density: 0.6,
},
"ice": {
color: "#c5e9f0",
behavior: behaviors.WALL,
temp: 0,
tempHigh: 5,
stateHigh: "water",
category: "solids",
state: "solid",
density: 917,
},
"snow": {
color: "#e1f8fc",
behavior: behaviors.POWDER,
temp: 0,
tempHigh: 5,
stateHigh: "water",
category: "land",
state: "solid",
density: 100,
},
"packed_snow": {
color: "#bcdde3",
behavior: behaviors.SUPPORTPOWDER,
temp: 0,
tempHigh: 20,
stateHigh: "water",
category: "land",
state: "solid",
density: 400,
},
"wood": {
color: "#a0522d",
behavior: behaviors.WALL,
tempHigh: 400,
stateHigh: "fire",
category: "solids",
burn: 5,
burnTime: 300,
burnInto: ["ash","charcoal","fire"],
state: "solid",
},
"smoke": {
color: "#383838",
behavior: behaviors.DGAS,
reactions: {
"steam": { "elem1": "pyrocumulus", "chance":0.08, "y":[0,15] },
"rain_cloud": { "elem1": "pyrocumulus", "chance":0.08, "y":[0,15] },
"snow_cloud": { "elem1": "pyrocumulus", "chance":0.08, "y":[0,15] },
"acid_cloud": { "elem1": "pyrocumulus", "chance":0.05, "y":[0,15] },
"fire_cloud": { "elem1": "pyrocumulus", "chance":0.05, "y":[0,15] },
"pyrocumulus": { "elem1": "pyrocumulus", "chance":0.08, "y":[0,15] },
},
temp: 114,
tempHigh: 605,
stateHigh: "fire",
category: "gases",
state: "gas",
density: 1180,
},
"magma": {
color: ["#ff6f00","#ff8c00","#ff4d00"],
behavior: behaviors.MOLTEN,
reactions: {
"ice": { "elem1": "basalt" },
},
temp: 950,
tempLow: 800,
stateLow: "rock",
viscosity: 10000,
category: "liquids",
state: "liquid",
density: 2725,
},
"plasma": {
color: ["#8800ff","#b184d9","#8800ff"],
behavior: behaviors.DGAS,
behaviorOn: [
"M2|M1|M2",
"CL%5 AND M1|XX|CL%5 AND M1",
"M2|M1|M2",
],
temp:7065,
tempLow:5000,
stateLow: "fire",
category: "energy",
state: "gas",
density: 1,
charge: 0.5,
conduct: 1,
},
"cold_fire": {
color: ["#21cbff","#006aff","#00ffff"],
behavior: [
"M1|M1|M1",
"M2|CH:smoke%8|M2",
"XX|M2|XX",
],
reactions: {
"fire": { "elem1": "smoke", "elem2": "smoke" },
"plasma": { "elem1": "light", "elem2": "light" },
},
temp:-200,
tempHigh:0,
stateHigh: "smoke",
category: "energy",
state: "gas",
density: 0.2,
},
"glass": {
color: ["#5e807d","#679e99"],
behavior: behaviors.WALL,
tempHigh: 1500,
category: "solids",
state: "solid",
density: 2500,
},
"chocolate": {
color: "#4d2818",
behavior: behaviors.STURDYPOWDER,
tempHigh: 31,
stateHigh: "chocolate_syrup",
category: "food",
state: "solid",
density: 1325,
},
"cloner": {
color: "#dddd00",
behavior: behaviors.CLONER,
category:"machines",
insulate:true,
hardness: 1,
},
"ecloner": {
name: "e-cloner",
color: "#dddd00",
behavior: behaviors.WALL,
behaviorOn: behaviors.CLONER,
category:"machines",
insulate:true,
conduct: 1,
hardness: 1,
},
"slow_cloner": {
color: "#888800",
behavior: [
"XX|CF%10|XX",
"CF%10|XX|CF%10",
"XX|CF%10|XX",
],
category:"machines",
insulate:true,
hardness: 1,
},
"wire": {
color: "#4d0a03",
behavior: behaviors.WALL,
category: "machines",
insulate: true,
conduct: 1,
},
"random": { //hard-coded
color: ["#3e5f8a","#a334ec","#ea96f9","#a6ecf6","#70ebc8","#d9286b","#7eed91","#a18b30"],
behavior: behaviors.WALL,
category: "special",
},
"filler": {
color: "#ae4cd9",
behavior: behaviors.FILL,
category:"special",
},
"lattice": {
color: "#cb4cd9",
behavior: [
"CL|XX|CL",
"XX|XX|XX",
"CL|XX|CL",
],
hidden: true,
category:"special",
},
"gravel": {
color: ["#E3E0DF","#B1ABA3","#74736D","#524B47"],
behavior: behaviors.POWDER,
category:"land",
tempHigh: 950,
stateHigh: "magma",
state: "solid",
density: 1680,
hardness: 0.2,
},
"slime": {
color: "#81cf63",
behavior: behaviors.LIQUID,
viscosity: 5000,
tempHigh: 120,
stateHigh: "steam",
category:"liquids",
state: "liquid",
density: 1450,
},
"ruins": {
color: "#5c5c5c",
behavior: [
"XX|SP|XX",
"XX|XX|XX",
"M2%1|M1|M2%1"
],
tempHigh: 1500,
stateHigh: "magma",
category:"powders",
state: "solid",
density: 2400,
hardness: 0.33,
},
"dust": {
color: "#666666",
behavior: behaviors.POWDER,
category: "powders",
burn: 10,
burnTime: 1,
state: "solid",
density: 1490,
},
"void": {
color: "#262626",
behavior: behaviors.DELETE,
category:"special",
hardness: 1,
},
"cell": {
color: ["#00ee00","#83ee00","#d6ee00"],
behavior: [
"XX|CL%0.5|XX",
"CL%0.5|XX|CL%0.5",
"M2%10|M1|M2%10",
],
reactions: {
"infection": { "elem1":"cancer", "chance":0.01 },
"blood": { "elem1":"blood", "chance":0.01 },
"antibody": { "elem1":"antibody", "chance":0.01 },
"laser": { "elem1":"cancer", "chance":0.001 },
},
tempHigh: 102,
stateHigh: "steam",
tempLow: -2,
stateLow: "ice",
state: "solid",
density: 1000.1,
category: "life",
},
"cancer": {
color: ["#300b29","#5c114e","#870c71"],
behavior: [
"XX|CL%1|XX",
"CL%1|XX|CL%1",
"M2%2|M1|M2%2",
],
reactions: {
"cell": { "elem2":"cancer", "chance":0.005 },
},
tempHigh: 202,
stateHigh: "plague",
state: "solid",
density: 1000.2,
category: "life",
},
"plague": {
color: "#36005c",
behavior: behaviors.GAS,
reactions: {
"frog": { "elem2":"plague" },
"ant": { "elem2":"plague" },
"bee": { "elem2":"plague" },
"fish": { "elem2":"plague" },
"firefly": { "elem2":"plague" },
},
category: "life",
state: "gas",
density: 600,
},
"flea": {
color: "#9e4732",
behavior: [
"M2|XX|M2",
"XX|XX|XX",
"M2|M1|M2",
],
reactions: {
"blood": { "elem2":null, "chance":0.1875 },
"infection": { "elem2":null, "chance":0.1875 },
"antibody": { "elem2":null, "chance":0.1875 },
},
tempHigh: 35,
stateHigh: "ash",
category:"life",
burn:95,
burnTime:25,
state: "solid",
density: 400,
conduct: 0.15,
},
"termite": {
color: "#f5a056",
behavior: [
"XX|XX|SW:wood,tree_branch%5",
"XX|FX%3|M2%15 AND BO",
"XX|M1|SW:wood,tree_branch%5",
],
reactions: {
"wood": { "elem2":null, chance:0.04 },
"tree_branch": { "elem2":null, chance:0.02 },
},
tempHigh: 37.78,
stateHigh: "ash",
category:"life",
burn:95,
burnTime:25,
state: "solid",
conduct: 0.15,
},
"ant": {
color: "#4a0903",
behavior: [
"SW:dirt,sand,gravel%5|XX|SW:dirt,sand,gravel%5",
"M2|XX|M2",
"SW:dirt,sand,gravel%5|M1|SW:dirt,sand,gravel%5",
],
tempHigh: 53.7,
stateHigh: "ash",
category:"life",
burn:95,
burnTime:25,
state: "solid",
density: 500,
conduct: 0.15,
},
"worm": {
color: "#402208",
behavior: [
"SW:dirt,sand,gravel,ash,mycelium,mud,wet_sand,clay_soil%3|XX|SW:dirt,sand,gravel,ash,mycelium,mud,wet_sand,clay_soil%3",
"M2%10|XX|M2%10",
"SW:dirt,sand,gravel,ash,mycelium,mud,wet_sand,clay_soil%3|M1|SW:dirt,sand,gravel,ash,mycelium,mud,wet_sand,clay_soil%3",
],
reactions: {
"ash": { "elem2":null, "chance":0.1 },
"root": { "elem2":"dirt", "chance":0.1 },
"hyphae": { "elem2":"mycelium", "chance":0.1 },
"plant": { "elem2":"root", "chance":0.1 },
"grass": { "elem2":"dirt", "chance":0.1 },
"limestone": { "elem2":"calcium", "chance":0.1 },
"quicklime": { "elem2":"calcium", "chance":0.1 },
"slaked_lime": { "elem2":"calcium", "chance":0.1 },
},
tempHigh: 40,
stateHigh: "ash",
category:"life",
burn:95,
burnTime:25,
state: "solid",
conduct: 0.17,
},
"fly": {
color: "#303012",
behavior: [
"XX|M2|M1",
"XX|FX%2|BO",
"XX|M2|M1",
],
reactions: {
"plant": { "elem2":null, chance:0.5 },
"meat": { "elem2":null, chance:0.5 },
"cooked_meat": { "elem2":null, chance:0.5 },
"rotten_meat": { "elem2":null, chance:0.5 },
"vine": { "elem2":null, chance:0.5 },
"corn": { "elem2":null, chance:0.5 },
"potato": { "elem2":null, chance:0.5 },
"wheat": { "elem2":null, chance:0.5 },
"yeast": { "elem2":null, chance:0.5 },
"caramel": { "elem2":null, chance:0.5 },
"bread": { "elem2":null, chance:0.5 },
},
tempHigh: 47,
stateHigh: "ash",
category:"life",
burn:95,
burnTime:25,
state: "solid",
density: 600,
conduct: 0.15,
},
"firefly": {
color: ["#310D09","#310D09","#d9d950","#310D09","#310D09"],
behavior: [
"XX|M2|M1",
"XX|CC:310D09,310D09,310D09,310D09,d9d950%10 AND FX%2|BO",
"XX|M2|M1",
],
reactions: {
"pollen": { "elem2":null, chance:0.5 },
"honey": { "elem2":null, chance:0.5 },
"firefly": { "elem2":null, chance:0.01 },
"sugar_water": { "elem2":null, chance:0.5 },
"sugar": { "elem2":null, chance:0.25 },
},
tempHigh: 47,
stateHigh: "ash",
category:"life",
burn:95,
burnTime:25,
state: "solid",
density: 600,
conduct: 0.15,
},
"bee": {
color: "#c4b100",
behavior: [
"XX|M2|M1",
"XX|FX%2|M1 AND BO",
"XX|CR:pollen%0.025 AND M2|M1",
],
reactions: {
"sugar_water": { "elem2":null, chance:0.5 },
"sugar": { "elem2":null, chance:0.25 },
"caramel": { "elem2":null, chance:0.5 },
"candy": { "elem2":null, chance:0.05 },
},
tempHigh: 47,
stateHigh: "ash",
category:"life",
burn:95,
burnTime:25,
state: "solid",
density: 600,
conduct: 0.15,
},
"rat": {
color: ["#A698A9","#8C7D82","#CCC3CF"],
behavior: [
"XX|CR:plague%0.05 AND M2%1.5|M2%5",
"XX|FX%2|M2 AND BO",
"XX|M1|M2",
],
reactions: {
"meat": { "elem2":null, "chance":0.5 },
"cooked_meat": { "elem2":null, "chance":0.5 },
"rotten_meat": { "elem2":null, "chance":0.5 },
"plant": { "elem2":null, "chance":0.5 },
"algae": { "elem2":null, "chance":0.5 },
"grass_seed": { "elem2":null, "chance":0.5 },
"wheat_seed": { "elem2":null, "chance":0.5 },
"wheat": { "elem2":null, "chance":0.5 },
"potato_seed": { "elem2":null, "chance":0.5 },
"potato": { "elem2":null, "chance":0.5 },
"corn_seed": { "elem2":null, "chance":0.5 },
"corn": { "elem2":null, "chance":0.5 },
"flower_seed": { "elem2":null, "chance":0.5 },
"flour": { "elem2":null, "chance":0.5 },
"dough": { "elem2":null, "chance":0.5 },
"bread": { "elem2":null, "chance":0.5 },
"toast": { "elem2":null, "chance":0.5 },
"salt": { "elem2":null, "chance":0.5 },
"sugar": { "elem2":null, "chance":0.5 },
"salt_water": { "elem2":"dirty_water", "chance":0.5 },
"sugar_water": { "elem2":"dirty_water", "chance":0.5 },
"water": { "elem2":"dirty_water", "chance":0.5 },
"popcorn": { "elem2":null, "chance":0.5 },
"candy": { "elem2":null, "chance":0.5 },
"caramel": { "elem2":null, "chance":0.5 },
},
category: "life",
tempHigh: 50,
stateHigh: "rotten_meat",
tempLow: 15,
stateLow: "frozen_meat",
burn:80,
burnTime:150,
state: "solid",
conduct: 0.25,
},
"frog": {
color: "#607300",
behavior: [
"XX|XX|M2%3",
"XX|FX%0.5|CR:slime%0.01 AND BO",
"XX|M1|XX",
],
reactions: {
"fly": { "elem2":null, chance:0.5 },
"firefly": { "elem2":null, chance:0.5 },
"snail": { "elem2":"calcium", chance:0.1 },
"slug": { "elem2":null, chance:0.2 },
"worm": { "elem2":null, chance:0.2 },
"algae": { "elem2":null, chance:0.5 },
"oxygen": { "elem2":"carbon_dioxide", chance:0.5 },
},
temp: 19.1,
tempHigh: 41,
stateHigh: "meat",
tempLow: -18,
stateLow: "frozen_frog",
category:"life",
burn:75,
burnTime:30,
state: "solid",
density: 1450,
conduct: 0.2,
},
"frozen_frog": {
color: "#007349",
behavior: behaviors.STURDYPOWDER,
temp: -18,
tempHigh: 0,
stateHigh: "frog",
tempLow: -18,
stateLow: "frozen_frog",
category:"life",
hidden: true,
state: "solid",
density: 1500,
},
"fish": {
color: "#ac8650",
behavior: [
"XX|M2%5|SW:water,salt_water,sugar_water,dirty_water%7",
"XX|FX%1|BO",
"XX|M1|SW:water,salt_water,sugar_water,dirty_water%8",
],
reactions: {
"algae": { "elem2":null, chance:0.5 },
"plant": { "elem2":null, chance:0.125 },
"fly": { "elem2":null, chance:0.5 },
"firefly": { "elem2":null, chance:0.5 },
"worm": { "elem2":null, chance:0.25 },
"oxygen": { "elem2":"carbon_dioxide", chance:0.5 },
},
temp: 20,
tempHigh: 32,
stateHigh: "meat",
tempLow: -20,
stateLow: "frozen_meat",
category:"life",
burn:40,
burnTime:100,
state: "solid",
density: 1080,
conduct: 0.2,
},
"slug": {
color: ["#997e12","#403314","#997e12","#403314","#997e12","#403314","#997e12","#403314","#997e12","#403314","#997e12","#403314","#124a44"],
behavior: [
"XX|XX|XX",
"XX|FX%0.25|M2%0.5 AND BO",
"XX|M1|XX",
],
reactions: {
"salt": { "elem1": "slime", "elem2": null },
"plant": { "elem2":null, "chance":0.05 },
"worm": { "elem2":null, "chance":0.01 },
"mushroom_spore": { "elem2":null, "chance":0.05 },
"grass": { "elem2":null, "chance":0.05 },
"grass_seed": { "elem2":null, "chance":0.05 },
"algae": { "elem2":null, "chance":0.05 },
"mushroom_cap": { "elem2":null, "chance":0.05 },
"mushroom_stalk": { "elem2":null, "chance":0.05 },
"mushroom_gill": { "elem2":null, "chance":0.05 },
"hyphae": { "elem2":"dirt", "chance":0.05 },
"mycelium": { "elem2":"dirt", "chance":0.05 },
},
tempLow: 5,
stateLow: "slime",
tempHigh: 40,
stateHigh: "slime",
category: "life",
state: "solid",
density: 1450,
conduct: 0.17,
},
"snail": {
color: "#5c3104",
behavior: [
"XX|XX|XX",
"XX|FX%0.25|M2%0.5 AND BO",
"XX|M1|XX",
],
reactions: {
"salt": { "elem1": "calcium", "elem2": null },
"plant": { "elem2":null, "chance":0.05 },
"worm": { "elem2":null, "chance":0.01 },
"mushroom_spore": { "elem2":null, "chance":0.05 },
"grass": { "elem2":null, "chance":0.05 },
"grass_seed": { "elem2":null, "chance":0.05 },
"algae": { "elem2":null, "chance":0.05 },
"mushroom_cap": { "elem2":null, "chance":0.05 },
"mushroom_stalk": { "elem2":null, "chance":0.05 },
"mushroom_gill": { "elem2":null, "chance":0.05 },
"hyphae": { "elem2":"dirt", "chance":0.05 },
"mycelium": { "elem2":"dirt", "chance":0.05 },
},
tempLow: -6.4,
stateLow: "calcium",
tempHigh: 100,
stateHigh: "calcium",
category: "life",
state: "solid",
density: 1500,
conduct: 0.16,
},
"heater": {
color: "#881111",
behavior: [
"XX|HT:2|XX",
"HT:2|XX|HT:2",
"XX|HT:2|XX",
],
category:"machines",
insulate:true,
},
"cooler": {
color: "#111188",
behavior: [
"XX|CO:2|XX",
"CO:2|XX|CO:2",
"XX|CO:2|XX",
],
category:"machines",
insulate:true,
},
"superheater": {
color: "#dd1111",
behavior: [
"XX|HT:10|XX",
"HT:10|XX|HT:10",
"XX|HT:10|XX",
],
category:"machines",
insulate:true,
},
"freezer": {
color: "#1111dd",
behavior: [
"XX|CO:10|XX",
"CO:10|XX|CO:10",
"XX|CO:10|XX",
],
category:"machines",
insulate:true,
},
"torch": {
color: "#d68542",
behavior: [
"XX|CR:fire|XX",
"XX|XX|XX",
"XX|XX|XX",
],
reactions: {
"water": { "elem1":"wood" },
},
temp:600,
category:"special",
},
"spout": {
color: "#606378",
behavior: [
"XX|CR:water|XX",
"CR:water|XX|CR:water",
"XX|CR:water|XX",
],
category:"special",
tempHigh: 1455.5,
stateHigh: "molten_steel",
conduct: 0.42,
},
"udder": {
color: "#ecb3f5",
behavior: [
"XX|XX|XX",
"XX|XX|XX",
"XX|CR:milk%2.5|XX",
],
category:"special",
},
"bone_marrow": {
color: "#c97265",
behavior: [
"XX|CR:blood,bone,bone%5|XX",
"CR:blood,bone,bone%5|XX|CR:blood,bone,bone%5",
"XX|CR:blood,bone,bone%5|XX",
],
category:"life",
tempHigh: 750,
stateHigh: "calcium",
hidden: true,
},
"bone": {
color: "#d9d9d9",
behavior: behaviors.SUPPORT,
category:"life",
tempHigh: 760,
stateHigh: "calcium",
state: "solid",
density: 1900,
},
"antipowder": {
color: "#ebd1d8",
behavior: behaviors.AGPOWDER,
category:"special",
tempHigh: 1850,
stateHigh: "antimolten",
state: "solid",
density: 1850,
},
"antimolten": {
color: ["#ffb5b5","#ffd0b5","#ffd0b5"],
behavior: [
"M1|M1|M1",
"M2|XX|M2",
"XX|CR:antifire%2.5|XX",
],
temp: 1850,
tempLow: 1750,
stateLow: "antipowder",
viscosity: 10000,
hidden: true,
state: "liquid",
density: 1000,
},
"antifire": {
color: ["#ffc3a6","#ffdfa3","#ffb69e"],
behavior: [
"XX|M2|XX",
"M2|XX|M2",
"M1|M1|M1",
],
reactions: {
"antiliquid": { "elem1": "antigas" },
},
temp:600,
tempLow:100,
stateLow: "antigas",
tempHigh: 7000,
stateHigh: "plasma",
category: "special",
burning: true,
burnTime: 25,
burnInto: "antigas",
hidden: true,
state: "gas",
density: 0.2,
},
"antifluid": {
color: "#d1dbeb",
behavior: behaviors.AGLIQUID,
category:"special",
tempHigh: 100,
stateHigh: "antigas",
state: "liquid",
density: 1000,
},
"antigas": {
color: "#e6fffc",
behavior: behaviors.GAS,
category:"special",
tempLow: 100,
stateLow: "antifluid",
hidden: true,
state: "gas",
density: 0.1,
},
"vertical": {
color: "#d9d9d9",
behavior: [
"XX|M1|XX",
"CR:wall|XX|CR:wall",
"XX|XX|XX",
],
category:"special",
hidden:true,
},
"horizontal": {
color: "#d9d9d9",
behavior: [
"XX|CR:wall|XX",
"XX|XX|M1",
"XX|CR:wall|XX",
],
category:"special",
hidden:true,
},
"rocket": {
color: "#ff0000",
behavior: [
"XX|M1|XX",
"XX|DL%1|XX",
"CR:smoke|CR:fire|CR:smoke",
],
category: "special",
hidden:true,
state: "solid",
temp:700,
density: 7300,
conduct: 0.73,
tempHigh: 1455.5,
stateHigh: "molten_steel",
},
"ash": {
color: ["#8c8c8c","#9c9c9c"],
behavior: behaviors.POWDER,
reactions: {
"steam": { "elem1": "pyrocumulus", "chance":0.08, "y":[0,15] },
"rain_cloud": { "elem1": "pyrocumulus", "chance":0.08, "y":[0,15] },
"snow_cloud": { "elem1": "pyrocumulus", "chance":0.08, "y":[0,15] },
"acid_cloud": { "elem1": "pyrocumulus", "chance":0.05, "y":[0,15] },
"pyrocumulus": { "elem1": "pyrocumulus", "chance":0.08, "y":[0,15] },
},
category:"powders",
state: "solid",
density: 700,
},
"meat": {
color: ["#9E4839","#BA6449","#D2856C","#A14940"],
behavior: [
"XX|XX|XX",
"SP|CH:rotten_meat%0.005|SP",
"XX|M1|XX",
],
tempHigh: 80,
stateHigh: "cooked_meat",
tempLow: -18,
stateLow: "frozen_meat",
category:"life",
burn:25,
burnTime:200,
burnInto:"cooked_meat",
state: "solid",
density: 1019.5,
conduct: 0.2,
},
"rotten_meat": {
color: ["#9ab865","#b8b165","#b89765"],
behavior: [
"XX|CR:plague%0.25|XX",
"SP|XX|SP",
"XX|M1|XX",
],
tempHigh: 120,
stateHigh: "plague",
category:"life",
hidden: true,
burn:25,
burnTime:200,
burnInto:"plague",
state: "solid",
density: 1005,
conduct: 0.1,
},
"cooked_meat": {
color: ["#AE7D5B","#9B6D54","#7E4D31"],
behavior: behaviors.STURDYPOWDER,
tempHigh: 150,
stateHigh: "ash",
category:"life",
hidden:true,
burn:25,
burnTime:200,
burnInto: "ash",
state: "solid",
density: 1005,
},
"frozen_meat": {
color: "#65b8aa",
behavior: behaviors.STURDYPOWDER,
temp: -18,
tempHigh: 0,
stateHigh: "meat",
category:"life",
hidden:true,
state: "solid",
density: 1067.5,
},
"light": {
color: "#ffffa8",
behavior: [
"XX|XX|XX",
"XX|DL%5|M1 AND BO",
"XX|XX|XX",
],
rotatable: true,
temp: 40,
category: "energy",
},
"laser": {
color: "#ff0000",
behavior: [
"XX|XX|XX",
"XX|DL%0.25|M1 AND BO:1,2,3",
"XX|XX|XX",
],
rotatable: true,
temp: 40,
category: "energy",
},
"ball": {
color: "#e35693",
behavior: [
"XX|XX|XX",
"XX|FY:0%5|XX",
"XX|M1 AND BO|XX",
],
category: "energy",
flipY: false,
flippableY: true,
hidden: true,
},
"pointer": {
color: "#ff0000",
behavior: behaviors.SELFDELETE,
category:"tools",
hidden:true,
},
"charcoal": {
color: "#2b2b2b",
behavior: behaviors.POWDER,
burn: 25,
burnTime: 1000,
burnInto: "carbon_dioxide",
category: "powders",
state: "solid",
density: 208,
},
"hydrogen": {
color: "#558bcf",
behavior: behaviors.GAS,
reactions: {
"oxygen": { "elem1":null, "elem2":"steam" },
},
category: "gases",
burn: 100,
burnTime: 2,
tempLow: -252.8,
stateLow: "liquid_hydrogen",
state: "gas",
density: 0.08375,
},
"oxygen": {
color: "#99c7ff",
behavior: behaviors.GAS,
reactions: {
"copper": { "elem2":"oxidized_copper", chance:0.05 },
"iron": { "elem2":"rust", chance:0.025 },
},
category: "gases",
burn: 100,
burnTime: 2,
tempLow: -183.94,
stateLow: "liquid_oxygen",
state: "gas",
density: 1.292,
},
"nitrogen": {
color: "#b8d1d4",
behavior: behaviors.GAS,
reactions: {
"oxygen": { "elem1":null, "elem2":"anesthesia" },
"hydrogen": { "elem1":null, "elem2":"ammonia" },
},
category: "gases",
tempLow: -195.8,
stateLow: "liquid_nitrogen",
state: "gas",
density: 1.165,
},
"anesthesia": {
color: "#d3e1e3",
behavior: behaviors.GAS,
category: "liquids",
tempLow: -88.48,
stateLow: ["nitrogen","oxygen"],
hidden: true,
state: "liquid",
density: 1.9781,
},
"ammonia": {
color: "#bab6a9",
behavior: behaviors.GAS,
reactions: {
"methane": { "elem1":null, "elem2":"cyanide", "chance":0.25 },
"plant": { "elem1":"plant", "chance":0.05 },
"wheat_seed": { "elem1":"wheat", "chance":0.05 },
"grass": { "elem1":"grass", "chance":0.05 },
"grass_seed": { "elem1":"grass", "chance":0.05 },
"bamboo_plant": { "elem1":"bamboo", "chance":0.05 },
"flower_seed": { "elem1":"flower_seed", "chance":0.05 },
"petal": { "elem1":"flower_seed", "chance":0.05 },
"vine": { "elem1":"vine", "chance":0.05 },
"sapling": { "elem1":"tree_branch", "chance":0.05 },
"tree_branch": { "elem1":"tree_branch", "chance":0.05 },
"corn_seed": { "elem1":"corn", "chance":0.05 },
"root": { "elem1":"root", "chance":0.05 },
"dirt": { "elem1":"grass", "chance":0.05 },
"mud": { "elem1":"grass", "chance":0.05 },
"potato_seed": { "elem1":"potato", "chance":0.05 },
"yeast": { "elem1":"yeast", "chance":0.05 },
"fish": { "elem2":"meat" },
"frog": { "elem2":"meat" },
},
category: "gases",
state: "gas",
density: 0.73,
},
"carbon_dioxide": {
color: "#2f2f2f",
behavior: behaviors.GAS,
reactions: {
"plant": { "elem1":"oxygen" },
"algae": { "elem1":"oxygen" },
},
category: "gases",
tempLow: -78.5,
stateLow: "dry_ice",
state: "gas",
density: 1.977,
},
"oil": {
color: "#300000",
behavior: behaviors.LIQUID,
category: "liquids",
tempHigh: 400,
stateHigh: "fire",
burn: 100,
burnTime: 30,
burnInto: ["carbon_dioxide","fire"],
viscosity: 250,
state: "liquid",
density: 825,
},
"lamp_oil": {
color: "#b3b38b",
behavior: behaviors.LIQUID,
category: "liquids",
tempHigh: 2100,
stateHigh: "fire",
burn: 95,
burnTime: 2000,
burnInto: ["carbon_dioxide","fire"],
viscosity: 3,
state: "liquid",
density: 850,
},
"propane": {
color: "#cfcfcf",
behavior: behaviors.GAS,
category: "gases",
tempHigh: 400,
stateHigh: "fire",
burn: 100,
burnTime: 5,
fireColor: ["#00ffff","#00ffdd"],
state: "gas",
density: 2.0098,
},
"methane": {
color: "#9f9f9f",
behavior: behaviors.GAS,
category: "gases",
tempHigh: 400,
stateHigh: "fire",
burn: 85,
burnTime: 5,
fireColor: ["#00ffff","#00ffdd"],
state: "gas",
density: 0.554,
},
"tinder": {
color: ["#917256","#87684F","#735F4A","#5D4C3E","#4B3A2E"],
behavior: behaviors.STURDYPOWDER,
category: "energy",
tempHigh: 400,
stateHigh: "fire",
burn: 50,
burnTime: 100,
state: "solid",
density: 23,
},
"static": {
color: ["#ffffff","#888888","#000000"],
behavior: [
"XX|XX|XX",
"XX|CC:ffffff,9c9c9c,454545|XX",
"XX|XX|XX",
],
category: "special",
},
"clay": {
color: "#d4c59c",
behavior: behaviors.SUPPORT,
tempHigh: 135,
stateHigh: "baked_clay",
category: "land",
state: "solid",
density: 1760,
},
"clay_soil": {
color: ["#F49A6F","#AB7160","#B56C52"],
behavior: [
"XX|XX|XX",
"XX|XX|XX",
"M2%25|M1|M2%25",
],
reactions: {
"water": { "elem1":"clay", "elem2":null },
},
tempHigh: 140,
stateHigh: "baked_clay",
category: "land",
state: "solid",
density: 1600,
},
"baked_clay": {
color: "#b85746",
behavior: behaviors.SUPPORT,
category: "powders",
state: "solid",
density: 2000,
},
"brick": {
color: "#cb4141",
behavior: behaviors.WALL,
category: "solids",
tempHigh: 1540,
state: "solid",
density: 1650,
hardness: 0.33,
},
"sapling": {
color: "#3e9c3e",
behavior: [
"XX|M2%2|XX",
"XX|L2:wood,tree_branch%80|XX",
"XX|M1|XX",
],
tempHigh: 400,
stateHigh: "fire",
burn: 65,
burnTime: 15,
category: "life",
state: "solid",
density: 1500,
},
"grass_seed": {
color: ["#439809","#258B08","#118511","#127B12","#136D14"],
behavior: [
"XX|M2%0.05|XX",
"XX|L2:grass|XX",
"XX|M1|XX",
],
tempHigh: 400,
stateHigh: "fire",
burn: 50,
burnTime: 20,
category: "life",
state: "solid",
density: 1400,
},
"wheat_seed": {
color: "#b6c981",
behavior: [
"XX|M2%0.25|XX",
"XX|L2:wheat AND C2:wheat%30|XX",
"XX|M1|XX",
],
tempHigh: 400,
stateHigh: "fire",
burn: 50,
burnTime: 20,
category: "life",
state: "solid",
density: 769,
},
"wheat": {
color: "#c9bc81",
behavior: behaviors.WALL,
reactions: {
"rock": { "elem1":"flour", "elem2":"rock" }
},
tempHigh: 400,
stateHigh: "fire",
burn:40,
burnTime:25,
category:"life",
hidden:true,
state: "solid",
density: 769,
},
"straw": {
color: ["#E9D391","#A3835E","#B79A73"],
behavior: behaviors.WALL,
tempHigh: 400,
stateHigh: "fire",
burn: 60,
burnTime: 40,
category: "powders",
state: "solid",
density: 67.5,
},
"pollen": {
color: "#ffffc0",
behavior: [
"XX|XX|XX",
"XX|CH:flower_seed%0.01|XX",
"M2|M1|M2",
],
reactions: {
"sugar_water": { "elem1": null, "elem2": "honey" },
},
category:"life",
hidden: true,
tempHigh: 400,
stateHigh: "ash",
burn:50,
burnTime:20,
state: "solid",
density: 1435,
},
"flower_seed": {
color: "#0e990e",
behavior: [
"XX|M2%1.5|XX",
"XX|L2:grass AND C2:pistil%30|XX",
"XX|M1|XX",
],
tempHigh: 400,
stateHigh: "fire",
burn:50,
burnTime:20,
category:"life",
state: "solid",
density: 1400,
},
"pistil": {
color: "#734e39",
behavior: [
"XX|CR:petal%10|XX",
"CR:petal%10|XX|CR:petal%10",
"XX|XX|XX",
],
tempHigh: 400,
stateHigh: "fire",
burn:50,
burnTime:20,
category:"life",
hidden: true,
state: "solid",
density: 1400,
},
"petal": {
color: "#ff0000",
behavior: behaviors.WALL,
tempHigh: 400,
stateHigh: "fire",
burn:50,
burnTime:20,
category:"life",
hidden: true,
state: "solid",
density: 1400,
},
"tree_branch": {
color: "#a0522d",
behavior: [
"CR:plant,tree_branch%2|CR:plant,plant,plant,tree_branch%2|CR:plant,tree_branch%2",
"XX|XX|XX",
"XX|XX|XX",
],
tempHigh: 400,
stateHigh: "fire",
category: "solids",
burn: 40,
burnTime: 50,
burnInto: ["ash","charcoal","fire"],
hidden: true,
state: "solid",
density: 1500,
},
"vine": {
color: "#005900",
behavior: [
"XX|SP|XX",
"XX|XX|XX",
"XX|CL%1 AND M1|XX",
],
tempHigh: 400,
stateHigh: "fire",
burn: 35,
burnTime: 100,
category: "life",
state: "solid",
density: 1050,
},
"bamboo": {
color: ["#7CC00C","#77A012"],
behavior: behaviors.WALL,
tempHigh: 400,
stateHigh: "fire",
burn: 10,
burnTime: 200,
category: "life",
state: "solid",
density: 686,
},
"bamboo_plant": {
color: ["#FBC882","#DFAD64"],
behavior: [
"XX|M2%0.25|XX",
"XX|L2:bamboo AND C2:bamboo%10|XX",
"XX|M1|XX",
],
tempHigh: 400,
stateHigh: "fire",
burn: 30,
burnTime: 100,
category: "life",
state: "solid",
density: 686,
},
"burner": {
color: "#d6baa9",
behavior: [
"CR:propane|CR:propane|CR:propane",
"XX|XX|XX",
"XX|XX|XX",
],
category: "machines",
conduct: 0.73,
},
"foam": {
color: "#cad2e3",
behavior: behaviors.FOAM,
category: "liquids",
state: "gas",
density: 40,
},
"bubble": {
color: "#afc7fa",
behavior: behaviors.BUBBLE,
category: "liquids",
state: "gas",
density: 1.294,
},
"rainbow": {
color: ["#ff0000","#ff8800","#ffff00","#00ff00","#00ffff","#0000ff","#ff00ff"],
behavior: [
"XX|XX|XX",
"XX|CC:ff0000,ff8800,ffff00,00ff00,00ffff,0000ff,ff00ff|XX",
"XX|XX|XX",
],
category: "special",
},
"acid": {
color: ["#b5cf91","#a1ff5e","#288f2a"],
behavior: [
"XX|DB%5|XX",
"DB%5 AND M2|XX|DB%5 AND M2",
"DB%5 AND M2|DB%10 AND M1|DB%5 AND M2",
],
ignore: ["glass","glass_shard","baked_clay"],
category: "liquids",
tempHigh: 400,
stateHigh: "fire",
burn: 30,
burnTime: 1,
state: "liquid",
density: 1049,
},
"acid_gas": {
color: ["#c0d1a7","#c2ff96","#58a659"],
behavior: [
"M1|DB%5 AND M1|M1",
"DB%5 AND M1|XX|DB%5 AND M1",
"DB%5 AND M1|DB%10 AND M1|DB%5 AND M1",
],
ignore: ["glass","glass_shard","baked_clay"],
reactions: {
"acid_gas": { "elem1": null, "elem2": "acid_cloud", "chance":0.3, "y":[0,15] },
"rain_cloud": { "elem1": null, "elem2": "acid_cloud", "chance":0.4, "y":[0,15] },
"snow_cloud": { "elem1": null, "elem2": "acid_cloud", "chance":0.4, "y":[0,15] },
"pyrocumulus": { "elem1": null, "elem2": "acid_cloud", "chance":0.4, "y":[0,15] },
"fire_cloud": { "elem1": null, "elem2": "acid_cloud", "chance":0.4, "y":[0,15] },
},
category: "gases",
tempHigh: 400,
stateHigh: "fire",
burn: 30,
burnTime: 1,
state: "gas",
density: 1.63,
},
"glue": {
color: "#f0f0f0",
behavior: behaviors.STICKY,
tempHigh: 475,
stateHigh: ["cyanide","dioxin"],
category: "liquids",
state: "liquid",
density: 1300,
},
"gray_goo": {
color: "#c0c0c0",
behavior: [
"XX|CH:gray_goo|XX",
"CH:gray_goo|DL%5|CH:gray_goo",
"XX|CH:gray_goo AND M1|XX",
],
category: "special",
state: "solid",
density: 21450,
},
"clone_powder": {
color: "#f0f000",
behavior: [
"XX|CF|XX",
"CF|XX|CF",
"M2|CF AND M1|M2",
],
category:"machines",
insulate:true,
state:"solid",
density:2710,
hardness: 1,
},
"floating_cloner": {
color: "#c7c787",
behavior: [
"XX|CF%3 AND M1%10|XX",
"CF%3 AND M1%10|XX|CF%3 AND M1%10",
"XX|CF%3 AND M1%10|XX",
],
category:"machines",
insulate:true,
state:"solid",
density:1355,
hardness: 1,
},
"virus": {
color: "#cc00ff",
behavior: [
"XX|CH:virus%25|XX",
"CH:virus%25|XX|CH:virus%25",
"XX|CH:virus%25 AND M1|XX",
],
category: "special",
state: "solid",
density: 600,
},
"permafrost": {
color: ["#557d65","#557d79"],
behavior: behaviors.SUPPORT,
temp: -50,
tempHigh: 0,
stateHigh: "mud",
category: "land",
state: "solid",
density: 700,
},
"cheese": {
color: "#fcba03",
behavior: behaviors.STURDYPOWDER,
tempHigh: 54,
stateHigh: "melted_cheese",
category: "food",
state: "solid",
density: 1153,
},
"melted_cheese": {
color: "#fcdb53",
behavior: behaviors.LIQUID,
tempLow: 0,
stateLow: "cheese",
category: "liquids",
viscosity: 112,
hidden: true,
state: "liquid",
density: 1153,
},
"fireball": {
color: ["#782828","#783b28","#784b28"],
behavior: [
"XX|CR:fire%25|XX",
"XX|CC:782828,783b28,784b28%25|XX",
"M2|M1|M2",
],
reactions: {
"water": { "elem1":"rock", "elem2":"steam" }
},
category: "special",
temp:600,
tempHigh: 1900,
stateHigh: "magma",
tempLow: -100,
stateLow: "rock",
burning: true,
burnInto: ["rock","rock","steam"],
burnTime: 170,
burn: 100,
state: "solid",
density: 1600,
},
"mushroom_spore": {
color: ["#d1d1d1","#d4cfa9","#b4d4ae","#b98aba","#805236"],
behavior: [
"XX|M2%1.5|XX",
"XX|L2:mushroom_stalk AND C2:mushroom_gill%20|XX",
"XX|M1|XX",
],
reactions: {
"wood": { "elem2":"dirt", "chance":0.04 },
"tree_brake": { "elem2":"dirt", "chance":0.04 },
"plant": { "elem2":"dirt", "chance":0.07 },
"root": { "elem2":"dirt", "chance":0.07 },
"grass": { "elem2":"dirt", "chance":0.08 },
"grass_seed": { "elem2":"dirt", "chance":0.08 },
},
category: "life",
tempHigh: 225,
stateHigh: "fire",
burn: 10,
burnTime: 20,
state: "solid",
density: 123.6,
},
"mushroom_stalk": {
color: "#d1d1d1",
behavior: [
"XX|XX|XX",
"XX|XX|XX",
"XX|CH:dirt>hyphae%1 AND M1|XX",
],
reactions: {
"wood": { "elem2":"dirt", "chance":0.04 },
"tree_brake": { "elem2":"dirt", "chance":0.04 },
"plant": { "elem2":"dirt", "chance":0.07 },
"root": { "elem2":"dirt", "chance":0.07 },
"grass": { "elem2":"dirt", "chance":0.08 },
"grass_seed": { "elem2":"dirt", "chance":0.08 },
},
category: "life",
hidden: true,
tempHigh: 225,
stateHigh: "fire",
burn: 10,
burnTime: 65,
state: "solid",
density: 90.445,
},
"mushroom_gill": {
color: "#d4cfa9",
behavior: [
"XX|CR:mushroom_cap%10|XX",
"CR:mushroom_gill,mushroom_cap%2|XX|CR:mushroom_gill,mushroom_cap%2",
"XX|XX|XX",
],
category: "life",
hidden: true,
tempHigh: 225,
stateHigh: "fire",
burn: 10,
burnTime: 65,
burnInto: "mushroom_spore",
state: "solid",
density: 90.445,
},
"mushroom_cap": {
color: ["#c74442","#c74442","#c74442","#c74442","#c74442","#c74442","#cfb4b4"],
behavior: behaviors.WALL,
category: "life",
hidden: true,
tempHigh: 225,
stateHigh: "fire",
burn: 10,
burnTime: 65,
burnInto: "mushroom_spore",
state: "solid",
density: 90.445,
},
"hyphae": {
color: "#c79789",
behavior: [
"CH:dirt>hyphae,hyphae,mycelium%0.5|CR:mushroom_spore%0.5|CH:dirt>hyphae,hyphae,mycelium%0.5",
"CH:mycelium%0.5|XX|CH:mycelium%0.5",
"CH:dirt>hyphae,hyphae,mycelium%0.5|XX|CH:dirt>hyphae,hyphae,mycelium%0.5",
],
reactions: {
"wood": { "elem2":"dirt", "chance":0.04 },
"tree_brake": { "elem2":"dirt", "chance":0.04 },
"plant": { "elem2":"dirt", "chance":0.07 },
"root": { "elem2":"dirt", "chance":0.07 },
"grass": { "elem2":"dirt", "chance":0.08 },
"grass_seed": { "elem2":"dirt", "chance":0.08 },
},
category: "life",
hidden: true,
tempHigh: 225,
stateHigh: "fire",
burn: 30,
burnTime: 20,
state: "solid",
density: 462,
},
"mycelium": {
color: ["#734d5e","#b5949f","#734d53"],
behavior: behaviors.POWDER,
tempHigh:225,
stateHigh: "dirt",
tempLow: -50,
stateLow: "permafrost",
burn: 20,
burnTime: 40,
burnInto: "dirt",
category:"land",
state: "solid",
density: 462,
},
"lichen": {
color: ["#b6d6c3","#769482"],
behavior: [
"XX|ST:wood AND M2%0.1|XX",
"ST:wood AND M2%0.1|L2:lichen|ST:wood AND M2%0.1",
"XX|M1 AND M2%0.1|XX",
],
tempHigh: 400,
stateHigh: "fire",
burn: 50,
burnTime: 20,
category: "life",
state: "solid",
density: 1.5,
},
"antimatter": {
color: "#a89ba8",
behavior: [
"M2|DB%50 AND M2|M2",
"M1|XX|M1",
"M1|DB%50 AND M1|M1",
],
category: "special",
state: "gas",
},
"plastic": {
color: "#c5dede",
behavior: behaviors.WALL,
tempHigh: 250,
burn: 10,
burnTime: 200,
burnInto: "dioxin",
category: "solids",
state: "solid",
density: 1052,
},
"fuse": {
color: "#825d38",
behavior: behaviors.WALL,
tempHigh: 500,
stateHigh: "fire",
burn: 100,
burnTime: 1,
category: "solids",
state: "solid",
density: 1000,
},
"dioxin": {
color: "#b8b8b8",
behavior: behaviors.GAS,
category: "gases",
hidden: true,
state: "gas",
density: 1830,
},
"insulation": {
color: "#b8aea5",
behavior: behaviors.WALL,
category: "solids",
insulate: true,
state: "solid",
},
"iron": {
color: ["#cbcdcd","#bdbdbd"],
behavior: behaviors.WALL,
reactions: {
"water": { "elem1":"rust", chance:0.0025 },
"salt_water": { "elem1":"rust", chance:0.005 },
"dirty_water": { "elem1":"rust", chance:0.04 },
"sugar_water": { "elem1":"rust", chance:0.0035 },
},
tempHigh: 1538,
category: "solids",
density: 7860,
conduct: 0.47,
},
"rust": {
color: ["#AE551C","#BC6E39","#925F49"],
behavior: behaviors.SUPPORT,
tempHigh: 1538,
stateHigh: "molten_iron",
category: "solids",
state: "solid",
density: 5250,
conduct: 0.37,
},
"copper": {
color: ["#A95232","#BE4322","#C76035"],
behavior: [
"XX|XX|XX",
"XX|CH:oxidized_copper%0.001|XX",
"XX|XX|XX",
],
reactions: {
"water": { "elem1":"oxidized_copper", chance:0.0025 },
"salt_water": { "elem1":"oxidized_copper", chance:0.005 },
"dirty_water": { "elem1":"oxidized_copper", chance:0.04 },
"sugar_water": { "elem1":"oxidized_copper", chance:0.0035 },
},
category: "solids",
tempHigh: 1085,
density: 8960,
conduct: 0.95,
},
"oxidized_copper": {
color: ["#406555","#42564A","#517364"],
behavior: [
"XX|XX|XX",
"XX|XX|XX",
"XX|XX|XX",
],
category: "solids",
hidden: true,
tempHigh: 1085,
stateHigh: "molten_copper",
density: 8960,
conduct: 0.85,
},
"zinc": {
color: ["#7C7A7B","#9D9D9F","#F8F8F3"],
behavior: behaviors.WALL,
tempHigh: 419.53,
category: "solids",
density: 7068,
conduct: 0.53,
},
"tin": {
color: ["#9E9D98","#AEADA4"],
behavior: behaviors.WALL,
tempHigh: 231.9,
category: "solids",
density: 7260,
conduct: 0.45,
},
"nickel": {
color: "#727472",
behavior: behaviors.WALL,
tempHigh: 1455,
category: "solids",
density: 8900,
conduct: 0.51,
},
"silver": {
color: "#CACACA",
behavior: behaviors.WALL,
tempHigh: 961.8,
category: "solids",
density: 10497,
conduct: 0.99,
},
"gold": {
color: ["#FFF0B5","#986A1A","#F0BB62"],
behavior: behaviors.WALL,
tempHigh: 1064,
category: "solids",
density: 19300,
conduct: 0.81,
},
"gold_coin": {
color: ["#FFF0B5","#986A1A","#F0BB62"],
behavior: behaviors.POWDER,
tempHigh: 1064,
stateHigh: "molten_gold",
category: "powders",
state: "solid",
density: 19300,
conduct: 0.78,
},
"aluminum": {
color: ["#D1C6BE","#B5C0AD","#B9B8BC"],
behavior: behaviors.WALL,
tempHigh: 660.3,
category: "solids",
density: 2710,
conduct: 0.73,
},
"lead": {
color: "#6c6c6a",
behavior: behaviors.WALL,
tempHigh: 327.5,
category: "solids",
density: 11343,
conduct: 0.41,
},
"brass": {
color: ["#cb9e5d","#865e39"],
behavior: behaviors.WALL,
tempHigh: 927,
category: "solids",
density: 8550,
conduct: 0.52,
},
"bronze": {
color: "#cd7f32",
behavior: behaviors.WALL,
tempHigh: 913,
category: "solids",
density: 8150,
conduct: 0.44,
},
"sterling": {
color: ["#858478","#eae8e2","#bfbcb7"],
behavior: behaviors.WALL,
tempHigh: 802,
category: "solids",
density: 10375.25,
conduct: 0.95,
},
"steel": {
color: "#71797E",
behavior: behaviors.WALL,
tempHigh: 1455.5,
category: "solids",
density: 7850,
conduct: 0.42,
hardness: 0.8,
},
"rose_gold": {
color: ["#B76E79","#a1334d","#f06283"],
behavior: behaviors.WALL,
tempHigh: 897,
category: "solids",
density: 12900,
conduct: 0.87,
},
"solder": {
color: "#a1a19d",
behavior: behaviors.WALL,
tempHigh: 200,
category: "solids",
density: 8885,
conduct: 0.43,
},
"molten_copper": {
reactions: {
"molten_zinc": { "elem1": null, "elem2": "molten_brass" },
"molten_tin": { "elem1": null, "elem2": "molten_bronze" },
"molten_silver": { "elem1": null, "elem2": "molten_sterling" },
"molten_gold": { "elem1": null, "elem2": "molten_rose_gold" },
}
},
"molten_iron": {
reactions: {
"charcoal": { "elem1": "molten_steel", "elem2": null },
"diamond": { "elem1": "molten_steel", "elem2": null },
"carbon_dioxide": { "elem1": "molten_steel", "elem2": null },
}
},
"molten_tin": {
reactions: {
"molten_lead": { "elem1": null, "elem2": "molten_solder" },
}
},
"milk": {
color: "#fafafa",
behavior: behaviors.LIQUID,
tempHigh: 93,
stateHigh: "yogurt",
viscosity: 1.5,
category: "liquids",
state: "liquid",
density: 1036.86,
},
"yogurt": {
color: "#f0efe6",
behavior: behaviors.STURDYPOWDER,
category: "food",
state: "liquid",
density: 820.33,
},
"vinegar": {
color: "#ffecb3",
behavior: behaviors.LIQUID,
reactions: {
"milk": { "elem1": null, "elem2": "cheese" },
"baking_soda": { "elem1": "carbon_dioxide", "elem2": "sodium_acetate" },
"rust": { "elem2":"iron", chance:0.05 },
"oxidized_copper": { "elem2":"copper", chance:0.05 },
},
viscosity: 12,
tempHigh: 100.6,
stateHigh: "steam",
category: "liquids",
state: "liquid",
density: 1006,
},
"baking_soda": {
color: "#ededed",
behavior: behaviors.POWDER,
category: "powders",
state: "solid",
density: 1000,
},
"sodium_acetate": {
color: ["#ededed","#dbdbdb"],
behavior: behaviors.POWDER,
hidden: true,
state: "solid",
density: 900,
},
"yeast": {
color: ["#AD9166","#9A7F4E","#D8BB8D"],
behavior: [
"XX|CL:50%20|XX",
"CL:50%20 AND SW:bread%30|XX|CL:50%20 AND SW:bread%30",
"XX|M1|XX",
],
reactions: {
"bread": { "elem1": "bread" },
"sugar": { "elem2": "alcohol" },
"potato": { "elem2": "alcohol" },
},
tempHigh: 100,
stateHigh: "bread",
burn: 50,
burnTime: 20,
burnInto: "ash",
category: "food",
state: "solid",
density: 1180,
},
"corn": {
color: ["#F8D223","#D6BA2A","#f7f5ba","#DBD281","#CDB12D"],
behavior: behaviors.WALL,
category: "food",
burn: 10,
burnTime: 200,
tempHigh: 180,
stateHigh: "popcorn",
state: "solid",
density: 721,
},
"popcorn": {
color: ["#a6a076","#ebe4ab","#ebe4ab","#ebe4ab","#ebe4ab","#ebe4ab","#ebe4ab","#c99947"],
behavior: behaviors.POWDER,
category: "food",
burn: 20,
burnTime: 200,
burnInto: ["fire","ash"],
state: "solid",
density: 360.5,
},
"corn_seed": {
color: ["#F2B813","#F9E3BA"],
behavior: [
"XX|M2%0.25|XX",
"XX|L2:plant,corn AND C2:corn%30|XX",
"XX|M1|XX",
],
tempHigh: 400,
stateHigh: "fire",
burn: 50,
burnTime: 20,
category: "life",
state: "solid",
density: 721,
},
"potato_seed": {
color: ["#CDA57F","#AA7437","#BC9563"],
behavior: [
"XX|CH:dirt>root|XX",
"CH:dirt>potato%5|CH:potato%1|CH:dirt>potato%5",
"XX|SW:dirt%3 AND M1|XX",
],
tempHigh: 400,
stateHigh: "fire",
burn: 50,
burnTime: 20,
category: "life",
state: "solid",
density: 675,
},
"potato": {
color: ["#d99857","#d98757","#a66933"],
behavior: behaviors.STURDYPOWDER,
tempHigh: 400,
stateHigh: "ash",
burn: 50,
burnTime: 20,
burnInto: "ash",
category: "food",
state: "solid",
density: 675,
},
"root": {
color: "#7B6F6B",
behavior: behaviors.WALL,
reactions: {
"rock": { "elem2":"sand", "chance":0.0004 },
},
tempHigh: 400,
stateHigh: "fire",
burn: 50,
burnTime: 20,
burnInto: "dirt",
category: "life",
state: "solid",
density: 1250,
},
"bread": {
color: "#F2CF99",
behavior: behaviors.STURDYPOWDER,
tempHigh: 176,
stateHigh: "toast",
category: "food",
burn: 30,
burnTime: 200,
burnInto: "ash",
state: "solid",
density: 233.96,
},
"toast": {
color: "#C08655",
behavior: behaviors.STURDYPOWDER,
tempHigh: 500,
stateHigh: "ash",
category: "food",
burn: 50,
burnTime: 170,
burnInto: "ash",
state: "solid",
density: 233.96,
},
"flour": {
color: "#F0E2B7",
behavior: behaviors.POWDER,
reactions: {
"water": { "elem1": "dough", "elem2": null },
},
category: "powders",
tempHigh: 400,
stateHigh: "fire",
burn:40,
burnTime:25,
state: "solid",
density: 600,
},
"dough": {
color: "#EDD8BA",
behavior: behaviors.SUPPORT,
category: "food",
tempHigh: 94,
stateHigh: "bread",
burn:40,
burnTime:25,
burnInto:"ash",
state: "solid",
density: 526.9,
},
"salt": {
color: ["#f2f2f2","#e0e0e0"],
behavior: behaviors.POWDER,
reactions: {
"ice": { "elem1":null, "elem2":"salt_water", "chance":0.1 },
"snow": { "elem1":null, "elem2":"salt_water", "chance":0.25 },
"packed_snow": { "elem1":null, "elem2":"salt_water", "chance":0.05 },
"packed_ice": { "elem1":null, "elem2":"salt_water", "chance":0.01 },
},
category: "powders",
tempHigh: 801,
state: "solid",
density: 2160,
},
"sugar": {
color: "#f2f2f2",
behavior: behaviors.POWDER,
category: "powders",
tempHigh: 186,
stateHigh: "caramel",
state: "solid",
density: 1590,
},
"candy": {
color: "#e6cab1",
behavior: behaviors.WALL,
tempHigh: 186,
stateHigh: "caramel",
category: "food",
state: "solid",
density: 900,
},
"dry_ice": {
color: "#e6e6e6",
behavior: behaviors.WALL,
category: "solids",
temp: -78.5,
tempHigh: -78.5,
stateHigh: "carbon_dioxide",
state: "solid",
density: 1562,
},
"alcohol": {
color: "#c9c5b1",
behavior: behaviors.LIQUID,
viscosity: 1,
tempHigh: 78,
stateHigh: ["steam","carbon_dioxide"],
burn: 100,
burnTime: 3,
fireColor: ["#80ACF0","#96CDFE","#bee6d4"],
category: "liquids",
state: "liquid",
density: 785.1,
},
"basalt": {
color: ["#2e2e2e","#333333","#3d3d3d"],
behavior: behaviors.STURDYPOWDER,
tempHigh: 1262.5,
stateHigh: "magma",
category: "land",
state: "solid",
density: 3000,
hardness: 0.65,
},
"soap": {
color: "#f2f2f2",
behavior: [
"XX|CR:bubble%0.25|XX",
"M2|XX|M2",
"M2|M1|M2",
],
reactions: {
"rust": { "elem2": "iron" },
"oxidized_copper": { "elem2": "copper" },
"blood": { "elem2": "water" },
"dirty_water": { "elem2": "water" },
"salt_water": { "elem2": "water" },
"oxygen": { "elem2": "bubble" },
"plague": { "elem2": null },
"virus": { "elem2": null },
"infection": { "elem2": null },
"mushroom_spore": { "elem2": null },
"lichen": { "elem2": null },
"rotten_meat": { "elem2": "meat" },
"acid_gas": { "elem2": "hydrogen" },
"carbon_dioxide": { "elem2": "oxygen" },
"acid": { "elem2": "hydrogen" },
"acid_cloud": { "elem2": "rain_cloud" },
},
tempHigh: 100,
stateHigh: "bubble",
viscosity: 500,
state: "liquid",
category:"liquids",
density: 1055,
},
"blood": {
color: "#ff0000",
behavior: behaviors.LIQUID,
reactions: {
"vaccine": { "elem1":"antibody", "elem2":null },
"plague": { "elem1":"infection", "elem2":null },
"virus": { "elem1":"infection", "elem2":null },
"cancer": { "elem1":"infection" },
"cyanide": { "elem1":"infection", "elem2":null },
"mushroom_spore": { "elem1":"infection", "elem2":null },
"dirty_water": { "elem1":"infection", "elem2":null },
"rust": { "elem1":"infection", "chance":0.05 },
"oxidized_copper": { "elem1":"infection", "chance":0.05 },
"rat": { "elem1":"infection", "chance":0.075 },
"flea": { "elem1":"infection", "chance":0.03 },
},
viscosity: 10,
tempHigh: 124.55,
stateHigh: ["steam","salt","oxygen"],
category:"liquids",
state: "liquid",
density: 1060,
},
"vaccine": {
color: "#e0d0ad",
behavior: behaviors.LIQUID,
reactions: {
"infection": { "elem1":null, "elem2":"antibody", "chance":0.1 },
"antibody": { "elem1":null, "chance":0.0025 },
"plague": { "elem2":null, "chance":0.1 },
"virus": { "elem2":null, "chance":0.1 },
"cancer": { "elem2":null, "chance":0.01 },
},
viscosity: 2.6,
tempHigh: 124.55,
stateHigh: "steam",
category:"liquids",
state: "liquid",
density: 1125,
},
"antibody": {
color: "#ff4040",
behavior: behaviors.LIQUID,
reactions: {
"blood": { "elem2":"antibody", "chance":0.01 },
"infection": { "elem2":"antibody", "chance":0.1 },
"cancer": { "elem2":null, "chance":0.01 },
},
viscosity: 6.3,
tempHigh: 124.55,
stateHigh: ["steam","salt","oxygen"],
category:"liquids",
hidden: true,
state: "liquid",
density: 1060,
},
"infection": {
color: "#cf005d",
behavior: behaviors.LIQUID,
reactions: {
"blood": { "elem2":"infection", "chance":0.01 },
"frog": { "elem2":"rotten_meat", "chance":0.005 },
"fish": { "elem2":"rotten_meat", "chance":0.005 },
"meat": { "elem2":"rotten_meat", "chance":0.005 },
},
viscosity: 15,
tempHigh: 124.55,
stateHigh: ["plague","plague","plague","salt","oxygen"],
category:"liquids",
hidden: true,
state: "liquid",
density: 1060,
},
"honey": {
color: ["#F6CE1A","#E79001","#BB5503"],
behavior: behaviors.LIQUID,
viscosity: 10000,
tempHigh: 71.11,
stateHigh: "caramel",
category:"liquids",
state: "liquid",
density: 1420,
},
"caramel": {
color: "#e89a51",
behavior: behaviors.LIQUID,
reactions: {
"fire": { "elem1": "molasses" },
},
viscosity: 500,
temp: 40,
tempLow: 24,
stateLow: "candy",
tempHigh: 204.44,
stateHigh: "fire",
category: "liquids",
state: "liquid",
density: 850,
},
"molasses": {
color: ["#210c06","#170804"],
behavior: behaviors.LIQUID,
viscosity: 7500,
tempHigh: 1000,
stateHigh: ["fire","sugar","steam"],
category:"liquids",
state: "liquid",
density: 1600,
},
"ketchup": {
color: "#ff3119",
behavior: behaviors.LIQUID,
viscosity: 50000,
tempHigh: 260,
stateHigh: ["vinegar","steam","salt","sugar"],
category:"liquids",
state: "liquid",
density: 1235,
},
"chocolate_syrup": {
color: "#3b160b",
behavior: behaviors.LIQUID,
tempLow: 0,
stateLow: "chocolate",
category: "liquids",
viscosity: 40,
state: "liquid",
density: 1325,
},
"liquid_hydrogen": {
color: "#97afcf",
behavior: behaviors.LIQUID,
reactions: {
"liquid_oxygen": { "elem1":"ice", "elem2":null },
"oxygen": { "elem1":"ice", "elem2":null },
},
category: "liquids",
burn: 100,
burnTime: 2,
temp:-252.8,
tempHigh: -252.8,
stateHigh: "hydrogen",
state: "liquid",
density: 71,
},
"liquid_oxygen": {
color: "#00ad99",
behavior: behaviors.LIQUID,
reactions: {
"hydrogen": { "elem1":"ice", "elem2":null },
},
category: "liquids",
burn: 100,
burnTime: 2,
temp:-182.94,
tempHigh: -182.94,
stateHigh: "oxygen",
state: "liquid",
density: 1141,
},
"liquid_nitrogen": {
color: "#d3e1e3",
behavior: behaviors.LIQUID,
category: "liquids",
temp:-195.8,
tempHigh: -195.8,
stateHigh: "nitrogen",
state: "liquid",
density: 804,
},
"calcium": {
color: ["#515053","#7a787d","#748193","#FEF9FF","#748193","#7a787d","#515053"],
behavior: behaviors.POWDER,
tempHigh: 842,
category: "powders",
state: "solid",
density: 1550,
conduct: 0.40,
},
"limestone": {
color: ["#C5B79C","#D9CCB2","#F8F1DB","#FCFAEB"],
behavior: behaviors.STURDYPOWDER,
tempHigh: 825,
stateHigh: "quicklime",
category: "land",
state: "solid",
density: 2100,
hardness: 0.4,
},
"quicklime": {
color: "#E9EBE7",
behavior: behaviors.POWDER,
tempHigh: 4662,
stateHigh: "molten_calcium",
category: "land",
state: "solid",
density: 1025,
hardness: 0.33,
},
"slaked_lime": {
color: "#adb8b5",
behavior: behaviors.STURDYPOWDER,
tempHigh: 580,
stateHigh: "quicklime",
category: "land",
hidden: true,
state: "solid",
density: 2211,
hardness: 0.2,
},
"metal_scrap": {
color: ["#b0afb4","#8c8f98","#cbcdcd","#6c6c6a","#fef9ff"],
behavior: behaviors.POWDER,
tempHigh: 1538,
stateHigh: ["molten_iron","molten_aluminum","molten_tin"],
category: "powders",
density: 2720,
state: "solid",
conduct: 0.43,
},
"neon": {
color: "#bababa",
behavior: behaviors.GAS,
behaviorOn: [
"M2|M1|M2",
"M1|CC:#ff0000|M1",
"M2|M1|M2",
],
tempLow: -248.59,
stateLow: "liquid_neon",
category: "gases",
density: 0.9002,
state: "gas",
conduct: 0.86,
},
"liquid_neon": {
color: "#d1d1d1",
behavior: behaviors.LIQUID,
behaviorOn: [
"XX|XX|XX",
"M2|CC:#ff0000|M2",
"M1|M1|M1",
],
tempHigh: -248.59,
stateHigh: "neon",
category: "liquids",
hidden: true,
density: 1207,
state: "liquid",
conduct: 0.83,
},
"rain_cloud": {
color: "#636b78",
behavior: [
"XX|XX|XX",
"M1%5|CH:water%0.05|M1%5",
"CR:electric%0.05|CR:electric%0.05|CR:electric%0.05",
],
category:"gases",
temp: 80,
tempLow: 0,
stateLow: "snow_cloud",
state: "gas",
density: 1,
conduct: 0.03,
},
"snow_cloud": {
color: "#7e8691",
behavior: [
"XX|XX|XX",
"M1%5|CH:snow%0.05|M1%5",
"XX|XX|XX",
],
category:"gases",
temp: -10,
tempHigh: 30,
stateHigh: "rain_cloud",
state: "gas",
density: 2,
conduct: 0.01,
},
"acid_cloud": {
color: "#637865",
behavior: [
"XX|XX|XX",
"M1%5|CH:acid%0.05|M1%5",
"XX|XX|XX",
],
category:"gases",
state: "gas",
density: 3,
},
"pyrocumulus": {
color: "#2e2e2e",
behavior: [
"XX|XX|XX",
"M1%5|CH:ash%0.075|M1%5",
"XX|XX|XX",
],
reactions: {
"fireball": { "elem1":null, "elem2":"fire_cloud", "chance":0.25 },
},
category:"gases",
hidden: true,
state: "gas",
density: 4,
},
"fire_cloud": {
color: ["#332424","#473431","#473931"],
behavior: [
"XX|XX|XX",
"M1%5|CH:fireball%0.02|M1%5",
"XX|XX|XX",
],
reactions: {
"rain_cloud": { "elem1": "pyrocumulus", "elem2": "pyrocumulus" },
"snow_cloud": { "elem1": "pyrocumulus", "elem2": "rain_cloud" },
"acid_cloud": { "elem1": "fire", "elem2": "electric" },
},
temp: 500,
tempLow: 100,
stateLow: "pyrocumulus",
category:"gases",
state: "gas",
density: 5,
},
"battery": {
color: "#9c6c25",
behavior: [
"XX|SH|XX", // shocks (adds charge)
"SH|XX|SH",
"XX|SH|XX",
],
category: "machines",
tempHigh: 1455.5,
stateHigh: "molten_steel",
},
"led_r": {
color: "#660000",
colorOn: "#ff0000",
category: "machines",
tempHigh: 1500,
stateHigh: "molten_glass",
conduct: 1,
},
"led_g": {
color: "#006600",
colorOn: "#00ff00",
category: "machines",
tempHigh: 1500,
stateHigh: "molten_glass",
conduct: 1,
},
"led_b": {
color: "#000066",
colorOn: "#0000ff",
category: "machines",
tempHigh: 1500,
stateHigh: "molten_glass",
conduct: 1,
},
"sulfur": {
color: ["#E9D74C","#89761B","#DDC56B"],
behavior: behaviors.POWDER,
category: "powders",
tempHigh: 115.21,
burn: 25,
burnTime: 207,
fireColor: ["#8180CC","#7F84E6"],
state: "solid",
density: 2070,
},
"molten_sulfur": {
reactions: {
"molten_copper": { "elem1": null, "elem2": "molten_copper_sulfate" },
},
density: 1819,
burn: 25,
burnTime: 507,
fireColor: ["#8180CC","#7F84E6"],
},
"copper_sulfate": {
color: ["#4391FD","#004CFE"],
behavior: behaviors.POWDER,
tempHigh: 110,
burn: 10,
burnTime: 1007,
fireColor: ["#91D106","#FEFF97","#248E01"],
state: "solid",
density: 3600,
hidden: true,
},
"diamond": {
color: ["#03fcec","#03c6fc","#b3eeff","#8ab0e6"],
behavior: behaviors.POWDER,
category: "powders",
tempHigh: 763,
stateHigh: "carbon_dioxide",
state: "solid",
density: 3515,
hardness: 1,
},
"glitter": {
color: ["#ACE4FB","#D9FCFF","#8F6EB2","#FDEAFC","#180E1C","#6B2778"],
behavior: behaviors.POWDER,
category: "powders",
tempHigh: 100,
stateHigh: ["fire","fire","dioxin"],
state: "solid",
density: 1450,
burn: 50,
burnTime: 50,
burnInto: ["smoke","smoke","dioxin"],
},
"electric": {
color: "#dddd00",
behavior: [
"CL%5|CL%5 AND SH|CL%5",
"CL%5 AND SH|SH%5 AND DL%50|CL%5 AND SH",
"M1%15 AND CL%6|M1%50 AND CL%13 AND SH|M1%15 AND CL%6",
],
charge: 3,
category: "energy",
state: "solid",
density: 2.1,
},
"snake": {
color: "#00bf00",
behavior: [
"XX|XX|XX",
"XX|LB:plant AND RT%5|M1 AND BO:1,2,3",
"XX|XX|XX",
],
rotatable: true,
category: "special",
},
"loopy": {
color: "#eb3474",
behavior: [
"XX|M2|M1",
"XX|RT%20|M2",
"CR:smoke|XX|XX",
],
rotatable: true,
category: "special",
},
"smoke_grenade": {
color: "#2b382c",
behavior: [
"XX|CR:smoke|XX",
"XX|XX|XX",
"M2|M1|M2",
],
category: "special",
state: "solid",
density: 7300,
conduct: 0.73,
tempHigh: 1455.5,
stateHigh: "molten_steel",
},
"cyanide": {
color: "#b6ccb6",
behavior: behaviors.GAS,
reactions: {
"frog": { "elem2":"meat" },
"ant": { "elem2":null },
"bee": { "elem2":null },
"fish": { "elem2":"meat" },
"firefly": { "elem2":null },
},
tempHigh: 550,
stateHigh: "fire",
burn: 100,
burnTime: 1,
state: "gas",
density: 687,
category: "gases",
},
"radiation": {
color: ["#00ff00","#6fff00"],
behavior: [
"XX|M1%0.5 AND HT|XX",
"M1%7 AND HT|DL%3|M1%7 AND HT",
"XX|M1%1 AND HT|XX",
],
reactions: {
"water": { "elem2":"rad_steam", "chance":0.4 },
"steam": { "elem2":"rad_steam", "chance":0.4 },
"salt_water": { "elem2":"rad_steam", "chance":0.4 },
"sugar_water": { "elem2":"rad_steam", "chance":0.4 },
"dirty_water": { "elem2":"rad_steam", "chance":0.4 },
"bubble": { "elem2":"rad_steam", "chance":0.4 },
"foam": { "elem2":"rad_steam", "chance":0.4 },
"ice": { "elem2":"rad_steam", "chance":0.4 },
"snow": { "elem2":"rad_steam", "chance":0.4 },
"packed_snow": { "elem2":"rad_steam", "chance":0.4 },
"slime": { "elem2":"rad_steam", "chance":0.4 },
"milk": { "elem2":"cheese", "chance":0.4 },
"permafrost": { "elem1":"rad_steam", "elem2":"dirt", "chance":0.4 },
"mud": { "elem1":"rad_steam", "elem2":"dirt", "chance":0.4 },
"wet_sand": { "elem1":"rad_steam", "elem2":"sand", "chance":0.4 },
"clay": { "elem1":"rad_steam", "elem2":"clay_soil", "chance":0.4 },
"slaked_lime": { "elem1":"rad_steam", "elem2":"limestone", "chance":0.4 },
"rain_cloud": { "elem2":"rad_cloud", "chance":0.4 },
"snow_cloud": { "elem2":"rad_cloud", "chance":0.4 },
"plant": { "elem2":"straw", "chance":0.4 },
"grass": { "elem2":["straw","grass_seed","wheat_seed"], "chance":0.4 },
"algae": { "elem2":["mushroom_spore","lichen","yeast"], "chance":0.4 },
"mushroom_spore": { "elem2":["lichen","yeast"], "chance":0.4 },
"mushroom_cap": { "elem2":["lichen","plant"], "chance":0.4 },
"mushroom_stalk": { "elem2":["lichen","yeast"], "chance":0.4 },
"mushroom_gill": { "elem2":["lichen","yeast"], "chance":0.4 },
"flea": { "elem2":["ash","ant","termite"], "chance":0.4 },
"ant": { "elem2":["ash","flea","termite"], "chance":0.4 },
"termite": { "elem2":["ash","flea","ant"], "chance":0.4 },
"fly": { "elem2":["ash","firefly","bee"], "chance":0.4 },
"bee": { "elem2":["ash","firefly","fly"], "chance":0.4 },
"firefly": { "elem2":["ash","bee","fly"], "chance":0.4 },
"frog": { "elem2":["ash","meat","rotten_meat","cooked_meat"], "chance":0.4 },
"fish": { "elem2":["ash","meat","rotten_meat","cooked_meat"], "chance":0.4 },
"rat": { "elem2":["ash","meat","rotten_meat","cooked_meat","plague"], "chance":0.4 },
"bone": { "elem2":["calcium","calcium","calcium","cancer"], "chance":0.4 },
"meat": { "elem2":["ash","rotten_meat","cooked_meat"], "chance":0.4 },
"rotten_meat": { "elem2":["ash","meat","cooked_meat"], "chance":0.4 },
"cooked_meat": { "elem2":["ash","rotten_meat"], "chance":0.4 },
"bamboo": { "elem2":["wood","plant","bamboo_plant"], "chance":0.4 },
"bamboo_plant": { "elem2":["wood","plant","bamboo"], "chance":0.4 },
"sapling": { "elem2":["wood","plant","tree_branch"], "chance":0.4 },
"tree_branch": { "elem2":["wood","plant","sapling"], "chance":0.4 },
"grass_seed": { "elem2":["straw","wheat_seed"], "chance":0.4 },
"lichen": { "elem2":"algae", "chance":0.4 },
"yeast": { "elem2":["algae","mushroom_spore","lichen"], "chance":0.4 },
"wheat_seed": { "elem2":["straw","wheat","grass_seed"], "chance":0.4 },
"flower_seed": { "elem2":["straw","grass","pistil","petal"], "chance":0.4 },
"pistil": { "elem2":["straw","grass","flower_seed","petal"], "chance":0.4 },
"petal": { "elem2":["straw","grass","flower_seed","pistil"], "chance":0.4 },
"vine": { "elem1":["vine"], "chance":0.4 },
"worm": { "elem2":"ash", "chance":0.4 },
"corn": { "elem2":"corn_seed", "chance":0.4 },
"corn_seed": { "elem2":"corn", "chance":0.4 },
"potato": { "elem2":"potato_seed", "chance":0.4 },
"potato_seed": { "elem2":"potato", "chance":0.4 },
"slug": { "elem2":"slime", "chance":0.4 },
"snail": { "elem2":"slime", "chance":0.4 },
"cell": { "elem2":"cancer", "chance":0.4 },
"blood": { "elem2":["infection","cancer"], "chance":0.4 },
"antibody": { "elem2":"cancer", "chance":0.4 },
"infection": { "elem2":"cancer", "chance":0.4 },
"cancer": { "elem2":null, "chance":0.1 },
},
state: "gas",
density: 0.2,
category: "energy",
},
"rad_steam": {
color: "#abffe4",
behavior: [
"M1%10|M1%10|M1%10",
"M2%10|XX|M2%10",
"XX|M2%10|XX",
],
reactions: {
"rad_steam": { "elem1": null, "elem2": "rad_cloud", "chance":0.3, "y":[0,15] },
"steam": { "elem1": null, "elem2": "rad_cloud", "chance":0.3, "y":[0,15] },
"rain_cloud": { "elem1": "rad_cloud", "chance":0.4, "y":[0,15] },
"snow_cloud": { "elem1": "rad_cloud", "chance":0.4, "y":[0,15] },
"pyrocumulus": { "elem1": "rad_cloud", "chance":0.4, "y":[0,15] },
"rad_cloud": { "elem1": "rad_cloud", "chance":0.3, "y":[0,15] },
},
tempLow: 10,
stateLow: "fallout",
category: "gases",
hidden: true,
state: "gas",
density: 1,
},
"rad_cloud": {
color: ["#2d7528","#557528"],
behavior: [
"XX|XX|XX",
"M1%5|CH:fallout,radiation%0.025|M1%5",
"CR:radiation%0.05|CR:radiation%0.05|CR:radiation%0.05",
],
category:"gases",
hidden: true,
state: "gas",
density: 3,
},
"fallout": {
color: ["#63b85a","#448044","#598044","#7bb85a"],
behavior: [
"XX|CR:radiation%2|XX",
"CR:radiation%2|CH:radiation%0.5|CR:radiation%2",
"M2|M1 AND CR:radiation%2|M2",
],
category:"energy",
hidden: true,
state: "solid",
density: 1490,
},
"uranium": {
color: ["#599e61","#364d3c","#494D4A","#6c8a42","#798d65","#b5e089"],
behavior: behaviors.RADPOWDER,
tempHigh: 1132.2,
category: "powders",
state: "solid",
density: 19100,
},
"molten_uranium": {
behavior: behaviors.RADMOLTEN,
},
"glass_shard": {
color: ["#5e807d","#679e99","#596b6e"],
behavior: behaviors.POWDER,
tempHigh: 1500,
stateHigh: "molten_glass",
category: "powders",
state: "solid",
density: 2500,
},
"bead": {
color: ["#ff5e5e","#ffcc5e","#76ff5e","#5ed4ff","#5e61ff","#cf5eff"],
behavior: behaviors.POWDER,
category: "powders",
tempHigh: 185,
stateHigh: "molten_plastic",
burn: 10,
burnTime: 400,
burnInto: "dioxin",
state: "solid",
density: 1052,
},
"borax": {
color: "#ffffff",
behavior: behaviors.POWDER,
category: "powders",
burn: 15,
burnTime: 200,
fireColor: ["#34eb67","#5ceb34"],
tempHigh: 743,
state: "solid",
density: 1730,
},
"epsom_salt": {
color: ["#f2f2f2","#e0e0e0"],
behavior: behaviors.POWDER,
category: "powders",
burn: 40,
burnTime: 200,
fireColor: ["#ffffff","#fcf0f0"],
tempHigh: 1124,
state: "solid",
density: 1680,
},
"potassium_salt": {
color: ["#f2f2f2","#e0e0e0"],
behavior: behaviors.POWDER,
category: "powders",
burn: 40,
burnTime: 200,
fireColor: ["#ff00ee","#ff6bf5"],
tempHigh: 292,
state: "solid",
density: 3980,
},
};
function hexToRGB(hex) {
var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
return result ? {
r: parseInt(result[1], 16),
g: parseInt(result[2], 16),
b: parseInt(result[3], 16)
} : null;
}
currentPixels = [];
//currentID = 0;
// Pixel class, with attributes such as x, y, and element
class Pixel {
constructor(x, y, element) {
this.x = x;
this.y = y;
this.element = element;
var elementInfo = elements[element];
this.color = pixelColorPick(this);
// If element doesn't have temp attribute, set temp to airTemp
if (elementInfo.temp==undefined) {
this.temp = airTemp;
} else {
this.temp = elementInfo.temp;
}
this.start = pixelTicks;
//this.id = currentID;
//currentID++;
if (elementInfo.burning) {
this.burning = true;
this.burnStart = pixelTicks;
}
else {
this.burning = false;
}
if (elementInfo.charge) {
this.charge = elementInfo.charge;
}
// If elementInfo.flippableX, set it to true or false randomly
if (elementInfo.flipX !== undefined) { this.flipX = elementInfo.flipX }
else if (elementInfo.flippableX) {
this.flipX = Math.random() >= 0.5;
}
// If elementInfo.flippableY, set it to true or false randomly
if (elementInfo.flipY !== undefined) { this.flipY = elementInfo.flipY }
else if (elementInfo.flippableY) {
this.flipY = Math.random() >= 0.5;
}
// If elementInfo.rotatable, set it to a number between 0 and 3
if (elementInfo.r !== undefined) { this.r = elementInfo.r }
else if (elementInfo.rotatable) {
this.r = Math.floor(Math.random() * 4);
}
pixelMap[x][y] = this;
}
}
// If the screen size is under 768px, set pixelSize to 5, otherwise 6
if (window.innerWidth < 700) {
pixelSize = 5;
} else {
pixelSize = 6;
}
function outOfBounds(x,y) {
// Returns true if the pixel is out of bounds
return y > height-1 || y < 1 || x > width-1 || x < 1
}
function isEmpty(x, y, ignoreBounds=false) {
if (outOfBounds(x,y)) {
return ignoreBounds;
}
return pixelMap[x][y] == undefined;
}
function canMove(pixel,x,y) {
if (isEmpty(x,y)) {
return true;
}
}
function movePixel(pixel,x,y,leaveBehind=null) {
// Delete the pixel from the old position
delete pixelMap[pixel.x][pixel.y];
if (leaveBehind != null && isEmpty(pixel.x,pixel.y)) { createPixel(leaveBehind,pixel.x,pixel.y); }
pixel.x = x;
pixel.y = y;
pixelMap[x][y] = pixel;
}
function clonePixel(pixel,x,y) {
currentPixels.push(new Pixel(x, y, pixel.element));
}
function createPixel(element,x,y) {
currentPixels.push(new Pixel(x, y, element));
}
function deletePixel(x,y) {
// remove pixelMap[x][y] from currentPixels
currentPixels.splice(currentPixels.indexOf(pixelMap[x][y]),1);
pixelMap[x][y].del = true;
delete pixelMap[x][y];
/*for (var i = 0; i < currentPixels.length; i++) {
if (currentPixels[i].x == x && currentPixels[i].y == y) {
currentPixels.splice(i, 1);
break;
}
}*/
/*if (id != null) {
for (var i = 0; i < currentPixels.length; i++) {
if (currentPixels[i].id == id) {
currentPixels.splice(i, 1);
return;
}
}
}*/
}
function swapPixels(pixel1,pixel2) {
var tempX = pixel1.x;
var tempY = pixel1.y;
pixel1.x = pixel2.x;
pixel1.y = pixel2.y;
pixel2.x = tempX;
pixel2.y = tempY;
pixelMap[pixel1.x][pixel1.y] = pixel1;
pixelMap[pixel2.x][pixel2.y] = pixel2;
}
function reactPixels(pixel1,pixel2) {
var r = elements[pixel1.element].reactions[pixel2.element];
if (r.chance !== undefined && Math.random() > r.chance) {
return false;
}
// r has the attribute "y" which is a range between two y values
// r.y example: [10,30]
// return false if y is defined and pixel1's y is not in the range
if (r.y !== undefined && (pixel1.y < r.y[0] || pixel1.y > r.y[1])) {
return false;
}
if (r.elem1 !== undefined) {
// if r.elem1 is an array, set elem1 to a random element from the array, otherwise set it to r.elem1
if (Array.isArray(r.elem1)) {
var elem1 = r.elem1[Math.floor(Math.random() * r.elem1.length)];
console.log(elem1);
} else { var elem1 = r.elem1; }
if (elem1 == null) {
deletePixel(pixel1.x,pixel1.y);
}
else {
pixel1.element = elem1;
pixel1.color = pixelColorPick(pixel1);
pixel1.start = pixelTicks;
if (elements[elem1].burning == true) {
pixel1.burning = true;
pixel1.burnStart = pixelTicks;
}
else if (pixel1.burning && !elements[elem1].burn) {
pixel1.burning = false;
delete pixel.burnStart;
}
}
}
if (r.elem2 !== undefined) {
// if r.elem2 is an array, set elem2 to a random element from the array, otherwise set it to r.elem2
if (Array.isArray(r.elem2)) {
var elem2 = r.elem2[Math.floor(Math.random() * r.elem2.length)];
} else { var elem2 = r.elem2; }
if (elem2 == null) {
deletePixel(pixel2.x,pixel2.y);
}
else {
pixel2.element = elem2;
pixel2.color = pixelColorPick(pixel2);
pixel2.start = pixelTicks;
if (elements[elem2].burning == true) {
pixel2.burning = true;
pixel2.burnStart = pixelTicks;
}
else if (pixel2.burning && !elements[elem2].burn) {
pixel2.burning = false;
delete pixel.burnStart;
}
}
}
return true;
}
validDensitySwaps = ["solid>liquid","liquid>gas","liquid>liquid","gas>gas","solid>gas"];
function tryMove(pixel,nx,ny,leaveBehind=undefined) {
var info = elements[pixel.element];
if (isEmpty(nx,ny)) { // If coords is empty, move to coords
movePixel(pixel,nx,ny,leaveBehind);
return true;
}
else {
if (!outOfBounds(nx,ny)) {
// Reactions
newPixel = pixelMap[nx][ny];
if (info.reactions != undefined && info.reactions[newPixel.element] != undefined) {
if (reactPixels(pixel,newPixel)) {
return true;
}
}
else if (elements[newPixel.element].reactions != undefined && elements[newPixel.element].reactions[pixel.element] != undefined && !elements[newPixel.element].reactions[pixel.element].oneway) {
if (reactPixels(newPixel,pixel)) {
return true;
}
}
// Density
if (pixel.element != newPixel.element) {
if (elements[newPixel.element].density != undefined && info.density != undefined) {
// if the pixel's state + ">" + newPixel's state is in validDensitySwaps, and the pixel's density is larger than the newPixel's density, swap the pixels
if (validDensitySwaps.includes(info.state+">"+elements[newPixel.element].state) && info.density >= elements[newPixel.element].density) {
// chance depending on the difference in density
if (Math.random() < (info.density - elements[newPixel.element].density)/(info.density + elements[newPixel.element].density)) {
swapPixels(pixel,newPixel);
return true;
}
}
}
}
}
}
return false;
}
function behaviorCoords(x,y,bx,by) {
return {x:x+bx-1,y:y+by-1};
}
/* Behavior Example (Sand)
[
["XX","XX","XX"],
["XX","XX","XX"],
["M2","M1","M2"]
] */
behaviorCache = {};
function rotateBehavior(behavior,rotation) {
// returns rotated 2D array counter-clockwise depending on rotation 1, 2, or 3
// if the rotation is under 0, subtract it from 3
if (rotation < 0) {
rotation = 4 + rotation;
}
var check = behaviorCache[behavior.toString()+rotation];
if (check != undefined) { return check; }
var newBehavior = []
if (rotation == 1) {
// rotate counter-clockwise 90 degrees
for (var i = 0; i < behavior.length; i++) {
newBehavior[i] = [];
for (var j = 0; j < behavior[i].length; j++) {
newBehavior[i][j] = behavior[j][behavior.length-1-i];
}}
}
else if (rotation == 2) {
// rotate counter-clockwise 180 degrees
for (var i = 0; i < behavior.length; i++) {
newBehavior[i] = [];
for (var j = 0; j < behavior[i].length; j++) {
newBehavior[i][j] = behavior[behavior.length-1-i][behavior[i].length-1-j];
}}
}
else if (rotation == 3) {
// rotate counter-clockwise 270 degrees
for (var i = 0; i < behavior.length; i++) {
newBehavior[i] = [];
for (var j = 0; j < behavior[i].length; j++) {
newBehavior[i][j] = behavior[behavior[i].length-1-j][i];}
}
}
else {
// no rotation
return behavior;
}
behaviorCache[behavior.toString()+rotation] = newBehavior;
return newBehavior;
}
function flipBehavior(behavior,axis) {
// returns flipped 2D array depending on axis "x" or "y"
var check = behaviorCache[behavior.toString()+axis];
if (check != undefined) { return check; }
if (axis === "x") {
var newBehavior = [];
for (var i = 0; i < behavior.length; i++) {
newBehavior[i] = [];
for (var j = 0; j < behavior[i].length; j++) {
newBehavior[i][j] = behavior[i][behavior[i].length-1-j];
}}
behaviorCache[behavior.toString()+axis] = newBehavior;
return newBehavior;
}
else { // axis === y
newBehavior = behavior.slice().reverse();
behaviorCache[behavior.toString()+axis] = newBehavior;
return newBehavior;
}
return behavior;
}
/* Behavior Rules
XX = Ignore
M1 = Move (First Priority)
M2 = Move (Second Priority)
SP = Support (Doesn't move if all aren't empty)
SA = Support Any (Doesn't move if any aren't empty)
DL = Delete
DB = Delete Both (Self and target)
CL = Clone
CF = Clone first touched
CH = Change
C2 = Change Self after M2
CR:element_name = Create a pixel of element_name
LB:element_name = Leave behind a pixel of element_name when moved (Must be center cell)
%(num) = Chance of rule happening
L1:element_name = Leave behind only on M1 moves
L2:element_name = Leave behind only on M2 moves
SW = Swap
HT = Heat
CO = Cool
CC = Change Color (Hexadecimal)
ST = Stick
SH = Shock with electricity
FX = Flip X
FY = Flip Y
RT = Rotate
BO = Bounce off of
*/
function pixelTick(pixel) {
if (pixel.start == pixelTicks) {return}
var info = elements[pixel.element];
if (pixel.charge && info.behaviorOn) { var behavior = info.behaviorOn; }
else { var behavior = info.behavior; }
if (pixel.flipX) { behavior = flipBehavior(behavior,"x"); }
if (pixel.flipY) { behavior = flipBehavior(behavior,"y"); }
if (pixel.r) { behavior = rotateBehavior(behavior,pixel.r); }
var x = pixel.x;
var y = pixel.y;
var move1Spots = [];
var move2Spots = [];
var supportSpots = [];
var swapSpots = [];
var leaveBehind = null;
var leaveBehind1 = null;
var leaveBehind2 = null;
var move = true;
// Parse behavior
for (var by = 0; by < behavior.length; by++) {
behaviorby = behavior[by];
for (var bx = 0; bx < behaviorby.length; bx++) {
var b0 = behaviorby[bx];
if (b0 === "XX") {continue}
//if (b.includes(" OR ")) {
// b = b.split(" OR ")[Math.floor(Math.random()*b.split(" OR ").length)];
//}
// Loop through b0.split(" AND ")
if (b0.includes(" AND ")) { var andsplit = b0.split(" AND "); }
else { var andsplit = [b0]; }
for (var i = 0; i < andsplit.length; i++) {
var b = andsplit[i];
if (b.includes(":")) {
var arg = b.split(":")[1].split(/[\:\%]/)[0];
if (!b.includes("%")) {
b = b.split(/[\:\%]/)[0];
}
}
else { var arg = null;}
// If b has "%" followed by a number in it, it's a chance to move
if (b.includes("%")) {
// Split the string at the "%" and use the second half as the chance (float)
var chance = parseFloat(b.split("%")[1]);
//console.log(b+": "+(Math.random()*100 < chance));
b = b.split(/[\:\%]/)[0];
}
else { var chance = 100; }
if (chance==100 || Math.random()*100 < chance) {
var newCoords = behaviorCoords(x,y,bx,by);
if (b == "M1") {
if (info.viscosity != undefined) {
if (!((Math.random()*100) < 100 / ((info.viscosity) ** 0.25))) {
newCoords.x = x;
}
}
move1Spots.push(newCoords);
}
else if (b == "M2") {
if (info.viscosity != undefined) {
if (!((Math.random()*100) < 100 / ((info.viscosity) ** 0.25))) {
newCoords.x = x;
}
}
move2Spots.push(newCoords);
}
else if (b == "SP") {
supportSpots.push({x:newCoords.x,y:newCoords.y,arg:arg});
}
else if (b == "SA") {
if (!isEmpty(newCoords.x,newCoords.y,true)) {
move = false;
}
}
else if (b == "DL") {
if (!isEmpty(newCoords.x,newCoords.y,true)) {
// if the pixel at newCoords is the same element as the pixel, ignore
newPixel = pixelMap[newCoords.x][newCoords.y];
// if info.ignore exists and newPixel.element is in it
if (info.ignore && info.ignore.includes(newPixel.element)) {
continue;
}
if ((!(newPixel.element == pixel.element)) || (newCoords.x == x && newCoords.y == y)) {
if (arg != null) { var args = arg.split(","); }
if (arg == null || args.includes(newPixel.element)) {
if (!elements[newPixel.element].hardness || Math.random() > elements[newPixel.element].hardness) {
deletePixel(newCoords.x,newCoords.y);
if (newCoords.x == x && newCoords.y == y) {
var deleted = true;
}
swapSpots = [];
}
}
}
}
}
else if (b == "DB") { // Delete Both
if (!isEmpty(newCoords.x,newCoords.y,true)) {
// if the pixel at newCoords is the same element as the pixel, ignore
newPixel = pixelMap[newCoords.x][newCoords.y];
// if info.ignore exists and newPixel.element is in it
if (info.ignore && info.ignore.includes(newPixel.element)) {
continue;
}
if (!(newPixel.element == pixel.element)) {
if (arg != null) { var args = arg.split(","); }
if (arg == null || args.includes(newPixel.element)) {
if (!elements[newPixel.element].hardness || Math.random() > elements[newPixel.element].hardness) {
deletePixel(newCoords.x,newCoords.y);
if (pixelMap[pixel.x][pixel.y] != undefined) {
deletePixel(pixel.x,pixel.y);
}
var deleted = true;
swapSpots = [];
}
}
}
}
}
//Change pixel
else if (b == "CH") {
if (!isEmpty(newCoords.x,newCoords.y,true)) {
var newPixel = pixelMap[newCoords.x][newCoords.y];
if (!elements[newPixel.element].hardness || Math.random() > elements[newPixel.element].hardness) {
if (arg.includes(">")) {
var argfrom = arg.split(">")[0];
var argto = arg.split(">")[1];
}
else {
var argfrom = null;
var argto = arg;
}
if (argto.includes(",")) {
var argto = argto.split(",")[Math.floor(Math.random()*argto.split(",").length)];
}
if (elements[argto]) {
if ((newPixel.element != argto) && (argfrom == null || argfrom == newPixel.element)) {
newPixel.element = argto;
newPixel.color = pixelColorPick(newPixel);
newPixel.start = pixelTicks;
if (elements[argto].burning != true) {
newPixel.burning = false;
}
else {
newPixel.burning = true;
newPixel.burnStart = pixelTicks;
}
}
}
}
}
}
//Swap
else if (b == "SW") {
if (!isEmpty(newCoords.x,newCoords.y,true)) {
var newPixel = pixelMap[newCoords.x][newCoords.y];
if (arg != null) { var args = arg.split(","); }
if (arg == null || args.includes(newPixel.element)) {
if (!elements[newPixel.element].hardness || Math.random() > elements[newPixel.element].hardness) {
swapSpots.push({x:newCoords.x,y:newCoords.y});
}
}
}
}
//Create pixel
else if (b == "CR") {
if (isEmpty(newCoords.x,newCoords.y)) {
if (arg == null) {
arg = pixel.element;
}
else if (arg.includes(",")) {
arg = arg.split(",")[Math.floor(Math.random()*arg.split(",").length)];
}
if (elements[arg]) {
createPixel(arg,newCoords.x,newCoords.y);
pixelMap[newCoords.x][newCoords.y].temp = pixel.temp
}
}
}
// Clone self
else if (b == "CL") {
if (isEmpty(newCoords.x,newCoords.y)) {
if (arg == null || pixel.temp >= parseFloat(arg)) {
clonePixel(pixel,newCoords.x,newCoords.y);
}
}
}
// Clone first touched
else if (b == "CF") {
if (pixel.clone) {
if (isEmpty(newCoords.x,newCoords.y)) {
createPixel(pixel.clone,newCoords.x,newCoords.y);
pixelMap[newCoords.x][newCoords.y].temp = pixel.temp;
}
}
else {
if (!isEmpty(newCoords.x,newCoords.y,true)) {
newPixel = pixelMap[newCoords.x][newCoords.y];
if (newPixel.element != pixel.element && newPixel.element != "wire") {
pixel.clone = newPixel.element;
pixel.temp = newPixel.temp;
}
else if (newPixel.clone) {
pixel.clone = newPixel.clone;
pixel.temp = newPixel.temp;
}
}
}
}
else if (b=="SH") {
if (!isEmpty(newCoords.x,newCoords.y,true)) {
var newPixel = pixelMap[newCoords.x][newCoords.y];
var con = elements[newPixel.element].conduct;
if (con != undefined) {
if (Math.random() < con) { // If random number is less than conductivity
if (!newPixel.charge && !newPixel.chargeCD) {
newPixel.charge = (parseFloat(arg) || 1);
if (elements[newPixel.element].colorOn) {
newPixel.color = pixelColorPick(newPixel);
}
}
}
}
}
}
//Stick
else if (b=="ST") {
if (!isEmpty(newCoords.x,newCoords.y,true)) {
var newPixel = pixelMap[newCoords.x][newCoords.y];
if (newPixel.element != pixel.element && (arg == null || newPixel.element == arg)) {
var sticking = true
}
}
}
//Leave behind element
else if (b == "LB" || b == "L1" || b == "L2") {
if (arg != null && arg.includes(",")) {
arg = arg.split(",")[Math.floor(Math.random()*arg.split(",").length)];
}
if (elements[arg]) {
if (b=="LB") {leaveBehind = arg;}
else if (b=="L1") {leaveBehind1 = arg;}
else if (b=="L2") {leaveBehind2 = arg;}
}
}
//Change color
else if (b == "CC") {
if (!isEmpty(newCoords.x,newCoords.y,true)) {
var newPixel = pixelMap[newCoords.x][newCoords.y];
if (arg == null) {arg = newPixel.colorObject}
else {
if (arg.includes(",")) {
arg = arg.split(",")[Math.floor(Math.random()*arg.split(",").length)];
}
if (!arg.startsWith("#")) {
arg = "#" + arg;
}
}
newPixel.color = pixelColorPick(newPixel,arg);
}
}
//Heat
else if (b == "HT") {
if (!isEmpty(newCoords.x,newCoords.y,true)) {
var newPixel = pixelMap[newCoords.x][newCoords.y];
// if the element isn't the same or the coords ARE the same
if (!(newPixel.element == pixel.element) || (newCoords.x == pixel.x && newCoords.y == pixel.y)) {
if (arg != null) {arg = parseFloat(arg)}
else {arg = 1}
if (isNaN(arg)) {arg = 1}
newPixel.temp += arg;
pixelTempCheck(newPixel);
}
}
}
//Cool
else if (b == "CO") {
if (!isEmpty(newCoords.x,newCoords.y,true)) {
var newPixel = pixelMap[newCoords.x][newCoords.y];
if (!(newPixel.element == pixel.element) || (newCoords.x == pixel.x && newCoords.y == pixel.y)) {
if (arg != null) {arg = parseFloat(arg)}
else {arg = 1}
if (isNaN(arg)) {arg = 1}
newPixel.temp -= arg;
pixelTempCheck(newPixel);
}
}
}
// Flip X
else if (b == "FX") {
if (!isEmpty(newCoords.x,newCoords.y,true)) {
var newPixel = pixelMap[newCoords.x][newCoords.y];
if (elements[newPixel.element].flippableX) {
if (arg === "0") { newPixel.flipX = false; }
else if (arg === "1") { newPixel.flipX = true; }
newPixel.flipX = !newPixel.flipX;
}
}
}
// Flip Y
else if (b == "FY") {
if (!isEmpty(newCoords.x,newCoords.y,true)) {
var newPixel = pixelMap[newCoords.x][newCoords.y];
if (elements[newPixel.element].flippableY) {
if (arg === "0") { newPixel.flipY = false; }
else if (arg === "1") { newPixel.flipY = true; }
else { newPixel.flipY = !newPixel.flipY; }
}
}
}
// Rotate
else if (b == "RT") {
if (!isEmpty(newCoords.x,newCoords.y,true)) {
var newPixel = pixelMap[newCoords.x][newCoords.y];
// If arg isn't null, set arg to a random choice from arg.split(",")
if (arg != null && arg.includes(",")) {
arg = arg.split(",")[Math.floor(Math.random()*arg.split(",").length)];
}
if (elements[newPixel.element].rotatable) {
newPixel.r = ((newPixel.r||0) + (parseInt(arg)||1)) % 4;
}
}
}
// Bounce
else if (b == "BO") {
if (!isEmpty(newCoords.x,newCoords.y)) {
if (info.flippableX) {
pixel.flipX = !pixel.flipX;
}
if (info.flippableY) {
pixel.flipY = !pixel.flipY;
}
if (info.rotatable) {
// If arg isn't null, set arg to a random choice from arg.split(",")
if (arg != null && arg.includes(",")) {
arg = arg.split(",")[Math.floor(Math.random()*arg.split(",").length)];
}
if (pixel.r !== undefined) {
pixel.r = (pixel.r + (parseInt(arg)||2)) % 4;
}
else { pixel.r = (parseInt(arg)||2); }
}
}
}
// Change When M2
else if (b == "C2") {
if (arg.includes(",")) {
arg = arg.split(",")[Math.floor(Math.random()*arg.split(",").length)];
}
var C2 = arg;
}
}
}
}
}
if (typeof deleted !== "undefined") {return;}
if (supportSpots.length > 0) {
var supportCount = 0;
var allEmpty = true;
for (var i = 0; i < supportSpots.length; i++) {
var bx = supportSpots[i].x;
var by = supportSpots[i].y;
var arg = supportSpots[i].arg;
if (!isEmpty(bx,by,true)) {
if ((arg == null && !validDensitySwaps.includes(info.state+">"+elements[pixelMap[bx][by].element].state)) || pixelMap[bx][by].element == arg) {
supportCount++;
}
}
}
if (supportCount == supportSpots.length) {
move = false;
}
}
var moved = false;
if (swapSpots.length > 0) {
var coords = swapSpots[Math.floor(Math.random()*swapSpots.length)];
if (pixelMap[coords.x][coords.y] != undefined) {
swapPixels(pixel,pixelMap[coords.x][coords.y]);
move = false;
moved = true;
}
}
if (typeof sticking !== "undefined") {
move = false;
}
// Move First Priority
if (move) {
if (move1Spots.length > 0) {
// While move1Spots is not empty
while (move1Spots.length > 0) {
// coords = random item of move1Spots
var coords = move1Spots[Math.floor(Math.random()*move1Spots.length)];
var nx = coords.x;
var ny = coords.y;
moved = tryMove(pixel,nx,ny,leaveBehind1 || leaveBehind);
if (moved) {
break;
}
else {
// remove coords from move1Spots
move1Spots.splice(move1Spots.indexOf(coords),1);
}
}
}
// Move Second Priority
if (!moved && move2Spots.length > 0) {
// While move2Spots is not empty
while (move2Spots.length > 0) {
// coords = random item of move2Spots
var coords = move2Spots[Math.floor(Math.random()*move2Spots.length)];
var nx = coords.x;
var ny = coords.y;
moved = tryMove(pixel,nx,ny,leaveBehind2 || leaveBehind);
if (moved) {
if (typeof C2 !== "undefined" && elements[C2]) {
pixel.element = C2;
pixel.color = pixelColorPick(pixel);
pixel.start = pixelTicks;
if (elements[C2].burning != true) {
pixel.burning = false;
}
else {
pixel.burning = true;
pixel.burnStart = pixelTicks;
}
}
break;
}
else {
// remove coords from move2Spots
move2Spots.splice(move2Spots.indexOf(coords),1);
}
}
}
}
if (pixel.burning) { // Burning
pixel.temp += 1;
pixelTempCheck(pixel);
var burnSpots = [
{x:pixel.x+1,y:pixel.y},
{x:pixel.x-1,y:pixel.y},
{x:pixel.x,y:pixel.y+1},
{x:pixel.x,y:pixel.y-1},
];
// loop through burnspots
for (var i = 0; i < burnSpots.length; i++) {
var burnSpot = burnSpots[i];
if (!isEmpty(burnSpot.x,burnSpot.y,true)) {
var newPixel = pixelMap[burnSpot.x][burnSpot.y];
if (elements[newPixel.element].burn && !newPixel.burning) {
if (Math.floor(Math.random()*100) < elements[newPixel.element].burn) {
newPixel.burning = true;
newPixel.burnStart = pixelTicks;
}
}
}
}
if ((pixelTicks - pixel.burnStart > (info.burnTime || 200)) && Math.floor(Math.random()*100)<(info.burn || 10)) {
var burnInto = info.burnInto;
if (burnInto == undefined) {
burnInto = 'fire';
}
else if (burnInto instanceof Array) {
burnInto = burnInto[Math.floor(Math.random()*burnInto.length)];
}
pixel.element = burnInto;
if (info.fireColor != undefined && burnInto == "fire") {
pixel.color = pixelColorPick(pixel,info.fireColor);
}
else {
pixel.color = pixelColorPick(pixel)
}
pixel.start = pixelTicks;
if (elements[burnInto].burning != true) {
pixel.burning = false;
delete pixel.burnStart;
}
else {
pixel.burning = true;
pixel.burnStart = pixelTicks;
}
if (elements[burnInto].temp != undefined) {
pixel.temp = elements[burnInto].temp;
pixelTempCheck(pixel)
}
}
else if (pixel.element != "fire" && isEmpty(pixel.x,pixel.y-1) && Math.floor(Math.random()*100)<10) {
createPixel("fire",pixel.x,pixel.y-1);
pixelMap[pixel.x][pixel.y-1].temp = pixel.temp//+(pixelTicks - (pixel.burnStart || 0));
if (info.fireColor != undefined) {
pixelMap[pixel.x][pixel.y-1].color = pixelColorPick(pixelMap[pixel.x][pixel.y-1],info.fireColor);
}
}
}
// Change tempearture if needed (unused)
/*if (info.tempChange != undefined) {
pixel.temp += info.tempChange;
pixelTempCheck(pixel);
}*/
// Heat Transfer
if (info.insulate != true) {
// Check right and bottom adjacent pixels
var coordsToCheck = [
{x:pixel.x+1,y:pixel.y},
{x:pixel.x,y:pixel.y+1},
];
for (var i = 0; i < coordsToCheck.length; i++) {
var coords = coordsToCheck[i];
if (!isEmpty(coords.x,coords.y,true)) {
var newPixel = pixelMap[coords.x][coords.y];
// Skip if both temperatures are the same
if (pixel.temp == newPixel.temp || elements[newPixel.element].insulate == true) {
continue;
}
// Set both pixel temperatures to their average
var avg = (pixel.temp + newPixel.temp)/2;
pixel.temp = avg;
newPixel.temp = avg;
pixelTempCheck(pixel);
pixelTempCheck(newPixel);
}
}
}
// Electricity Transfer
if (pixel.charge) {
// Check each adjacent pixel, if that pixel's charge is false, set it to the same charge
var coordsToCheck = [
{x:pixel.x+1,y:pixel.y},
{x:pixel.x-1,y:pixel.y},
{x:pixel.x,y:pixel.y+1},
{x:pixel.x,y:pixel.y-1},
];
for (var i = 0; i < coordsToCheck.length; i++) {
var coords = coordsToCheck[i];
if (!isEmpty(coords.x,coords.y,true)) {
var newPixel = pixelMap[coords.x][coords.y];
var con = elements[newPixel.element].conduct;
if (con == undefined) {continue}
if (Math.random() < con) { // If random number is less than conductivity
if (!newPixel.charge && !newPixel.chargeCD) {
newPixel.charge = 1;
if (elements[newPixel.element].colorOn) {
newPixel.color = pixelColorPick(newPixel);
}
}
}
else if (elements[newPixel.element].insulate != true) { // Otherwise heat the pixel (Resistance simulation)
newPixel.temp += pixel.charge/4;
pixelTempCheck(newPixel);
}
}
}
pixel.charge -= 0.25;
if (pixel.charge <= 0) {
if (elements[pixel.element].colorOn) {
pixel.color = pixelColorPick(pixel);
}
delete pixel.charge;
pixel.chargeCD = 4;
}
}
// Lower charge cooldown
else if (pixel.chargeCD) {
pixel.chargeCD -= 1;
if (pixel.chargeCD <= 0) {
delete pixel.chargeCD;
}
}
}
function pixelColorPick(pixel,customColor=null) {
var element = pixel.element;
var elementInfo = elements[element];
//if (elementInfo.behavior instanceof Array) {
if (pixel.charge && elementInfo.colorOn) {
customColor = elementInfo.colorOn;
}
if (customColor != null) {
if (Array.isArray(customColor)) {
customColor = customColor[Math.floor(Math.random() * customColor.length)];
}
if (customColor.startsWith("#")) {
customColor = hexToRGB(customColor);
}
var rgb = customColor;
}
else {
var rgb = elements[element].colorObject; // {r, g, b}
// If rgb is an array, choose a random item
if (Array.isArray(rgb)) {
rgb = rgb[Math.floor(Math.random() * rgb.length)];
}
}
// Randomly darken or lighten the RGB color
var coloroffset = Math.floor(Math.random() * (Math.random() > 0.5 ? -1 : 1) * Math.random() * 15);
var r = rgb.r + coloroffset;
var g = rgb.g + coloroffset;
var b = rgb.b + coloroffset;
// Make sure the color is within the RGB range
r = Math.max(0, Math.min(255, r));
g = Math.max(0, Math.min(255, g));
b = Math.max(0, Math.min(255, b));
var color = "rgb("+r+","+g+","+b+")";
/*}
else {
var color = elementInfo.color;
if (Array.isArray(color)) {
color = color[Math.floor(Math.random() * color.length)];
}
}*/
return color;
}
function pixelTempCheck(pixel) {
var elementInfo = elements[pixel.element];
if (pixel.temp < -273.15) { // Absolute Zero
pixel.temp = -273.15;
}
// If the pixel's temp >= the elementInfo tempHigh, change pixel.element to elementInfo.stateHigh
if (pixel.temp >= elementInfo.tempHigh) {
var result = elementInfo.stateHigh;
// If result is an array, choose a random item
if (Array.isArray(result)) {
result = result[Math.floor(Math.random() * result.length)];
}
pixel.element = result;
pixel.color = pixelColorPick(pixel);
if (pixel.burning) {
pixel.burning = false;
delete pixel.burnStart;
}
if (elements[result].burning == true) {
pixel.burning = true;
pixel.burnStart = pixelTicks;
}
}
// If the pixel's temp <= the elementInfo tempLow, change pixel.element to elementInfo.stateLow
else if (pixel.temp <= elementInfo.tempLow) {
var result = elementInfo.stateLow;
// If result is an array, choose a random item
if (Array.isArray(result)) {
result = result[Math.floor(Math.random() * result.length)];
}
pixel.element = result;
pixel.color = pixelColorPick(pixel);
if (pixel.burning) {
pixel.burning = false;
delete pixel.burnStart;
}
if (elements[result].burning) {
pixel.burning = true;
pixel.burnStart = pixelTicks;
}
}
}
function getNeighbors(pixel) {
var neighbors = [];
var x = pixel.x;
var y = pixel.y;
if (!isEmpty(x-1,y,true)) { neighbors.push(pixelMap[x-1][y]); }
if (!isEmpty(x+1,y,true)) { neighbors.push(pixelMap[x+1][y]); }
if (!isEmpty(x,y-1,true)) { neighbors.push(pixelMap[x][y-1]); }
if (!isEmpty(x,y+1,true)) { neighbors.push(pixelMap[x][y+1]); }
return neighbors;
}
hiding = false;
function drawPixels(forceTick=false) {
// newCurrentPixels = shuffled currentPixels
var newCurrentPixels = currentPixels.slice();
newCurrentPixels.sort(function() {return 0.5 - Math.random()});
for (var i = 0; i < newCurrentPixels.length; i++) {
pixel = newCurrentPixels[i];
//if (pixelMap[pixel.x][pixel.y] == undefined || currentPixels.indexOf(pixel) == -1) {continue}
if (pixel.del) {continue}
if ((!paused) || forceTick) {pixelTick(pixel);};
}
// Draw the current pixels
if (!hiding) {
var canvas = document.getElementById("game");
var ctx = canvas.getContext("2d");
for (var i = 0; i < newCurrentPixels.length; i++) {
pixel = newCurrentPixels[i];
if (pixelMap[pixel.x][pixel.y] == undefined) {continue}
ctx.fillStyle = pixel.color;
ctx.fillRect(pixel.x*pixelSize, pixel.y*pixelSize, pixelSize, pixelSize);
if (pixel.charge) { // Yellow glow on charge
if (!elements[pixel.element].colorOn) {
ctx.fillStyle = "rgba(255,255,0,0.5)";
ctx.fillRect(pixel.x*pixelSize, pixel.y*pixelSize, pixelSize, pixelSize);
}
}
}
}
if ((!paused) || forceTick) {pixelTicks++};
}
function tick() {
// If mouseIsDown, do mouseAction
if (mouseIsDown) {
mouseAction(null,mousePos.x,mousePos.y);
}
// Get the canvas
var canvas = document.getElementById("game");
var ctx = canvas.getContext("2d");
// Clear the canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawPixels();
if (currentElement == "pick" || currentElement == "lookup") {
var mouseOffset = 0;
}
else {
var mouseOffset = Math.trunc(mouseSize/2);
}
var topLeft = [mousePos.x-mouseOffset,mousePos.y-mouseOffset];
var bottomRight = [mousePos.x+mouseOffset,mousePos.y+mouseOffset];
// Draw a rectangle around the mouse
ctx.strokeStyle = "white";
ctx.strokeRect(topLeft[0]*pixelSize,topLeft[1]*pixelSize,(bottomRight[0]-topLeft[0]+1)*pixelSize,(bottomRight[1]-topLeft[1]+1)*pixelSize);
updateStats();
//ticks ++;
}
currentElement = "sand";
mouseIsDown = false;
mouseType = null;
function mouseClick(e) {
mouseIsDown = true;
// If it's a left click
if (e.button == 0) {
mouseType = "left";
}
else if (e.button == 2) {
mouseType = "right";
}
// middle click
else if (e.button == 1) {
mouseType = "middle";
}
else {
mouseType = "left";
}
mouseMove(e);
return false;
}
function mouseUp(e) {
mouseIsDown = false;
}
function getMousePos(canvas, evt) {
// If evt.touches is defined, use the first touch
if (evt.touches) {
evt.preventDefault();
evt = evt.touches[0];
}
var rect = canvas.getBoundingClientRect();
return {
// Round to nearest pixel
x: Math.round((evt.clientX - rect.left)/pixelSize-0.5),
y: Math.round((evt.clientY - rect.top)/pixelSize-0.5)
};
}
function mouseMove(e) {
if (mouseIsDown) {
mouseAction(e);
}
else {
var canvas = document.getElementById("game");
mousePos = getMousePos(canvas, e);
}
}
function mouseAction(e,mouseX=undefined,mouseY=undefined) {
if (showingMenu && currentElement != "lookup") {
closeMenu();
}
if (mouseType == "left") { mouse1Action(e,mouseX,mouseY); }
else if (mouseType == "right") { mouse2Action(e,mouseX,mouseY); }
else if (mouseType == "middle") { mouseMiddleAction(e,mouseX,mouseY); }
}
mouseSize = 5;
mousePos = {x:0,y:0};
function mouseRange(mouseX,mouseY) {
var coords = [];
var mouseOffset = Math.trunc(mouseSize/2);
var topLeft = [mouseX-mouseOffset,mouseY-mouseOffset];
var bottomRight = [mouseX+mouseOffset,mouseY+mouseOffset];
// Starting at the top left, go through each pixel
for (var x = topLeft[0]; x <= bottomRight[0]; x++) {
for (var y = topLeft[1]; y <= bottomRight[1]; y++) {
// If the pixel is empty, add it to coords
coords.push([x,y]);
}
}
return coords;
}
function mouse1Action(e,mouseX=undefined,mouseY=undefined) {
if (currentElement == "erase") { mouse2Action(e,mouseX,mouseY); return; }
else if (currentElement == "pick") { mouseMiddleAction(e,mouseX,mouseY); return; }
// If x and y are undefined, get the mouse position
if (mouseX == undefined && mouseY == undefined) {
var canvas = document.getElementById("game");
var ctx = canvas.getContext("2d");
mousePos = getMousePos(canvas, e);
var mouseX = mousePos.x;
var mouseY = mousePos.y;
}
if (currentElement == "lookup") {
if (!isEmpty(mouseX,mouseY,true)) {
showInfo(pixelMap[mouseX][mouseY].element);
}
return;
}
var coords = mouseRange(mouseX,mouseY);
var element = elements[currentElement];
var mixList = [];
// For each x,y in coords
for (var i = 0; i < coords.length; i++) {
var x = coords[i][0];
var y = coords[i][1];
// If element name is heat or cool
if (currentElement == "heat" || currentElement == "cool") {
if (!isEmpty(x,y,false)) {
if (outOfBounds(x,y)) {
continue;
}
var pixel = pixelMap[x][y];
if (shiftDown) {pixel.temp += element.temp+(Math.random()*element.temp*1.5)*20;}
else {pixel.temp += element.temp+(Math.random()*element.temp*1.5);}
pixelTempCheck(pixel);
}
}
else if (currentElement == "mix") {
if (!isEmpty(x,y,true)) {
var pixel = pixelMap[x][y];
if (pixel.element != "fire" & pixel.element != "smoke" || shiftDown) {
mixList.push(pixel);
}
}
}
else if (currentElement == "shock") {
if (!isEmpty(x,y,true)) {
// One loop that repeats 5 times if shiftDown else 1 time
for (var j = 0; j < (shiftDown ? 5 : 1); j++) {
var pixel = pixelMap[x][y];
var con = elements[pixel.element].conduct;
if (con == undefined) {continue}
if (Math.random() < con) { // If random number is less than conductivity
if (!pixel.charge && !pixel.chargeCD) {
pixel.charge = 1;
if (elements[pixel.element].colorOn) {
pixel.color = pixelColorPick(pixel);
}
}
}
else if (elements[pixel.element].insulate != true) { // Otherwise heat the pixel (Resistance simulation)
pixel.temp += 0.25;
pixelTempCheck(pixel);
}
}
}
}
else if (currentElement == "random" && isEmpty(x, y)) {
// create pixel with random element from "randomChoices" array
currentPixels.push(new Pixel(x, y, randomChoices[Math.floor(Math.random() * randomChoices.length)]));
}
else if (placeMode == "replace") {
if (outOfBounds(x,y)) {
continue;
}
// Remove pixel at position from currentPixels
var index = currentPixels.indexOf(pixelMap[x][y]);
if (index > -1) {
currentPixels.splice(index, 1);
}
currentPixels.push(new Pixel(x, y, currentElement));
}
else if (isEmpty(x, y)) {
currentPixels.push(new Pixel(x, y, currentElement));
}
}
if (currentElement == "mix") {
// 1. repeat for each pixel in mixList
// 2. choose 2 random pixels and swap their x and y
// 3. remove pixel from mixList
for (var i = 0; i < mixList.length; i++) {
var pixel1 = mixList[Math.floor(Math.random()*mixList.length)];
var pixel2 = mixList[Math.floor(Math.random()*mixList.length)];
swapPixels(pixel1,pixel2);
mixList.splice(mixList.indexOf(pixel1),1);
mixList.splice(mixList.indexOf(pixel2),1);
}
}
}
function mouse2Action(e,mouseX=undefined,mouseY=undefined) {
// Erase pixel at mouse position
if (mouseX == undefined && mouseY == undefined) {
var canvas = document.getElementById("game");
var ctx = canvas.getContext("2d");
mousePos = getMousePos(canvas, e);
var mouseX = mousePos.x;
var mouseY = mousePos.y;
}
// If the current element is "pick" or "lookup", coords = [mouseX,mouseY]
if (currentElement == "pick" || currentElement == "lookup") {
var coords = [[mouseX,mouseY]];
}
else {
var coords = mouseRange(mouseX,mouseY);
}
// For each x,y in coords
for (var i = 0; i < coords.length; i++) {
var x = coords[i][0];
var y = coords[i][1];
if (!isEmpty(x, y)) {
if (outOfBounds(x,y)) {
continue
}
var pixel = pixelMap[x][y];
delete pixelMap[x][y];
// Remove pixel from currentPixels
for (var j = 0; j < currentPixels.length; j++) {
if (currentPixels[j].x == x && currentPixels[j].y == y) {
currentPixels.splice(j, 1);
break;
}
}
}
}
}
function mouseMiddleAction(e, mouseX=undefined, mouseY=undefined) {
if (mouseX == undefined && mouseY == undefined) {
var canvas = document.getElementById("game");
var ctx = canvas.getContext("2d");
mousePos = getMousePos(canvas, e);
var mouseX = mousePos.x;
var mouseY = mousePos.y;
}
if (!isEmpty(mouseX, mouseY,true)) {
selectElement(pixelMap[mouseX][mouseY].element);
mouseIsDown = false;
}
}
function wheelHandle(e) {
e.preventDefault();
var deltaY = e.deltaY*0.1;
if (Math.round(deltaY) == 0) {
if (deltaY > 0) { deltaY = 1; }
else { deltaY = -1; }
}
mouseSize += Math.round(deltaY*2);
if (mouseSize < 1) { mouseSize = 1; }
if (mouseSize > (height > width ? height : width)) { mouseSize = (height > width ? height : width); }
}
function chooseElementPrompt() {
var e = prompt("Enter the element's ID")
if (elements[e] != undefined) {
e = e.replace(/ /g,"_");
selectElement(e);
var btn = document.getElementById("elementButton-"+e);
if (btn != null) {
btn.setAttribute("current","true");
}
};
}
function togglePause() {
paused = !paused;
if (paused) {
document.getElementById("pauseButton").setAttribute("on","true");
}
else {
document.getElementById("pauseButton").setAttribute("on","false");
}
}
function doFrame() {
if (!paused) {
paused = true;
document.getElementById("pauseButton").setAttribute("on","true");
}
drawPixels(true);
}
function selectElement(element) {
var e1 = document.getElementById("elementButton-"+currentElement);
if (e1 != null) { e1.setAttribute("current","false"); }
currentElement = element;
var e2 = document.getElementById("elementButton-"+element);
if (e2 != null) { e2.setAttribute("current","true"); }
}
function clearAll() {
currentPixels = [];
pixelMap = [];
for (var i = 0; i < width; i++) {
pixelMap[i] = [];
for (var j = 0; j < height; j++) {
pixelMap[i][j] = undefined;
}
}
pixelTicks = 0;
}
// Update stats
function updateStats() {
var statsDiv = document.getElementById("stats");
var stats = "<span id='stat-pos' class='stat'>x"+mousePos.x+",y"+mousePos.y+"</span>";
stats += "<span id='stat-pixels' class='stat'>Pxls:" + currentPixels.length+"</span>";
stats += "<span id='stat-tps' class='stat'>" + tps+"tps</span>";
stats += "<span id='stat-ticks' class='stat'>" + pixelTicks+"</span>";
if (typeof pixelMap == 'undefined') { return; }
if (pixelMap[mousePos.x] != undefined) {
var currentPixel = pixelMap[mousePos.x][mousePos.y];
if (currentPixel != undefined) {
stats += "<span id='stat-element' class='stat'>Elem:"+currentPixel.element.toUpperCase()+"</span>";
stats += "<span id='stat-temperature' class='stat'>Temp:"+Math.round(currentPixel.temp)+"°C</span>";
if (currentPixel.charge) {
stats += "<span id='stat-charge' class='stat'>C"+currentPixel.charge+"</span>";
}
if (currentPixel.burning) {
stats += "<span id='stat-burning' class='stat'>Burning</span>";
}
}
}
if (shiftDown) {
if (shiftDown==1) {stats += "<span id='stat-shift' class='stat'>[↑ ]</span>";}
else if (shiftDown==2) {stats += "<span id='stat-shift' class='stat'>[A ]</span>";}
else if (shiftDown==3) {stats += "<span id='stat-shift' class='stat'>[ ↑]</span>";}
else if (shiftDown==4) {stats += "<span id='stat-shift' class='stat'>[ A]</span>";}
}
statsDiv.innerHTML = stats;
}
showingMenu = false;
function infoLink(l) {
if (l instanceof Array) {
var newtext = "";
for (var i = 0; i < l.length; i++) {
var element = l[i];
// add to newtext a span with the element's name and its onclick to showInfo(element)
if (element=="pixels" || element=="itself") { newtext += element+", "}
else { newtext += "<span class='infoLink' onclick='showInfo(\""+element+"\")'>"+element.toUpperCase().replace(/_/g," ")+"</span>, ";}
}
// remove the last comma and space
newtext = newtext.substring(0, newtext.length-2);
return newtext
}
else {
if (l=="pixels" || l=="[???]" || l=="itself") {return l}
else {return "<span class='infoLink' onclick='showInfo(\""+l+"\")'>"+l.toUpperCase().replace(/_/g," ")+"</span>";}
}
}
function showInfo(element) { // this is such a mess please don't look at it
showingMenu = "info";
var infoParent = document.getElementById("infoParent");
infoParent.style.display = "block";
var infoSearch = document.getElementById("infoSearch");
infoSearch.focus();
var infoTitle = document.getElementById("infoTitle");
var infoText = document.getElementById("infoText");
if (element != undefined) {
// replace all spaces with underscores
element = element.replace(/ /g,"_");
infoSearch.value = element;
info = elements[element];
if (info) {
infoTitle.innerHTML = info.name || element.replace(/_/g," ");
infoTitle.innerHTML = infoTitle.innerHTML.replace(/\w\S*/g, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();});
infoText.innerHTML = "";
infoSearch.style.backgroundColor = "rgb(66, 66, 66)";
if (info.color) {
if (!(info.color instanceof Array)) {
infoText.innerHTML += "\nColor: <span style='background-color:"+info.color+"'> </span>";
}
else {
//gradient
var gradient = info.color;
var gradientString = "linear-gradient(to right";
for (var i = 0; i < gradient.length; i++) {
gradientString += ", "+gradient[i]+" "+(i*100/gradient.length)+"%";
}
gradientString += ")";
infoText.innerHTML += "\nColor: <span style='background:"+gradientString+"'> </span>";
}
}
var moves = false;
var deletes = [];
var swaps = [];
var creates = [];
var heats = false;
var cools = false;
var clones = false;
var sticks = [];
if (info.behavior) {
// for x and y in behavior array
for (var i = 0; i < info.behavior.length; i++) {
for (var j = 0; j < info.behavior[i][1].length; j++) {
var b0 = info.behavior[i][j];
if (!b0) { continue; }
for (var k = 0; k < b0.split(" AND ").length; k++) {
var b = b0.split(" AND ")[k];
// remove everything after %
b = b.split("%")[0];
if (b.indexOf(":") != -1) {
var arg = b.split(":")[1];
}
else { var arg = undefined }
var b = b.split(":")[0];
if (b == "M1" || b == "M2") {
moves = true;
}
else if (b == "DL") {
if (i==1 && j==1) { arg = "itself" }
else if (!arg) { arg = "pixels" }
if (deletes.indexOf(arg) == -1) { deletes = deletes.concat(arg.split(",")); }
}
else if (b == "SW") {
if (!arg) { arg = "pixels" }
if (swaps.indexOf(arg) == -1) { swaps = swaps.concat(arg.split(",")); }
}
else if (b == "CL") {
clones = true;
}
else if (b == "CR" || b == "CH" || b == "LB" || b == "L1" || b == "L2") {
if (!arg) { arg = "[???]" }
else if (arg.indexOf(">") != -1) { arg = arg.split(">")[1]; }
if (creates.indexOf(arg) == -1) { creates = creates.concat(arg.split(",")); }
}
else if (b == "HT") {
heats = true;
}
else if (b == "CO") {
cools = true;
}
else if (b == "ST") {
if (!arg) { arg = "pixels" }
if (sticks.indexOf(arg) == -1) { sticks = sticks.concat(arg.split(",")); }
}
}}}}
// make sure deletes, swaps, creates, and sticks have no duplicate items
deletes = deletes.filter(function(item, pos) {return deletes.indexOf(item) == pos;});
swaps = swaps.filter(function(item, pos) {return swaps.indexOf(item) == pos;});
creates = creates.filter(function(item, pos) {return creates.indexOf(item) == pos;});
sticks = sticks.filter(function(item, pos) {return sticks.indexOf(item) == pos;});
if (info.category == "tools") { infoText.innerHTML += "\nTool."}
else {
if (!moves) { infoText.innerHTML += "\nStationary."; }
if (info.category) { infoText.innerHTML += "\nCategory: "+info.category.toUpperCase()+"."; }
}
if (info.conduct) { infoText.innerHTML += "\nConducts electricity."; }
if (swaps.length > 0) { infoText.innerHTML += "\nMoves through "+infoLink(swaps)+"."; }
if (creates.length > 0) { infoText.innerHTML += "\nMakes "+infoLink(creates)+"."; }
if (clones) { infoText.innerHTML += "\nClones self." }
if (deletes.length > 0) { infoText.innerHTML += "\nDeletes "+infoLink(deletes)+"."; }
if (heats) { infoText.innerHTML += "\nHeats pixels." }
if (cools) { infoText.innerHTML += "\nCools pixels." }
if (sticks.length > 0) { infoText.innerHTML += "\nSticks to "+infoLink(sticks)+"."; }
if (info.hidden) { infoText.innerHTML += "\nHidden from toolbar."; }
if (info.density != undefined) { infoText.innerHTML += "\nDensity: "+info.density+"kgm<sup>3</sup>."; }
if (info.tempHigh != undefined) {
infoText.innerHTML += "\nTurns into "+infoLink(info.stateHigh || "[???]")+" above "+info.tempHigh+"°C.";
}
if (info.tempLow != undefined) {
infoText.innerHTML += "\nTurns into "+infoLink(info.stateLow || "[???]")+" below "+info.tempLow+"°C.";
}
if (info.burn != undefined) { infoText.innerHTML += "\nFlammability: "+info.burn+"%."; }
if (info.burnTime != undefined) {
infoText.innerHTML += "\nBurns for "+info.burnTime+" tick";
if (info.burnTime != 1) { infoText.innerHTML += "s"; }
infoText.innerHTML += ".";
}
if (info.burnInto) { infoText.innerHTML += "\nBurns into "+infoLink(info.burnInto)+"."; }
if (info.fireColor) {
if (!(info.fireColor instanceof Array)) {
infoText.innerHTML += "\nFlame Color: <span style='background-color:"+info.fireColor+"'> </span>";
}
else {
//gradient
var gradient = info.fireColor;
var gradientString = "linear-gradient(to right";
for (var i = 0; i < gradient.length; i++) {
gradientString += ", "+gradient[i]+" "+(i*100/gradient.length)+"%";
}
gradientString += ")";
infoText.innerHTML += "\nFlame Color: <span style='background:"+gradientString+"'> </span>";
}
}
if (info.reactions) {
infoText.innerHTML += "\nReacts with " + infoLink(Object.keys(info.reactions)) + ".";
}
infoText.innerHTML += "\n\n\n\n"
}
else {
infoTitle.innerHTML = "";
infoText.innerHTML = "";
// infoSearch red background
infoSearch.style.backgroundColor = "rgb(100, 33, 33)";
}
}
else {
infoTitle.innerHTML = "";
infoText.innerHTML = "";
infoSearch.style.backgroundColor = "rgb(66, 66, 66)";
}
}
function closeMenu() {
if (!showingMenu) { return; }
if (showingMenu == "info") {
var infoParent = document.getElementById("infoParent");
var infoSearch = document.getElementById("infoSearch");
infoParent.style.display = "none";
infoSearch.value = "";
showingMenu = false;
}
else if (showingMenu == "mods") {
var modParent = document.getElementById("modParent");
var modManagerUrl = document.getElementById("modManagerUrl");
modParent.style.display = "none";
modManagerUrl.value = "";
showingMenu = false;
}
}
function showModManager() {
var modParent = document.getElementById("modParent");
var modManagerUrl = document.getElementById("modManagerUrl");
modParent.style.display = "block";
modManagerUrl.focus();
showingMenu = "mods";
}
function addMod(url) {
// remove trailing slashes
while (url.charAt(url.length-1) == "/") { url = url.substring(0, url.length-1); }
// if the mod is in enabledMods, return
for (var i = 0; i < enabledMods.length; i++) {
if (enabledMods[i] == url) { return; }
}
// if the url doesn't have a slash or a dot, alert
if (url.indexOf("/") == -1 && url.indexOf(".") == -1) {
alert("Invalid mod URL.");
return;
}
// if the url doesn't start with http, add "mods/" to the beginning
if (url.indexOf("http") == -1) { url = "mods/"+url; }
// add it to enabledMods and set the localStorage
enabledMods.push(url);
localStorage.setItem("enabledMods", JSON.stringify(enabledMods));
// add to modManagerList
var modManagerList = document.getElementById("modManagerList");
var modName = url.split("/").pop();
modManagerList.innerHTML += "<li><a href='" + url + "' target='_blank'>" + modName + "</a> <span class='removeModX' onclick='removeMod(\"" + url + "\")'>X</span></li>";
alert("Added mod. Refresh the page to see changes.");
}
function removeMod(url) {
// remove url from enabledMods and set the localStorage
for (var i = 0; i < enabledMods.length; i++) {
if (enabledMods[i] == url) {
enabledMods.splice(i, 1);
break;
}
}
localStorage.setItem("enabledMods", JSON.stringify(enabledMods));
// remove from modManagerList by href
var modManagerList = document.getElementById("modManagerList");
var modManagerListLinks = modManagerList.getElementsByTagName("a");
for (var i = 0; i < modManagerListLinks.length; i++) {
if (modManagerListLinks[i].href.endsWith(url)) {
modManagerListLinks[i].parentNode.remove();
break;
}
}
alert("Removed mod. Refresh the page to see changes.");
}
// On window load, run tick() 20 times per second
tps = 30;
tickInterval = window.setInterval(tick, 1000/tps);
function resetInterval(newtps=30) {
window.clearInterval(tickInterval);
tickInterval = window.setInterval(tick, 1000/newtps);
}
//ticks = 0;
pixelTicks = 0;
placeMode = null;
paused = false;
function focusGame() { document.getElementById("game").focus(); if(showingMenu) { closeMenu(); } }
//on window load
window.onload = function() {
// Loop through runAfterLoadList and run each function
for (var i = 0; i < runAfterLoadList.length; i++) {
runAfterLoadList[i]();
}
// Loop through behaviors and each behavior, if it is a string, split the items and replace the value with the array
for (var behavior in behaviors) {
if (typeof behaviors[behavior][0] === "string") {
var newbehavior = [];
for (var i = 0; i < behaviors[behavior].length; i++) {
newbehavior.push(behaviors[behavior][i].split("|"));
}
behaviors[behavior] = newbehavior;
}
}
// convert every color in the elements object to rgb
for (var key in elements) {
if (elements.hasOwnProperty(key)) {
// if the element has no color, skip it
if (elements[key].color === undefined) {
continue;
}
// if the color is an array, loop over each one
if (elements[key].color instanceof Array) {
var rgbs = [];
var rgbos = [];
for (var i = 0; i < elements[key].color.length; i++) {
var c = elements[key].color[i];
if (c.startsWith("#")) {
var rgb = hexToRGB(c);
rgbs.push("rgb("+rgb.r+","+rgb.g+","+rgb.b+")");
rgbos.push(rgb);
}
else {
rgbs.push(c);
}
}
elements[key].color = rgbs;
elements[key].colorObject = rgbos;
} else {
// if elements[key].color starts with #
if (elements[key].color.startsWith("#")) {
var rgb = hexToRGB(elements[key].color);
elements[key].color = "rgb("+rgb.r+","+rgb.g+","+rgb.b+")";
elements[key].colorObject = rgb;
}
}
}
}
// Automatic molten element generation
// Loop through each element. If it has a tempHigh, but not a stateHigh, create a new molten element
for (element in elements) {
if (elements[element].tempHigh && !elements[element].stateHigh) {
var newname = "molten_"+element;
elements[element].stateHigh = newname;
var newcolor = elements[element].colorObject;
var colorList = [];
var colorObjectList = [];
// if newcolor is not an array, put it in an array
if (!(newcolor instanceof Array)) {
newcolor = [newcolor];
}
// for every color in the newcolor array, add a new color with the same value, but with the r and g values increased
for (var i = 0; i < newcolor.length; i++) {
var c = newcolor[i];
r = c.r * 2;
g = c.g * 1.25;
b = c.b * 0.5;
if (r > 255) {r = 255;}
if (g > 255) {g = 255;}
colorList.push("rgb("+r+","+g+","+b+")");
colorObjectList.push({r:r,g:g,b:b});
r = c.r * 2;
g = c.g;
b = c.b * 0.5;
if (r > 255) {r = 255;}
if (g > 255) {g = 255;}
colorList.push("rgb("+r+","+g+","+b+")");
colorObjectList.push({r:r,g:g,b:b});
r = c.r * 2;
g = c.g * 0.75;
b = 0;
if (r > 255) {r = 255;}
if (g > 255) {g = 255;}
colorList.push("rgb("+r+","+g+","+b+")");
colorObjectList.push({r:r,g:g,b:b});
}
var newmolten = {
//"name": newname.replaceAll("_"," "),
color: colorList,
"colorObject": colorObjectList,
behavior: behaviors.MOLTEN,
temp: elements[element].tempHigh,
tempLow: elements[element].tempHigh-100,
stateLow: element,
viscosity: elements[element].viscosity || 10000,
hidden: true,
state: "liquid",
}
// If the element has a density, add it to the new molten element * 0.9
if (elements[element].density) { newmolten.density = Math.round(elements[element].density * 0.9 * 10) / 10; }
// If the element has a conductivity, add it to the new molten element * 1.1
if (elements[element].conduct) { newmolten.conductivity = Math.round(elements[element].conduct * 1.1 * 10) / 10; }
// Same for burn, burnTime, burnInto, and fireColor
if (elements[element].burn) { newmolten.burn = Math.round(elements[element].burn * 1.1 * 10) / 10; }
if (elements[element].burnTime) { newmolten.burnTime = Math.round(elements[element].burnTime * 1.1 * 10) / 10; }
if (elements[element].burnInto) { newmolten.burnInto = elements[element].burnInto; }
if (elements[element].fireColor) { newmolten.fireColor = elements[element].fireColor; }
// If the new element doesn't exist, add it
if (!elements[newname]) { elements[newname] = newmolten; }
else {
// Loop through newmolten's keys and values, copy them to the new element if they are not already defined
for (var key in newmolten) {
if (elements[newname][key] == undefined) {
elements[newname][key] = newmolten[key];
}
}
}
}
if (elements[element].behavior && typeof elements[element].behavior[0] === "string") {
var newbehavior = [];
for (var i = 0; i < elements[element].behavior.length; i++) {
newbehavior.push(elements[element].behavior[i].split("|"));
}
elements[element].behavior = newbehavior;
}
if (elements[element].behaviorOn && typeof elements[element].behaviorOn[0] === "string") {
var newbehavior = [];
for (var i = 0; i < elements[element].behaviorOn.length; i++) {
newbehavior.push(elements[element].behaviorOn[i].split("|"));
}
elements[element].behaviorOn = newbehavior;
}
}
// Loop through each element, final checks
for (key in elements) {
// If the element has no behavior, set it to behaviors.WALL
if (!elements[key].behavior) {
elements[key].behavior = behaviors.WALL;
}
// If the element has no color, set it to white
if (elements[key].color === undefined) {
elements[key].color = "rgb(255,255,255)";
elements[key].colorObject = {r:255,g:255,b:255};
}
// If the element's behavior[1][1] includes "FX", set it's flippableX to true
if (elements[key].behavior[1][1].includes("FX")) {
elements[key].flippableX = true;
}
// If the element's behavior[1][1] includes "FY", set it's flippableY to true
if (elements[key].behavior[1][1].includes("FY")) {
elements[key].flippableY = true;
}
// If the element's behavior[1][1] includes "RT", set it's rotatable to "true"
if (elements[key].behavior[1][1].includes("RT")) {
elements[key].rotatable = true;
}
// If the element has reactions, loop through each one (it is an object), if the value for elem1 or elem2 is not an element and is not null, remove that key
if (elements[key].reactions) {
for (var reaction in elements[key].reactions) {
// If elem1 exists
if (elements[key].reactions[reaction].elem1) {
// If elem1 is an array, loop through each element, else check once. Don't delete if it === null
if (Array.isArray(elements[key].reactions[reaction].elem1)) {
for (var i = 0; i < elements[key].reactions[reaction].elem1.length; i++) {
if (elements[key].reactions[reaction].elem1[i] && !elements[elements[key].reactions[reaction].elem1[i]]) {
elements[key].reactions[reaction].elem1.splice(i,1);
}
}
}
else if (elements[key].reactions[reaction].elem1 && !elements[elements[key].reactions[reaction].elem1]) {
delete elements[key].reactions[reaction].elem1;
}
}
// If elem2 exists
if (elements[key].reactions[reaction].elem2) {
// If elem2 is an array, loop through each element, else check once. Don't delete if it === null
if (Array.isArray(elements[key].reactions[reaction].elem2)) {
for (var i = 0; i < elements[key].reactions[reaction].elem2.length; i++) {
if (elements[key].reactions[reaction].elem2[i] && !elements[elements[key].reactions[reaction].elem2[i]]) {
elements[key].reactions[reaction].elem2.splice(i,1);
}
}
}
else if (elements[key].reactions[reaction].elem2 && !elements[elements[key].reactions[reaction].elem2]) {
delete elements[key].reactions[reaction].elem2;
}
}
}
}
// If the element's stateHigh or stateLow is not an element, remove it and tempHigh/Low
if (elements[key].stateHigh) {
// If it's an array, do it for each item, otherwise, just do it once
if (Array.isArray(elements[key].stateHigh)) {
for (var i = 0; i < elements[key].stateHigh.length; i++) {
if (!elements[elements[key].stateHigh[i]]) {
elements[key].stateHigh.splice(i,1);
}
}
if (elements[key].stateHigh.length == 0) {
delete elements[key].stateHigh;
delete elements[key].tempHigh;
}
}
else {
if (!elements[elements[key].stateHigh]) {
delete elements[key].stateHigh;
delete elements[key].tempHigh;
}
}
}
if (elements[key].stateLow) {
if (Array.isArray(elements[key].stateLow)) {
for (var i = 0; i < elements[key].stateLow.length; i++) {
if (!elements[elements[key].stateLow[i]]) {
elements[key].stateLow.splice(i,1);
}
}
if (elements[key].stateLow.length == 0) {
delete elements[key].stateLow;
delete elements[key].tempLow;
}
}
else {
if (!elements[elements[key].stateLow]) {
delete elements[key].stateLow;
delete elements[key].tempLow;
}
}
}
// same for burnInto
if (elements[key].burnInto) {
if (Array.isArray(elements[key].burnInto)) {
for (var i = 0; i < elements[key].burnInto.length; i++) {
if (!elements[elements[key].burnInto[i]]) {
delete elements[key].burnInto[i];
}
}
if (elements[key].burnInto.length == 0) {
delete elements[key].burnInto;
}
}
else {
if (!elements[elements[key].burnInto]) {
delete elements[key].burnInto;
}
}
}
}
// While the mouse is down, run mouseDown()
var gameCanvas = document.getElementById("game");
// Get context
var ctx = gameCanvas.getContext("2d");
var newWidth = Math.ceil(window.innerWidth*0.9 / pixelSize) * pixelSize;
var newHeight = Math.ceil(window.innerHeight*0.675 / pixelSize) * pixelSize;
// If the new width is greater than 800, set it to 800
if (newWidth > 1000) { newWidth = 1000; }
// If we are on a desktop and the new height is greater than 600, set it to 600
if (window.innerWidth > 1000 && newHeight > 500) { newHeight = 500; }
ctx.canvas.width = newWidth;
ctx.canvas.height = newHeight;
width = Math.round(newWidth/pixelSize)-1;
height = Math.round(newHeight/pixelSize)-1;
// Object with width arrays of pixels starting at 0
pixelMap = {};
for (var i = 0; i < width; i++) {
pixelMap[i] = [];
}
// randomChoices = the keys of "elements" with "filler", "lattice", "gray_goo", and any element with the category "tools" removed
randomChoices = Object.keys(elements).filter(function(e) {
return e != "filler" && e != "lattice" && e != "gray_goo" && elements[e].category != "tools" && e != "random" && e != "virus" && e != "vertical" && e != "horizontal" && e != "snake";
});
//...drawing code...
gameCanvas.addEventListener("mousedown", mouseClick);
gameCanvas.addEventListener("touchstart", mouseClick, { passive: false });
window.addEventListener("mouseup", mouseUp);
window.addEventListener("touchend", mouseUp, { passive: false });
window.addEventListener("mousemove", mouseMove);
gameCanvas.addEventListener("touchmove", mouseMove, { passive: false });
gameCanvas.addEventListener("wheel", wheelHandle);
gameCanvas.ontouchstart = function(e) {
if (e.touches) e = e.touches[0];
return false;
}
window.onbeforeunload = function(){ // Confirm leaving page if there are pixels on-screen
if (currentPixels.length > 0){
return 'Are you sure you want to leave?';
}
};
// If enabledMods has items, add an li to modManagerList for each item with the href to the item, target blank, and the item's name, with "<span class="removeModX" onclick='removeMod('>X</span>" after the link
if (enabledMods.length > 0) {
modManagerList = document.getElementById("modManagerList");
for (var i = 0; i < enabledMods.length; i++) {
var mod = enabledMods[i];
// modName is the last part of the mod's path
var modName = mod.split("/").pop();
modManagerList.innerHTML += "<li><a href='" + mod + "' target='_blank'>" + modName + "</a> <span class='removeModX' onclick='removeMod(\"" + mod + "\")'>X</span></li>";
}
}
shiftDown = 0;
// If the user presses [ or -, decrease the mouse size by 2
document.addEventListener("keydown", function(e) {
if (showingMenu) {
// esc or / to close
if (e.keyCode == 27 || (e.keyCode == 191 && showingMenu=="info")) { closeMenu(); }
// enter to clear infoSearch
else if (e.keyCode == 13 && showingMenu == "info") {
var infoSearch = document.getElementById("infoSearch");
infoSearch.value = "";
showInfo();
}
return;
}
if (e.keyCode == 219 || e.keyCode == 189) {
if (shiftDown) {mouseSize = 1}
else {
mouseSize -= 2;
if (mouseSize < 1) { mouseSize = 1; }
}
}
// If the user presses ] or =, increase the mouse size by 2
if (e.keyCode == 221 || e.keyCode == 187) {
if (shiftDown) {mouseSize = (mouseSize+15)-((mouseSize+15) % 15)}
else {mouseSize += 2;}
// if height>width and mouseSize>height, set mouseSize to height, if width>height and mouseSize>width, set mouseSize to width
if (mouseSize > (height > width ? height : width)) { mouseSize = (height > width ? height : width); }
}
// User presses shift
else if (e.keyCode == 16) {
if (event.location === KeyboardEvent.DOM_KEY_LOCATION_LEFT) {
shiftDown = 1;
} else if (event.location === KeyboardEvent.DOM_KEY_LOCATION_RIGHT) {
shiftDown = 3;
}
}
// User presses alt
else if (e.keyCode == 18) {
if (event.location === KeyboardEvent.DOM_KEY_LOCATION_LEFT) {
shiftDown = 2;
} else if (event.location === KeyboardEvent.DOM_KEY_LOCATION_RIGHT) {
shiftDown = 4;
}
}
// p or spacebar or ` or k = pause
if (e.keyCode == 80 || e.keyCode == 32 || e.keyCode == 192 || e.keyCode == 75) {
e.preventDefault();
togglePause();
}
// e = chooseElementPrompt()
else if (e.keyCode == 69) {
e.preventDefault();
chooseElementPrompt();
}
// . = doFrame()
else if (e.keyCode == 190) {
e.preventDefault();
doFrame();
}
// / or i = showInfo()
else if (e.keyCode == 191 || e.keyCode == 73) {
e.preventDefault();
showInfo();
}
// f = full screen
else if (e.keyCode == 70) {
e.preventDefault();
if (document.fullscreenElement) {
document.exitFullscreen(document.body);
} else {
requestFullScreen(document.body);
}
}
});
// If the user releases either shift
document.addEventListener("keyup", function(e) {
if (e.keyCode == 16 || e.keyCode == 18) { shiftDown = 0; }
});
// Create buttons for elements
// For each element type in elements, create a button in controls that sets the current element to that type
// Alphabetically sort and loop through dictionary named "elements"
elementCount = 0;
hiddenCount = 0;
for (var element in elements) {
elementCount++;
if (elements[element].hidden) { hiddenCount++; continue; }
var category = elements[element].category;
if (category==null) {category="Other"}
var categoryDiv = document.getElementById("category-"+category);
if (categoryDiv == null) {
categoryButton = document.createElement("button");
categoryButton.id = "categoryButton-"+category;
categoryButton.innerHTML = category.replace("."," ").replace(/\w\S*/g, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();}).replace(" ",".").replace(/ /g, "");;
categoryButton.className = "categoryButton";
categoryButton.setAttribute("category",category);
categoryButton.onclick = function() {
var category = this.getAttribute("category");
var categoryDiv = document.getElementById("category-"+category);
// Show this categoryDiv and hide all others
for (var i = 0; i < this.parentNode.children.length; i++) {
var e = categoryDiv.parentNode.children[i];
e.style.display = "none";
// Set the categoryButton of categoryDiv's category attribute to current=false
document.getElementById("categoryButton-"+e.getAttribute("category")).setAttribute("current",false);
}
categoryDiv.style.display = "block";
this.setAttribute("current", true);
}
document.getElementById("categoryControls").appendChild(categoryButton);
categoryDiv = document.createElement("div");
//categoryDiv.innerHTML = "<span class='categoryName'>"+category+"</span>";
categoryDiv.setAttribute("id","category-"+category);
categoryDiv.setAttribute("category",category);
categoryDiv.setAttribute("class","category");
document.getElementById("elementControls").appendChild(categoryDiv);
}
var button = document.createElement("button");
// if the element has the attribute "name", use that as the button's text, otherwise use the element with underscores replaced by spaces
if (elements[element].name) {
button.innerHTML = elements[element].name;
}
else {
button.innerHTML = element.replace(/_/g, " ");
}
//capitalize first letter of each word
button.innerHTML = button.innerHTML.replace("."," ").replace(/\w\S*/g, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();}).replace(" ",".").replace(/ /g, "");
//set attribute of element to the element
button.setAttribute("element", element);
button.setAttribute("current", "false");
button.className = "elementButton";
//color of the element
// if the element color is an array, make a gradient background color, otherwise, set the background color to the element color
if (elements[element].color instanceof Array) {
button.style.backgroundImage = "linear-gradient(to bottom right, "+elements[element].color.join(", ")+")";
// choose the middlemost item in array
var colorObject = elements[element].colorObject[Math.floor(elements[element].colorObject.length/2)];
if ((colorObject.r+colorObject.g+colorObject.b)/3 > 200) {
button.className += " bright"
}
}
else {
button.style.background = elements[element].color;
var colorObject = elements[element].colorObject;
if ((colorObject.r+colorObject.g+colorObject.b)/3 > 200) {
button.className += " bright"
}
}
button.id = "elementButton-" + element;
button.onclick = function() {
selectElement(this.getAttribute("element"));
}
// on right click, show the element's info
button.oncontextmenu = function(e) {
e.preventDefault();
showInfo(this.getAttribute("element"));
}
categoryDiv.appendChild(button);
}
// Set the first button in categoryControls div to be the current category
document.getElementById("categoryControls").children[0].click()
document.getElementById("extraInfo").innerHTML += "<p><small>There are " + elementCount + " elements, including " + hiddenCount + " hidden ones.</small></p>";
selectElement(currentElement);
focusGame();
// For every button element, onkeyup="event.preventDefault()"
var buttonElements = document.getElementsByTagName("button");
for (var i = 0; i < buttonElements.length; i++) {
buttonElements[i].onkeyup = function(e) {
e.preventDefault();
}
}
}
</script>
</head>
<body>
<h1 class="pagetitle">
<a href="https://R74n.com" class="backbutton" target="_blank">&lt;</a> Sandboxels</h1>
<div id="gameDiv">
<canvas id="game" width="800" height="600" oncontextmenu="return false;">
Your browser does not support the HTML5 canvas tag.<br>
Please update your browser to the latest version.<br>
<a href="https://www.google.com/chrome/">Chrome</a> 4.0+<br>
<a href="https://www.mozilla.org/firefox/new/">Firefox</a> 2.0+<br>
<a href="http://www.apple.com/safari/">Safari</a> 3.1+<br><br>
<a href="http://www.opera.com/">Opera</a> 9.0+<br>
<a href="http://www.microsoft.com/windows/internet-explorer/default.aspx">Internet Explorer</a> 9.0+<br>
</canvas>
<div id="underDiv">
<div id="stats"></div>
<div id="controls">
<div id="toolControls">
<button id="pauseButton" title="Pause/play the simulation" class="controlButton" onclick='togglePause();focusGame();' on="false">Pause</button><button id="frameButton" title="Pause and play one frame" class="controlButton" onclick='doFrame();focusGame();' on="false">Step</button><button id="sizeDownButton" title="Decrease the brush size" class="controlButton" onclick="mouseSize -= 2;if (mouseSize < 1) { mouseSize = 1; };focusGame();">-</button><button id="sizeUpButton" title="Increase the brush size" class="controlButton" onclick="mouseSize += 2;if (mouseSize > (height > width ? height : width)) { mouseSize = (height > width ? height : width); };focusGame();">+</button><button id="resetButton" title="Clear the entire scene" class="controlButton" onclick="if (confirm('Are you sure you want to clear the whole scene?')) {clearAll();};focusGame();">Reset</button><button id="replaceButton" title="Override existing pixels when placing" class="controlButton" onclick='if (placeMode == "replace") {placeMode = null;this.setAttribute("on","false");}else {placeMode = "replace";this.setAttribute("on","true");};focusGame();' on="false">Replace</button><button id="elemSelectButton" title="Select an element by ID" class="controlButton" onclick='chooseElementPrompt();focusGame();'>E</button><button id="tpsButton" title="Change the simulation Ticks Per Second (TPS)" class="controlButton" onclick='var newtps = prompt("Enter the new simulation Ticks Per Second (TPS). This is how many updates per second the simulation will run.\n\nThe default is 30.\n\nThe current TPS is " + tps + ".");if (newtps !== null) {if (isNaN(newtps) || newtps == "" || newtps == "0") {alert("You did not enter a valid TPS.");}else if (newtps > 1000) {alert("You entered a TPS that is too high. The TPS will be set to the maximum, 1000.");tps = 1000;}else {tps = parseInt(newtps);if (isNaN(tps)) {alert("You did not enter a valid TPS.");tps = 30;}}resetInterval(tps);}focusGame();'>Tps</button><button id="hideButton" title="Stops updating the scene to allow more resources towards simulation" class="controlButton" onclick='if (hiding) {hiding = false;this.setAttribute("on","false");}else {hiding = true;this.setAttribute("on","true");};focusGame();' on="false">Hide</button><button id="infoButton" title="Brings up the element info screen" class="controlButton" onclick='if (showingMenu!="info"){closeMenu();showInfo(currentElement)}else{closeMenu()};' on="false">Info</button><button id="modsButton" title="Brings up the Mod Manager" class="controlButton" onclick='if (showingMenu!="mods"){closeMenu();showModManager()}else{closeMenu()};' on="false">Mods</button>
</div>
<div id="category-tools" category="tools" style="display: block;"></div>
<div id="categoryControls"></div>
<div id="elementControls"></div>
</div>
<div id="extraInfo"><small><a href="controls.txt" target="_blank">Controls</a><a href="changelog.txt" target="_blank">Changelog</a><a href="https://docs.google.com/document/d/1R8xljj_J-K5oU-9y4louwplQmM-ZBvUfXmhbgj5LYdk/edit?usp=sharing" target="_blank">Feedback</a></small></div>
</div>
</div>
<div id="infoParent">
<div id="infoScreen"> <!--Element Info Page-->
<button class="XButton" onclick="closeMenu();">-</button>
<span class="menuTitle" id="infoTitle">Title</span>
<div class="menuText" id="infoText">Text</div>
</div>
<input type="text" id="infoSearch" placeholder="Element..." oninput="showInfo(this.value);"></input>
</div>
<!--Mod Manager Page with the list of current mods and a url input box with a plus button to add it-->
<div id="modParent">
<div id="modManager">
<button class="XButton" onclick="closeMenu();">-</button>
<span class="menuTitle">Enabled Mods</span>
<ul class="menuText" id="modManagerList"></ul>
<!--If the key is Enter, addMod -->
</div>
<input type="text" id="modManagerUrl" placeholder=".JS URL..." onkeydown="if (event.keyCode == 13) {addMod(this.value);this.value = '';};this.focus();"></input>
<!-- <button id="modManagerAdd" onclick="addMod(document.getElementById('modManagerUrl').value); document.getElementById('modManagerUrl').value = '';">+</button> -->
</div>
<!-- i like having this but ublock blocks these things anyway -->
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-T6E9BCPM32"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-T6E9BCPM32');
</script>
</body>
</html>