function roundToChunkIndex(%pos) {
	%x = mFloor(getWord(%pos, 0) / 16); // 32x Cube
	%y = mFloor(getWord(%pos, 1) / 16); // 32x Cube

	return %x SPC %y;
}

function ChunkSO(%x, %y, %dim) {
	if (!isObject(MCWorld)) {
		error("ERROR: No MCWorld exists!");
		return -1;
	}

	if (%dim $= "") {
		%dim = 0;
	}

	if (isObject(MCWorld.chunk[%x, %y, %dim])) {
		return MCWorld.chunk[%x, %y, %dim];
	}

	%obj = new SimSet() {
		dimension = %dim;
		position = %x SPC %y SPC 0;
		index = %x SPC %y;
	};

	MCWorld.chunk[%x, %y, %dim] = %obj;
	MCWorld.add(%obj);

	%obj.generateChunk();
	return %obj;
}

function SimSet::getPosition(%this) {
	return vectorAdd(vectorScale(%this.position, 16), "0 0" SPC 1024 * %this.dimension);
}

function SimSet::setBlock(%this, %x, %y, %z, %dataBlock) {
	if (%dataBlock !$= "" && !isObject(%dataBlock)) {
		%dataBlock = "mc_blockData_" @ %dataBlock;
	}

	if (!isObject(%dataBlock)) {
		%dataBlock = -1;
	}
	else {
		%dataBlock = %dataBlock.getID();
	}

	%x = mFloor(%x);
	%y = mFloor(%y);
	%z = mfloor(%z);

	if (%x < 0 || %y < 0 || %z < 0) {
		return false;
	}

	if (%x > 15 || %y > 15 || %z > 155) {
		return false;
	}

	%obj = %this.block[%x, %y, %z];

	if (isObject(%obj)) {
		if (%dataBlock != -1 && %obj.getDataBlock() == %dataBlock) {
			return true;
		}
		else {
			%this.block[%x, %y, %z] = "";
			%obj.delete();

			if (%dataBlock == -1) {
				if (%this.getBlock(%x, %y, %z + 1) $= "Sand") {
					for (%i = %z; %i >= 0; %i--) {
						if (%this.getBlock(%x, %y, %i) $= "") {
							%last = %i;
						}
						else {
							break;
						}
					}

					if (%last !$= "") {
						%this.setBlock(%x, %y, %last, Sand);
						%this.setBlock(%x, %y, %z + 1);
					}
				}
			}
		}
	}

	if (%dataBlock == -1) {
		return;
	}

	if (%this.getBlock(%x, %y, %z - 1) $= "GrassBlock" && !%dataBlock.allowOnGrass) {
		%this.setBlock(%x, %y, %z - 1, "Dirt");
	}

	%this.generatedPoint[%x, %y, %z] = true;

	%pos = vectorAdd(%this.getPosition(), %x SPC %y SPC %z);
	%pos = vectorAdd(%pos, "0 0" SPC $MC::GlobalBlockOffsetZ);

	if (%dataBlock.mcBlockOffsetZ !$= "") {
		%pos = vectorAdd(%pos, "0 0" SPC %dataBlock.mcBlockOffsetZ);
	}

	//BlockActionQueue().push(0 SPC %pos SPC %x SPC %y SPC %z SPC %dataBlock SPC %this);
	//return true;

	%obj = new fxDTSBrick() {
		position = %pos;
		dataBlock = %dataBlock;

		colorId = 0;
		isPlanted = true;

		chunk = %this;
	};

	%this.add(%obj);
	BrickGroup_888888.add(%obj);

	%obj.setTrusted(true);
	%obj.plant();

	%this.block[%x, %y, %z] = %obj;
	%name = %dataBlock.getName();

	return true;
}

function SimSet::getBlock(%this, %x, %y, %z) {
	%obj = %this.block[%x, %y, %z];

	if (isObject(%obj)) {
		return strReplace(%obj.getDataBlock().getName(), "mc_blockData_", "");
	}

	return "";
}

function SimSet::getTerrainHeight(%this, %x, %y) {
	%x = getWord(%this.position, 0) * 16 + %x;
	%y = getWord(%this.position, 1) * 16 + %y;

	return %this.getGroup().getTerrainHeight(%x, %y);
}
