427 lines
8.8 KiB
ActionScript
427 lines
8.8 KiB
ActionScript
import biomes;
|
|
import buildings;
|
|
|
|
enum SurfaceFlags {
|
|
SuF_Usable = 1,
|
|
};
|
|
|
|
void preparePlanetShader(Object& obj) {
|
|
#section client
|
|
vec4f picks;
|
|
|
|
getBiomePicks(obj, getBiome(obj.Biome0), picks);
|
|
shader::BIOME_PICKS[0] = picks;
|
|
|
|
getBiomePicks(obj, getBiome(obj.Biome1), picks);
|
|
shader::BIOME_PICKS[1] = picks;
|
|
|
|
getBiomePicks(obj, getBiome(obj.Biome2), picks);
|
|
shader::BIOME_PICKS[2] = picks;
|
|
|
|
shader::PLANET_FULL_GRID_SIZE = vec2f(obj.surfaceGridSize);
|
|
shader::PLANET_SURFACE_GRID_SIZE = vec2f(obj.originalGridSize);
|
|
#section all
|
|
}
|
|
|
|
void getBiomePicks(Object& obj, const Biome@ biome, vec4f& picks) {
|
|
if(biome is null)
|
|
return;
|
|
picks = biome.picks;
|
|
picks.z += (biome.lookupRange.y - biome.lookupRange.x) * double((obj.id * 2654435761) % 127) / 127.0 + biome.lookupRange.x;
|
|
}
|
|
|
|
void renderSurfaceData(Object& obj, PlanetSurface& surface, Image& output, const vec2u& sizeLimit = vec2u(0,0), bool citiesMode = false) {
|
|
Image@ img = output;
|
|
vec2u size = surface.size;
|
|
vec2u origSize = vec2u(obj.originalGridSize);
|
|
if(sizeLimit.x != 0 && sizeLimit.y != 0)
|
|
size = sizeLimit;
|
|
if(img.size != size)
|
|
@img = Image(size, 4);
|
|
|
|
const Biome@ biome0;
|
|
const Biome@ biome1;
|
|
const Biome@ biome2;
|
|
|
|
if(surface.biomes.length == 1) {
|
|
@biome0 = getBiome(obj.Biome0);
|
|
}
|
|
else if(surface.biomes.length == 2) {
|
|
@biome0 = getBiome(obj.Biome0);
|
|
@biome1 = getBiome(obj.Biome1);
|
|
}
|
|
else if(surface.biomes.length >= 3) {
|
|
@biome0 = getBiome(obj.Biome0);
|
|
@biome1 = getBiome(obj.Biome1);
|
|
@biome2 = getBiome(obj.Biome2);
|
|
}
|
|
|
|
for(uint y = 0; y < size.height; ++y) {
|
|
for(uint x = 0; x < size.width; ++x) {
|
|
const Biome@ biome = surface.getBiome(x, y);
|
|
|
|
Color output(0);
|
|
if(x >= origSize.x || y >= origSize.y) {
|
|
if(biome.isMoon) {
|
|
output.r = 0xff;
|
|
}
|
|
else if(biome.isVoid) {
|
|
//output.a = 0; //implied
|
|
}
|
|
else {
|
|
output.g = 0xff;
|
|
}
|
|
}
|
|
else {
|
|
output.b = 0x80;
|
|
if(citiesMode) {
|
|
if(surface.getBuilding(x, y) !is null)
|
|
output.a = 0xff;
|
|
else
|
|
output.a = 0x0;
|
|
}
|
|
else {
|
|
output.a = 0xff;
|
|
}
|
|
|
|
if(biome.isCrystallic)
|
|
output.b = 0;
|
|
|
|
if(biome.isVoid) {
|
|
output.a = 0;
|
|
}
|
|
else if(biome.isWater) {
|
|
output.b = 0xff;
|
|
}
|
|
else if(biome is biome0) {
|
|
//output.r = 0; //implied
|
|
//output.g = 0; //implied
|
|
}
|
|
else if(biome is biome1) {
|
|
output.r = 0xff;
|
|
//output.g = 0; //implied
|
|
}
|
|
else if(biome is biome2) {
|
|
//output.r = 0; //implied
|
|
output.g = 0xff;
|
|
}
|
|
}
|
|
|
|
img.set(x,y, output);
|
|
}
|
|
}
|
|
|
|
if(img !is output)
|
|
output = img;
|
|
}
|
|
|
|
class PlanetSurface : Serializable {
|
|
vec2u size;
|
|
|
|
//Data grid
|
|
array<uint8> biomes;
|
|
array<uint8> flags;
|
|
array<SurfaceBuilding@> tileBuildings;
|
|
const Biome@ baseBiome;
|
|
|
|
//Resources and pressures
|
|
double[] resources = double[](TR_COUNT, 0);
|
|
float[] saturates = float[](TR_COUNT, 0);
|
|
float[] pressures = float[](TR_COUNT, 0.f);
|
|
double totalResource = 0;
|
|
float totalSaturate = 0;
|
|
double totalPressure = 0.0;
|
|
|
|
//Improving tiles to usable status
|
|
vec2u nextReady;
|
|
double readyTimer = -1.0;
|
|
int Maintenance = 0;
|
|
uint usableTiles = 0;
|
|
uint citiesBuilt = 0;
|
|
uint civsBuilt = 0;
|
|
uint pressureCap = 0;
|
|
|
|
//Civilian building construction
|
|
array<SurfaceBuilding@> buildings;
|
|
SurfaceBuilding@ civConstructing;
|
|
|
|
PlanetSurface() {
|
|
}
|
|
|
|
uint get_dataSize() {
|
|
return size.width * size.height;
|
|
}
|
|
|
|
bool isValidPosition(const vec2i& pos) const {
|
|
return uint(pos.x) < size.width && uint(pos.y) < size.height;
|
|
}
|
|
|
|
bool isValidPosition(const vec2u& pos) const {
|
|
return pos.x < size.width && pos.y < size.height;
|
|
}
|
|
|
|
void clearState() {
|
|
for(uint i = 0, cnt = flags.length; i < cnt; ++i)
|
|
flags[i] = 0;
|
|
for(uint i = 0, cnt = flags.length; i < cnt; ++i)
|
|
@tileBuildings[i] = null;
|
|
buildings.length = 0;
|
|
}
|
|
|
|
void write(Message& msg) {
|
|
write(msg, false);
|
|
}
|
|
|
|
void write(Message& msg, bool delta) {
|
|
msg.writeSmall(size.width);
|
|
msg.writeSmall(size.height);
|
|
|
|
msg << baseBiome.id;
|
|
msg.writeSmall(Maintenance);
|
|
msg.writeSmall(pressureCap);
|
|
msg.writeSmall(civsBuilt);
|
|
|
|
uint maxBiomeID = getBiomeCount() - 1;
|
|
uint dsize = biomes.length;
|
|
uint8 prevFlags = 0, prevBiome = baseBiome.id;
|
|
for(uint i = 0; i < dsize; ++i) {
|
|
uint8 biome = biomes[i];
|
|
if(biome != prevBiome) {
|
|
msg.write0();
|
|
msg.writeLimited(biome,maxBiomeID);
|
|
prevBiome = biome;
|
|
}
|
|
else {
|
|
msg.write1();
|
|
}
|
|
|
|
uint8 _flags = flags[i];
|
|
if(_flags != prevFlags) {
|
|
msg.write0();
|
|
msg << _flags;
|
|
prevFlags = _flags;
|
|
}
|
|
else {
|
|
msg.write1();
|
|
}
|
|
}
|
|
|
|
uint bcnt = buildings.length;
|
|
msg.writeSmall(bcnt);
|
|
int civIndex = -1;
|
|
for(uint i = 0; i < bcnt; ++i) {
|
|
SurfaceBuilding@ bldg = buildings[i];
|
|
if(bldg is civConstructing)
|
|
civIndex = int(i);
|
|
if(delta) {
|
|
msg.writeBit(bldg.delta);
|
|
if(!bldg.delta)
|
|
continue;
|
|
bldg.delta = false;
|
|
}
|
|
bldg.write(msg);
|
|
}
|
|
|
|
if(civIndex > 0) {
|
|
msg.write1();
|
|
msg.writeSmall(uint(civIndex));
|
|
}
|
|
else {
|
|
msg.write0();
|
|
}
|
|
|
|
for(uint i = 0; i < TR_COUNT; ++i) {
|
|
if(resources[i] != 0) {
|
|
msg.write1();
|
|
msg << float(resources[i]);
|
|
}
|
|
else {
|
|
msg.write0();
|
|
}
|
|
|
|
if(pressures[i] != 0) {
|
|
msg.write1();
|
|
msg << pressures[i];
|
|
msg << saturates[i];
|
|
}
|
|
else {
|
|
msg.write0();
|
|
}
|
|
}
|
|
}
|
|
|
|
void read(Message& msg) {
|
|
read(msg, false);
|
|
}
|
|
|
|
bool read(Message& msg, bool delta) {
|
|
bool surfaceDelta = false;
|
|
size.width = msg.readSmall();
|
|
size.height = msg.readSmall();
|
|
|
|
uint8 baseId = 0;
|
|
msg >> baseId;
|
|
@baseBiome = ::getBiome(baseId);
|
|
Maintenance = msg.readSmall();
|
|
pressureCap = msg.readSmall();
|
|
civsBuilt = msg.readSmall();
|
|
|
|
uint maxBiomeID = getBiomeCount() - 1;
|
|
|
|
uint dsize = dataSize;
|
|
if(biomes.length != dsize)
|
|
surfaceDelta = true;
|
|
biomes.length = dsize;
|
|
flags.length = dsize;
|
|
tileBuildings.length = dsize;
|
|
|
|
uint8 prevFlags = 0, prevBiome = baseId;
|
|
for(uint i = 0; i < dsize; ++i) {
|
|
if(!msg.readBit())
|
|
prevBiome = msg.readLimited(maxBiomeID);
|
|
if(!surfaceDelta && prevBiome != biomes[i])
|
|
surfaceDelta = true;
|
|
biomes[i] = prevBiome;
|
|
|
|
if(!msg.readBit())
|
|
msg >> prevFlags;
|
|
flags[i] = prevFlags;
|
|
|
|
@tileBuildings[i] = null;
|
|
}
|
|
|
|
uint bcnt = msg.readSmall();
|
|
buildings.length = bcnt;
|
|
|
|
for(uint i = 0; i < bcnt; ++i) {
|
|
if(buildings[i] is null)
|
|
@buildings[i] = SurfaceBuilding();
|
|
|
|
SurfaceBuilding@ bld = buildings[i];
|
|
if(delta && !msg.readBit())
|
|
continue;
|
|
|
|
bld.read(msg);
|
|
|
|
vec2u pos = bld.position;
|
|
vec2u center = bld.type.getCenter();
|
|
|
|
for(uint x = 0; x < bld.type.size.x; ++x) {
|
|
for(uint y = 0; y < bld.type.size.y; ++y) {
|
|
vec2u rpos = (pos - center) + vec2u(x, y);
|
|
uint index = rpos.y * size.width + rpos.x;
|
|
@tileBuildings[index] = bld;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(msg.readBit()) {
|
|
uint civIndex = msg.readSmall();
|
|
if(civIndex < buildings.length)
|
|
@civConstructing = buildings[civIndex];
|
|
}
|
|
else {
|
|
@civConstructing = null;
|
|
}
|
|
|
|
totalPressure = 0;
|
|
totalSaturate = 0;
|
|
totalResource = 0;
|
|
|
|
for(uint i = 0; i < TR_COUNT; ++i) {
|
|
if(msg.readBit()) {
|
|
float resource = 0;
|
|
msg >> resource;
|
|
resources[i] = resource;
|
|
totalResource += resource;
|
|
}
|
|
else {
|
|
resources[i] = 0;
|
|
}
|
|
|
|
if(msg.readBit()) {
|
|
msg >> pressures[i];
|
|
totalPressure += pressures[i];
|
|
|
|
msg >> saturates[i];
|
|
totalSaturate += saturates[i];
|
|
}
|
|
else {
|
|
pressures[i] = 0;
|
|
}
|
|
}
|
|
|
|
return surfaceDelta;
|
|
}
|
|
|
|
uint getIndex(int x, int y) {
|
|
return y * size.width + x;
|
|
}
|
|
|
|
const Biome@ getBiome(int x, int y) {
|
|
uint index = y * size.width + x;
|
|
if(index >= biomes.length)
|
|
return null;
|
|
return ::getBiome(biomes[index]);
|
|
}
|
|
|
|
uint8 getFlags(int x, int y) {
|
|
uint index = y * size.width + x;
|
|
if(index >= flags.length)
|
|
return 0;
|
|
return flags[index];
|
|
}
|
|
|
|
bool checkFlags(int x, int y, uint8 f) {
|
|
uint index = y * size.width + x;
|
|
if(index >= flags.length)
|
|
return false;
|
|
return (flags[index] & f) == f;
|
|
}
|
|
|
|
void setFlags(int x, int y, uint8 f) {
|
|
uint index = y * size.width + x;
|
|
if(index >= flags.length)
|
|
return;
|
|
flags[index] = f;
|
|
}
|
|
|
|
void addFlags(int x, int y, uint8 f) {
|
|
uint index = y * size.width + x;
|
|
if(index >= flags.length)
|
|
return;
|
|
flags[index] |= f;
|
|
}
|
|
|
|
void removeFlags(int x, int y, uint8 f) {
|
|
uint index = y * size.width + x;
|
|
if(index >= flags.length)
|
|
return;
|
|
flags[index] &= ~f;
|
|
}
|
|
|
|
SurfaceBuilding@ getBuilding(int x, int y) {
|
|
uint index = y * size.width + x;
|
|
if(index >= tileBuildings.length)
|
|
return null;
|
|
return tileBuildings[index];
|
|
}
|
|
|
|
float getBuildingBuildWeight(int x, int y) {
|
|
uint index = y * size.width + x;
|
|
if(index >= tileBuildings.length)
|
|
return 0;
|
|
SurfaceBuilding@ bld = tileBuildings[index];
|
|
if(bld is null)
|
|
return 0;
|
|
return bld.type.hubWeight;
|
|
}
|
|
|
|
void setBuilding(int x, int y, SurfaceBuilding@ bld) {
|
|
uint index = y * size.width + x;
|
|
if(index >= tileBuildings.length)
|
|
return;
|
|
@tileBuildings[index] = bld;
|
|
}
|
|
};
|