19 changes: 0 additions & 19 deletions src/multiopt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -327,25 +327,6 @@ bool multiShutdown(void)
return true;
}

// ////////////////////////////////////////////////////////////////////////////
// copy templates from one player to another.
static DROID_TEMPLATE *addTemplateToList(DROID_TEMPLATE *psNew, DROID_TEMPLATE **ppList)
{
DROID_TEMPLATE *psTempl = new DROID_TEMPLATE(*psNew);

psTempl->psNext = *ppList;
*ppList = psTempl;

return psTempl;
}

// ////////////////////////////////////////////////////////////////////////////
// copy templates from one player to another.
DROID_TEMPLATE *addTemplate(UDWORD player, DROID_TEMPLATE *psNew)
{
return addTemplateToList(psNew, &apsDroidTemplates[player]);
}

// ////////////////////////////////////////////////////////////////////////////
static bool gameInit(void)
{
Expand Down
26 changes: 7 additions & 19 deletions src/multiplay.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -404,38 +404,26 @@ FEATURE *IdToFeature(UDWORD id, UDWORD player)

DROID_TEMPLATE *IdToTemplate(UDWORD tempId, UDWORD player)
{
DROID_TEMPLATE *psTempl = NULL;
UDWORD i;

// Check if we know which player this is from, in that case, assume it is a player template
// FIXME: nuke the ANYPLAYER hack
if (player != ANYPLAYER && player < MAX_PLAYERS)
{
for (psTempl = apsDroidTemplates[player]; psTempl && (psTempl->multiPlayerID != tempId); psTempl = psTempl->psNext)
{} // follow templates

if (psTempl)
if (droidTemplates[player].count(tempId) > 0)
{
return psTempl;
}
else
{
return NULL;
return droidTemplates[player][tempId];
}
return NULL;
}

// It could be a AI template...or that of another player
for (i = 0; i < MAX_PLAYERS; i++)
for (int i = 0; i < MAX_PLAYERS; i++)
{
for (psTempl = apsDroidTemplates[i]; psTempl && psTempl->multiPlayerID != tempId; psTempl = psTempl->psNext)
{} // follow templates

if (psTempl)
if (droidTemplates[i].count(tempId) > 0)
{
debug(LOG_NEVER, "Found template ID %d, for player %d, but found it in player's %d list?", tempId, player, i);
return psTempl;
return droidTemplates[i][tempId];
}
}

// no error, since it is possible that we don't have this template defined yet.
return NULL;
}
Expand Down
1 change: 0 additions & 1 deletion src/multiplay.h
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,6 @@ extern bool joinGame(const char *host, uint32_t port);
extern void playerResponding(void);
extern bool multiGameInit(void);
extern bool multiGameShutdown(void);
DROID_TEMPLATE *addTemplate(UDWORD player, DROID_TEMPLATE *psNew);

// syncing.
extern bool sendScoreCheck(void); //score check only(frontend)
Expand Down
2 changes: 1 addition & 1 deletion src/multistruct.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,7 @@ void recvStructureInfo(NETQUEUE queue)
NETuint8_t(&pT->asWeaps[i]);
}
pT->droidType = (DROID_TYPE)droidType;
pT = addTemplate(player, pT);
pT = copyTemplate(player, pT);
}
NETend();

