Skip to content
Permalink
Browse files

fix /reloadcegs

  • Loading branch information...
rtri
rtri committed Aug 17, 2019
1 parent a4e7262 commit 3283443cf25f21273903b10610c51f5fa955065f
@@ -71,29 +71,43 @@ CColorMap* CColorMap::LoadFromRawVector(const float* data, size_t size)
if (numColorMaps >= (colorMapsCache.size() - 1))
return &colorMapsCache[colorMapsCache.size() - 1];

colorMapsCache[numColorMaps] = {data, size};
CColorMap cm{data, size};

// slowish, but gets invoked by /reloadcegs via LoadFromDefString callback
// need to do a cache lookup or numColorMaps quickly spirals out of control
for (size_t i = 0; i < numColorMaps; i++) {
if (colorMapsCache[i].map.size() != cm.map.size())
continue;

if (memcmp(colorMapsCache[i].map.data(), cm.map.data(), cm.map.size()) == 0)
return &colorMapsCache[i];
}

colorMapsCache[numColorMaps] = std::move(cm);

return &colorMapsCache[numColorMaps++];
}


CColorMap* CColorMap::LoadFromDefString(const std::string& defString)
{
std::stringstream stream;
std::array<float, 4096> vec;

stream << defString;
size_t idx = 0;

char* pos = const_cast<char*>(defString.c_str());
char* end = nullptr;

size_t count = 0;
float value = 0.0f;
vec.fill(0.0f);

while ((count < vec.size()) && (stream >> value)) {
vec[count++] = value;
for (float val; (val = std::strtof(pos, &end), pos != end && idx < vec.size()); pos = end) {
vec[idx++] = val;
}

if (count == 0)
if (idx == 0)
return (CColorMap::LoadFromBitmapFile("bitmaps\\" + defString));

return (CColorMap::LoadFromRawVector(vec.data(), count));
return (CColorMap::LoadFromRawVector(vec.data(), idx));
}


@@ -708,51 +708,58 @@ void CCustomExplosionGenerator::ParseExplosionCode(
string& code
) {
const std::string content = script.substr(0, script.find(';', 0));
const bool isFloat = memberInfo.type == SExpGenSpawnableMemberInfo::TYPE_FLOAT;

const bool isFloat = (memberInfo.type == SExpGenSpawnableMemberInfo::TYPE_FLOAT);
const bool isInt = (memberInfo.type == SExpGenSpawnableMemberInfo::TYPE_INT );

if (content == "dir") {
// dir keyword; type has to be float3
if (memberInfo.length < 3 || !isFloat)
if (!isFloat || memberInfo.length < 3)
throw content_error("[CCEG::ParseExplosionCode] incorrect use of \"dir\" (" + script + ")");

code += OP_DIR;
std::uint16_t ofs = memberInfo.offset;
code.append((char*) &ofs, (char*) &ofs + sizeof(ofs));
const std::uint16_t ofs = memberInfo.offset;

code.append(1, OP_DIR);
code.append((char*) &ofs, (char*) &ofs + sizeof(ofs));
return;
}

//Arrays (float3 or float4)
// arrays (float3 or float4)
if (memberInfo.length > 1) {
string::size_type start = 0;
SExpGenSpawnableMemberInfo subInfo = memberInfo;
subInfo.length = 1;

for (unsigned int i = 0; i < memberInfo.length && start < script.length(); ++i) {
string::size_type subEnd = script.find(',', start + 1);
const string::size_type subEnd = script.find(',', start + 1);

ParseExplosionCode(psi, script.substr(start, subEnd - start), subInfo, code);

start = subEnd + 1;
subInfo.offset += subInfo.size;
}

return;
}

//Textures, Colormaps, etc.
// textures, colormaps, etc.
if (memberInfo.type == SExpGenSpawnableMemberInfo::TYPE_PTR) {
// Memory is managed by whomever this callback belongs to
void* ptr = memberInfo.ptrCallback(content);
code += OP_LOADP;

code.append(1, OP_LOADP);
code.append((char*)(&ptr), ((char*)(&ptr)) + sizeof(void*));
code += OP_STOREP;
std::uint16_t ofs = memberInfo.offset;
code.append((char*)&ofs, (char*)&ofs + sizeof(ofs));

const std::uint16_t ofs = memberInfo.offset;

code.append(1, OP_STOREP);
code.append((char*)&ofs, (char*)&ofs + sizeof(ofs));
return;
}


//Floats or Ints
assert(isFloat || memberInfo.type == SExpGenSpawnableMemberInfo::TYPE_INT);
// Floats or Ints
assert(isFloat || isInt);

if (isFloat) {
switch (memberInfo.size) {
@@ -767,8 +774,7 @@ void CCustomExplosionGenerator::ParseExplosionCode(
}

// parse the code
int p = 0;
while (p < script.length()) {
for (size_t p = 0, len = script.length(); p < len; ) {
char opcode = OP_END;
char c = script[p++];

@@ -791,7 +797,7 @@ void CCustomExplosionGenerator::ParseExplosionCode(
else if (c == 'q') { opcode = OP_POWBUFF; useInt = true; }
else if (isdigit(c) || c == '.' || c == '-') { opcode = OP_ADD; p--; }
else {
LOG_L(L_WARNING, "[CCEG::%s] unknown op-code \"%c\" in \"%s\" at index %d", __func__, c, script.c_str(), p);
LOG_L(L_WARNING, "[CCEG::%s] unknown op-code \"%c\" in \"%s\" at index " _STPF_ "", __func__, c, script.c_str(), p);
continue;
}

@@ -802,28 +808,27 @@ void CCustomExplosionGenerator::ParseExplosionCode(
char* endp = nullptr;

if (!useInt) {
// strtod&co expect C-style strings with NULLs,
// c_str() is guaranteed to be NULL-terminated
// (whether .data() == .c_str() depends on the
// implementation of std::string)
const float v = (float)strtod(&script.c_str()[p], &endp);

p += (endp - &script.c_str()[p]);
code += opcode;
const float v = (float)strtod(&script[p], &endp);

p += (endp - &script[p]);

code.append(1, opcode);
code.append((char*) &v, ((char*) &v) + sizeof(v));
} else {
const int v = std::max(0, std::min(16, (int)strtol(&script.c_str()[p], &endp, 10)));
const int v = Clamp(int(strtol(&script[p], &endp, 10)), 0, 16);

p += (endp - &script.c_str()[p]);
code += opcode;
code.append((char*) &v, ((char*) &v) + + sizeof(v));
p += (endp - &script[p]);

code.append(1, opcode);
code.append((char*) &v, ((char*) &v) + sizeof(v));
}
}

// store the final value
const std::uint16_t ofs = memberInfo.offset;

code.push_back(isFloat ? OP_STOREF : OP_STOREI);
code.push_back(memberInfo.size);
std::uint16_t ofs = memberInfo.offset;
code.append((char*)&ofs, (char*)&ofs + sizeof(ofs));
}

@@ -139,26 +139,14 @@ class CCustomExplosionGenerator: public IExplosionGenerator
{
protected:
struct ProjectileSpawnInfo {
ProjectileSpawnInfo()
: spawnableID(0)
, count(0)
, flags(0)
{}
ProjectileSpawnInfo(const ProjectileSpawnInfo& psi)
: spawnableID(psi.spawnableID)
, code(psi.code)
, count(psi.count)
, flags(psi.flags)
{}

unsigned int spawnableID;
unsigned int spawnableID = 0;

/// number of projectiles spawned of this type
unsigned int count = 0;
unsigned int flags = 0;

/// parsed explosion script code
std::vector<char> code;

/// number of projectiles spawned of this type
unsigned int count;
unsigned int flags;
};

struct ExpGenParams {

0 comments on commit 3283443

Please sign in to comment.
You can’t perform that action at this time.