Files
starruler-linux/scripts/shared/planets/PlanetSurface.as
T
2018-07-17 14:15:37 +02:00

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;
}
};