Expand Down
26 changes: 10 additions & 16 deletions src/qtscriptfuncs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1340,16 +1340,11 @@ static QScriptValue js_enumGateways(QScriptContext *, QScriptEngine *engine)
static QScriptValue js_enumTemplates(QScriptContext *context, QScriptEngine *engine)
{
int player = context->argument(0).toInt32();
QScriptValue result = engine->newArray(droidTemplates[player].size());
int count = 0;
for (DROID_TEMPLATE *psCurr = apsDroidTemplates[player]; psCurr != NULL; psCurr = psCurr->psNext)
for (auto &keyvaluepair : droidTemplates[player])
{
count++;
}
QScriptValue result = engine->newArray(count);
count = 0;
for (DROID_TEMPLATE *psCurr = apsDroidTemplates[player]; psCurr != NULL; psCurr = psCurr->psNext)
{
result.setProperty(count, convTemplate(psCurr, engine));
result.setProperty(count, convTemplate(keyvaluepair.second, engine));
count++;
}
return result;
Expand Down Expand Up @@ -1902,8 +1897,7 @@ static QScriptValue js_buildDroid(QScriptContext *context, QScriptEngine *engine
// Add to list
debug(LOG_SCRIPT, "adding template %s for player %d", getName(psTemplate), player);
psTemplate->multiPlayerID = generateNewObjectId();
psTemplate->psNext = apsDroidTemplates[player];
apsDroidTemplates[player] = psTemplate;
addTemplate(player, psTemplate);
if (!structSetManufacture(psStruct, psTemplate, ModeQueue))
{
debug(LOG_ERROR, "Could not produce template %s in %s", getName(psTemplate), objInfo(psStruct));
Expand Down Expand Up @@ -2970,10 +2964,10 @@ static QScriptValue js_setDesign(QScriptContext *context, QScriptEngine *engine)
allowDesign = context->argument(0).toBool();
// Switch on or off future templates
// FIXME: This dual data structure for templates is just plain insane.
for (psCurr = apsDroidTemplates[selectedPlayer]; psCurr != NULL; psCurr = psCurr->psNext)
for (auto &keyvaluepair : droidTemplates[selectedPlayer])
{
bool researched = researchedTemplate(psCurr, selectedPlayer);
psCurr->enabled = (researched || allowDesign);
bool researched = researchedTemplate(keyvaluepair.second, selectedPlayer);
keyvaluepair.second->enabled = (researched || allowDesign);
}
for (std::list<DROID_TEMPLATE>::iterator i = localTemplates.begin(); i != localTemplates.end(); ++i)
{
Expand All @@ -2991,11 +2985,11 @@ static QScriptValue js_enableTemplate(QScriptContext *context, QScriptEngine *en
QString templateName = context->argument(0).toString();
bool found = false;
// FIXME: This dual data structure for templates is just plain insane.
for (psCurr = apsDroidTemplates[selectedPlayer]; psCurr != NULL; psCurr = psCurr->psNext)
for (auto &keyvaluepair : droidTemplates[selectedPlayer])
{
if (templateName.compare(psCurr->id) == 0)
if (templateName.compare(keyvaluepair.second->id) == 0)
{
psCurr->enabled = true;
keyvaluepair.second->enabled = true;
found = true;
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/research.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1037,7 +1037,6 @@ RESEARCH *getResearch(const char *pName)
static void replaceComponent(COMPONENT_STATS *pNewComponent, COMPONENT_STATS *pOldComponent,
UBYTE player)
{
DROID_TEMPLATE *psTemplates;
COMPONENT_TYPE oldType = pOldComponent->compType;
int oldCompInc = pOldComponent->index;
COMPONENT_TYPE newType = pNewComponent->compType;
Expand All @@ -1054,8 +1053,9 @@ static void replaceComponent(COMPONENT_STATS *pNewComponent, COMPONENT_STATS *pO
replaceDroidComponent(apsLimboDroids[player], oldType, oldCompInc, newCompInc);

//check thru the templates
for (psTemplates = apsDroidTemplates[player]; psTemplates != NULL; psTemplates = psTemplates->psNext)
for (auto &keyvaluepair : droidTemplates[player])
{
DROID_TEMPLATE *psTemplates = keyvaluepair.second;
switch (oldType)
{
case COMP_BODY:
Expand Down
72 changes: 9 additions & 63 deletions src/scriptfuncs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2312,7 +2312,6 @@ bool scrGetStructure(void)
bool scrGetTemplate(void)
{
SDWORD player;
DROID_TEMPLATE *psTemplate;
bool found;
INTERP_VAL sVal;
UDWORD i;
Expand All @@ -2331,9 +2330,10 @@ bool scrGetTemplate(void)

//search the players' list of templates to see if one exists
found = false;
for (psTemplate = apsDroidTemplates[player]; psTemplate != NULL; psTemplate =
psTemplate->psNext)
for (auto &keyvaluepair : droidTemplates[player])
{
DROID_TEMPLATE *psTemplate = keyvaluepair.second;

switch ((unsigned)sVal.type) // Unsigned cast to suppress compiler warnings due to enum abuse.
{
case ST_BODY:
Expand Down Expand Up @@ -2396,10 +2396,9 @@ bool scrGetTemplate(void)
//make sure pass NULL back if not got one
if (!found)
{
psTemplate = NULL;
scrFunctionResult.v.oval = NULL;
}

scrFunctionResult.v.oval = psTemplate;
if (!stackPushResult((INTERP_TYPE)ST_TEMPLATE, &scrFunctionResult))
{
return false;
Expand Down Expand Up @@ -6033,56 +6032,9 @@ bool scrIsVtol(void)
return true;
}

// Fix the tutorial's template list(s).
// DO NOT MODIFY THIS WITHOUT KNOWING WHAT YOU ARE DOING. You will break the tutorial!
// In short, we want to design a ViperLtMGWheels, but it is already available to make, so we must delete it.
// no-op
bool scrTutorialTemplates(void)
{
#if 0
DROID_TEMPLATE *psCurr, *psPrev;

// find ViperLtMGWheels
char const *pName = getDroidResourceName("ViperLtMGWheels");

for (psCurr = apsDroidTemplates[selectedPlayer], psPrev = NULL; psCurr != NULL; psCurr = psCurr->psNext)
{
if (psCurr->name.compare(pName) == 0)
{
if (psPrev)
{
psPrev->psNext = psCurr->psNext;
}
else
{
apsDroidTemplates[selectedPlayer] = psCurr->psNext;
}
break;
}
psPrev = psCurr;
}

// Delete the template in *both* lists!
if (psCurr)
{
for (std::list<DROID_TEMPLATE>::iterator i = localTemplates.begin(); i != localTemplates.end(); ++i)
{
DROID_TEMPLATE *dropTemplate = &*i;
if (psCurr->multiPlayerID == dropTemplate->multiPlayerID)
{
free(dropTemplate->pName);
localTemplates.erase(i);
break;
}
}
delete psCurr;
}
else
{
debug(LOG_FATAL, "tutorial template setup failed");
abort();
return false;
}
#endif
return true;
}

Expand Down Expand Up @@ -10246,10 +10198,7 @@ bool scrAssembleWeaponTemplate(void)
{
// set template id
pNewTemplate->multiPlayerID = generateNewObjectId();

// add template to player template list
pNewTemplate->psNext = apsDroidTemplates[player];
apsDroidTemplates[player] = pNewTemplate; //apsTemplateList?
addTemplate(player, pNewTemplate);
}
else
{
Expand All @@ -10275,14 +10224,11 @@ bool scrAssembleWeaponTemplate(void)
/* Checks if template already exists, returns it if yes */
static DROID_TEMPLATE *scrCheckTemplateExists(SDWORD player, DROID_TEMPLATE *psTempl)
{
DROID_TEMPLATE *psCurrent;
bool equal;

for (psCurrent = apsDroidTemplates[player]; psCurrent != NULL; psCurrent = psCurrent->psNext)
for (auto &keyvaluepair : droidTemplates[player])
{
DROID_TEMPLATE *psCurrent = keyvaluepair.second;
unsigned int weaponSlot;

equal = true;
bool equal = true;

// compare components
for (int componentType = 0; componentType < ARRAY_SIZE(psTempl->asParts); ++componentType)
Expand Down
87 changes: 50 additions & 37 deletions src/template.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,7 @@
#include "main.h"

// Template storage
DROID_TEMPLATE *apsDroidTemplates[MAX_PLAYERS];

std::map<int, DROID_TEMPLATE *> droidTemplates[MAX_PLAYERS];

bool allowDesign = true;
bool includeRedundantDesigns = false;
Expand Down Expand Up @@ -193,9 +192,10 @@ bool initTemplates()
debug(LOG_ERROR, "Invalid template %d / %s from stored templates", i, list[i].toUtf8().constData());
continue;
}
DROID_TEMPLATE *psDestTemplate = apsDroidTemplates[selectedPlayer];
while (psDestTemplate != NULL)
DROID_TEMPLATE *psDestTemplate = NULL;
for (auto &keyvaluepair : droidTemplates[selectedPlayer])
{
psDestTemplate = keyvaluepair.second;
// Check if template is identical to a loaded template
if (psDestTemplate->droidType == design.droidType
&& psDestTemplate->name.compare(design.name) == 0
Expand All @@ -213,7 +213,7 @@ bool initTemplates()
{
break;
}
psDestTemplate = psDestTemplate->psNext;
psDestTemplate = NULL;
}
if (psDestTemplate)
{
Expand All @@ -222,7 +222,7 @@ bool initTemplates()
continue; // next!
}
design.enabled = allowDesign;
addTemplate(selectedPlayer, &design);
copyTemplate(selectedPlayer, &design);
localTemplates.push_back(design);
ini.endGroup();
}
Expand All @@ -238,8 +238,9 @@ bool storeTemplates()
debug(LOG_ERROR, "Could not open %s", ini.fileName().toUtf8().constData());
return false;
}
for (DROID_TEMPLATE *psCurr = apsDroidTemplates[selectedPlayer]; psCurr != NULL; psCurr = psCurr->psNext)
for (auto &keyvaluepair : droidTemplates[selectedPlayer])
{
DROID_TEMPLATE *psCurr = keyvaluepair.second;
if (!psCurr->stored)
{
continue; // not stored
Expand Down Expand Up @@ -302,7 +303,6 @@ DROID_TEMPLATE::DROID_TEMPLATE() // This constructor replaces a memset in scrAs
//, asWeaps
, droidType(DROID_WEAPON)
, multiPlayerID(0)
, psNext(NULL)
, prefab(false)
, stored(false)
, enabled(false)
Expand Down Expand Up @@ -336,9 +336,9 @@ bool loadDroidTemplates(const char *filename)
if (NetPlay.players[i].allocated && available)
{
design.prefab = false;
addTemplate(i, &design);
copyTemplate(i, &design);

// This sets up the UI templates for display purposes ONLY--we still only use apsDroidTemplates for making them.
// This sets up the UI templates for display purposes ONLY--we still only use droidTemplates for making them.
// FIXME: Why are we doing this here, and not on demand ?
// Only add unique designs to the UI list (Note, perhaps better to use std::map instead?)
std::list<DROID_TEMPLATE>::iterator it;
Expand All @@ -360,7 +360,7 @@ bool loadDroidTemplates(const char *filename)
else if (!NetPlay.players[i].allocated) // AI template
{
design.prefab = true; // prefabricated templates referenced from VLOs
addTemplate(i, &design);
copyTemplate(i, &design);
}
}
debug(LOG_NEVER, "Droid template found, Name: %s, MP ID: %d, ref: %u, ID: %s, prefab: %s, type:%d (loading)",
Expand All @@ -370,24 +370,35 @@ bool loadDroidTemplates(const char *filename)
return true;
}

//free the storage for the droid templates
bool droidTemplateShutDown(void)
DROID_TEMPLATE *copyTemplate(int player, DROID_TEMPLATE *psTemplate)
{
DROID_TEMPLATE *dup = new DROID_TEMPLATE(*psTemplate);
droidTemplates[player][psTemplate->multiPlayerID] = dup;
return dup;
}

void addTemplate(int player, DROID_TEMPLATE *psTemplate)
{
unsigned int player;
DROID_TEMPLATE *pTemplate, *pNext;
droidTemplates[player][psTemplate->multiPlayerID] = psTemplate;
}

for (player = 0; player < MAX_PLAYERS; player++)
void clearTemplates(int player)
{
for (auto &keyvaluepair : droidTemplates[player])
{
for (pTemplate = apsDroidTemplates[player]; pTemplate != NULL; pTemplate = pNext)
{
pNext = pTemplate->psNext;
delete pTemplate;
}
apsDroidTemplates[player] = NULL;
delete keyvaluepair.second;
}
droidTemplates[player].clear();
}

//free the storage for the droid templates
bool droidTemplateShutDown()
{
for (int player = 0; player < MAX_PLAYERS; player++)
{
clearTemplates(player);
}
localTemplates.clear();

return true;
}

Expand All @@ -401,11 +412,11 @@ DROID_TEMPLATE *getTemplateFromTranslatedNameNoPlayer(char const *pName)
{
for (int i = 0; i < MAX_PLAYERS; i++)
{
for (DROID_TEMPLATE *psCurr = apsDroidTemplates[i]; psCurr != NULL; psCurr = psCurr->psNext)
for (auto &keyvaluepair : droidTemplates[i])
{
if (psCurr->id.compare(pName) == 0)
if (keyvaluepair.second->id.compare(pName) == 0)
{
return psCurr;
return keyvaluepair.second;
}
}
}
Expand All @@ -415,17 +426,11 @@ DROID_TEMPLATE *getTemplateFromTranslatedNameNoPlayer(char const *pName)
/*getTemplatefFromMultiPlayerID gets template for unique ID searching all lists */
DROID_TEMPLATE *getTemplateFromMultiPlayerID(UDWORD multiPlayerID)
{
UDWORD player;
DROID_TEMPLATE *pDroidDesign;

for (player = 0; player < MAX_PLAYERS; player++)
for (int player = 0; player < MAX_PLAYERS; player++)
{
for (pDroidDesign = apsDroidTemplates[player]; pDroidDesign != NULL; pDroidDesign = pDroidDesign->psNext)
if (droidTemplates[player].count(multiPlayerID) > 0)
{
if (pDroidDesign->multiPlayerID == multiPlayerID)
{
return pDroidDesign;
}
return droidTemplates[player][multiPlayerID];
}
}
return NULL;
Expand Down Expand Up @@ -500,8 +505,7 @@ void deleteTemplateFromProduction(DROID_TEMPLATE *psTemplate, unsigned player, Q
bool templateIsIDF(DROID_TEMPLATE *psTemplate)
{
//add Cyborgs
if (!(psTemplate->droidType == DROID_WEAPON || psTemplate->droidType == DROID_CYBORG ||
psTemplate->droidType == DROID_CYBORG_SUPER))
if (!(psTemplate->droidType == DROID_WEAPON || psTemplate->droidType == DROID_CYBORG || psTemplate->droidType == DROID_CYBORG_SUPER))
{
return false;
}
Expand All @@ -514,6 +518,15 @@ bool templateIsIDF(DROID_TEMPLATE *psTemplate)
return true;
}

void listTemplates()
{
for (auto &keyvaluepair : droidTemplates[selectedPlayer])
{
DROID_TEMPLATE *t = keyvaluepair.second;
debug(LOG_INFO, "template %s : %ld : %s : %s : %s", getName(t), (long)t->multiPlayerID, t->enabled ? "Enabled" : "Disabled", t->stored ? "Stored" : "Temporal", t->prefab ? "Prefab" : "Designed");
}
}

/*
fills the list with Templates that can be manufactured
in the Factory - based on size. There is a limit on how many can be manufactured
Expand Down
12 changes: 11 additions & 1 deletion src/template.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,21 @@
#include "droiddef.h"

//storage
extern DROID_TEMPLATE *apsDroidTemplates[MAX_PLAYERS];
extern std::map<int, DROID_TEMPLATE *> droidTemplates[MAX_PLAYERS];

extern bool allowDesign;
extern bool includeRedundantDesigns;


bool initTemplates();

/// Take ownership of template given by pointer.
void addTemplate(int player, DROID_TEMPLATE *psTemplate);

/// Make a duplicate of template given by pointer and store it. Then return pointer to copy.
DROID_TEMPLATE *copyTemplate(int player, DROID_TEMPLATE *psTemplate);

void clearTemplates(int player);
bool shutdownTemplates();
bool storeTemplates();

Expand All @@ -31,4 +39,6 @@ DROID_TEMPLATE *getTemplateFromMultiPlayerID(UDWORD multiPlayerID);
/// Have we researched the components of this template?
bool researchedTemplate(DROID_TEMPLATE *psCurr, int player, bool allowRedundant = false, bool verbose = false);

void listTemplates();

#endif // TEMPLATE_H