mirror of
https://github.com/openmoh/openmohaa.git
synced 2025-05-02 15:47:58 +03:00
399 lines
10 KiB
C++
399 lines
10 KiB
C++
/*
|
|
===========================================================================
|
|
Copyright (C) 2023 the OpenMoHAA team
|
|
|
|
This file is part of OpenMoHAA source code.
|
|
|
|
OpenMoHAA source code is free software; you can redistribute it
|
|
and/or modify it under the terms of the GNU General Public License as
|
|
published by the Free Software Foundation; either version 2 of the License,
|
|
or (at your option) any later version.
|
|
|
|
OpenMoHAA source code is distributed in the hope that it will be
|
|
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with OpenMoHAA source code; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
===========================================================================
|
|
*/
|
|
|
|
#include "bg_voteoptions.h"
|
|
#include "../qcommon/script.h"
|
|
|
|
CLASS_DECLARATION(Class, VoteOptions, NULL) {
|
|
{NULL, NULL}
|
|
};
|
|
|
|
VoteOptionListItem::VoteOptionListItem()
|
|
: m_pNext(NULL)
|
|
{}
|
|
|
|
SingleVoteOption::SingleVoteOption()
|
|
: m_optionType(VOTE_NO_CHOICES)
|
|
, m_pListItem(NULL)
|
|
, m_pNext(NULL)
|
|
{}
|
|
|
|
SingleVoteOption::~SingleVoteOption()
|
|
{
|
|
VoteOptionListItem *item;
|
|
VoteOptionListItem *next;
|
|
|
|
for (item = m_pListItem; item; item = next) {
|
|
next = item->m_pNext;
|
|
delete item;
|
|
}
|
|
}
|
|
|
|
VoteOptions::VoteOptions()
|
|
{
|
|
m_pHeadOption = NULL;
|
|
}
|
|
|
|
VoteOptions::~VoteOptions()
|
|
{
|
|
ClearOptions();
|
|
}
|
|
|
|
void VoteOptions::ClearOptions()
|
|
{
|
|
SingleVoteOption *option;
|
|
SingleVoteOption *next;
|
|
|
|
for (option = m_pHeadOption; option; option = next) {
|
|
next = option->m_pNext;
|
|
delete option;
|
|
}
|
|
|
|
m_pHeadOption = NULL;
|
|
}
|
|
|
|
void VoteOptions::SetupVoteOptions(const char *configFileName)
|
|
{
|
|
char *buffer;
|
|
int compressedLength;
|
|
long length;
|
|
|
|
length = gi.FS_ReadFile(configFileName, (void**)&buffer, qtrue);
|
|
if (length == -1 || !length) {
|
|
Com_Printf("WARNING: Couldn't find voting options file: %s\n", configFileName);
|
|
return;
|
|
}
|
|
|
|
// compress the buffer before setting up
|
|
compressedLength = COM_Compress(buffer);
|
|
SetupVoteOptions(configFileName, compressedLength, buffer);
|
|
gi.FS_FreeFile(buffer);
|
|
}
|
|
|
|
void VoteOptions::SetupVoteOptions(const char *configFileName, int length, const char *buffer)
|
|
{
|
|
if (length >= MAX_VOTEOPTIONS_BUFFER_LENGTH) {
|
|
Com_Error(
|
|
ERR_DROP,
|
|
"VoteOptions: Options file '%s' is too big. Max size is %i bytes\n",
|
|
configFileName,
|
|
MAX_VOTEOPTIONS_BUFFER_LENGTH
|
|
);
|
|
return;
|
|
}
|
|
|
|
m_sFileName = configFileName;
|
|
m_sBuffer = buffer;
|
|
|
|
ParseVoteOptions();
|
|
}
|
|
|
|
void VoteOptions::ParseVoteOptions()
|
|
{
|
|
SingleVoteOption *option;
|
|
SingleVoteOption *newOption;
|
|
VoteOptionListItem *listItem;
|
|
VoteOptionListItem *newListItem;
|
|
str token;
|
|
Script script;
|
|
|
|
ClearOptions();
|
|
script.LoadFile(m_sFileName.c_str(), m_sBuffer.length(), m_sBuffer.c_str());
|
|
|
|
option = m_pHeadOption;
|
|
|
|
while (script.TokenAvailable(true)) {
|
|
token = script.GetToken(true);
|
|
|
|
if (!str::icmp(token, "{")) {
|
|
Com_Error(
|
|
ERR_DROP,
|
|
"Vote Options %s: Found choices list without option header on line %d.\n",
|
|
m_sFileName.c_str(),
|
|
script.GetLineNumber()
|
|
);
|
|
return;
|
|
}
|
|
|
|
if (!str::icmp(token, "}")) {
|
|
Com_Error(
|
|
ERR_DROP,
|
|
"Vote Options %s: Illegal end of choices list without list being started on line %d.\n",
|
|
m_sFileName.c_str(),
|
|
script.GetLineNumber()
|
|
);
|
|
return;
|
|
}
|
|
|
|
if (!token.length()) {
|
|
Com_Error(
|
|
ERR_DROP,
|
|
"Vote Options %s: Empty option name on line %d.\n",
|
|
m_sFileName.c_str(),
|
|
script.GetLineNumber()
|
|
);
|
|
return;
|
|
}
|
|
|
|
newOption = new SingleVoteOption();
|
|
|
|
if (option) {
|
|
option->m_pNext = newOption;
|
|
} else {
|
|
m_pHeadOption = newOption;
|
|
}
|
|
option = newOption;
|
|
|
|
newOption->m_sOptionName = token;
|
|
|
|
if (!script.TokenAvailable(false)) {
|
|
Com_Error(
|
|
ERR_DROP,
|
|
"Vote Options %s: Option without a command specified on line %d.\n",
|
|
m_sFileName.c_str(),
|
|
script.GetLineNumber()
|
|
);
|
|
return;
|
|
}
|
|
|
|
newOption->m_sCommand = script.GetToken(false);
|
|
|
|
if (script.TokenAvailable(false)) {
|
|
token = script.GetToken(false);
|
|
|
|
if (!str::icmp(token, "nochoices")) {
|
|
newOption->m_optionType = VOTE_NO_CHOICES;
|
|
} else if (!str::icmp(token, "list")) {
|
|
newOption->m_optionType = VOTE_OPTION_LIST;
|
|
} else if (!str::icmp(token, "text")) {
|
|
newOption->m_optionType = VOTE_OPTION_TEXT;
|
|
} else if (!str::icmp(token, "integer")) {
|
|
newOption->m_optionType = VOTE_OPTION_INTEGER;
|
|
} else if (!str::icmp(token, "float")) {
|
|
newOption->m_optionType = VOTE_OPTION_FLOAT;
|
|
} else if (!str::icmp(token, "client")) {
|
|
newOption->m_optionType = VOTE_OPTION_CLIENT;
|
|
} else if (!str::icmp(token, "clientnotself")) {
|
|
newOption->m_optionType = VOTE_OPTION_CLIENT_NOT_SELF;
|
|
} else {
|
|
Com_Error(
|
|
ERR_DROP,
|
|
"Vote Options %s: Illegal option type '%s' specified on line %d.\n"
|
|
" Valid types are nochoices, list, text, & number.\n",
|
|
m_sFileName.c_str(),
|
|
token.c_str(),
|
|
script.GetLineNumber()
|
|
);
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (newOption->m_optionType == VOTE_OPTION_LIST) {
|
|
if (!script.TokenAvailable(true) || Q_stricmp(script.GetToken(true), "{")) {
|
|
Com_Error(
|
|
ERR_DROP,
|
|
"Vote Options %s: Missing '{'. No choices list specified for list option on line %d.\n",
|
|
m_sFileName.c_str(),
|
|
script.GetLineNumber()
|
|
);
|
|
return;
|
|
}
|
|
|
|
listItem = NULL;
|
|
|
|
while (script.TokenAvailable(true)) {
|
|
token = script.GetToken(true);
|
|
|
|
if (!str::icmp(token, "}")) {
|
|
break;
|
|
}
|
|
|
|
newListItem = new VoteOptionListItem();
|
|
|
|
if (listItem) {
|
|
listItem->m_pNext = newListItem;
|
|
} else {
|
|
newOption->m_pListItem = newListItem;
|
|
}
|
|
listItem = newListItem;
|
|
|
|
if (!script.TokenAvailable(false)) {
|
|
Com_Error(
|
|
ERR_DROP,
|
|
"Vote Options %s: List choice without vote string specified on line %d.\n",
|
|
m_sFileName.c_str(),
|
|
script.GetLineNumber()
|
|
);
|
|
return;
|
|
}
|
|
|
|
newListItem->m_sCommand = script.GetToken(false);
|
|
}
|
|
} else if (script.TokenAvailable(true)) {
|
|
token = script.GetToken(true);
|
|
|
|
if (!str::icmp(token, "{")) {
|
|
Com_Error(
|
|
ERR_DROP,
|
|
"Vote Options %s: Choices list specified for non-list option on line %d.\n",
|
|
m_sFileName.c_str(),
|
|
script.GetLineNumber()
|
|
);
|
|
return;
|
|
}
|
|
|
|
script.UnGetToken();
|
|
}
|
|
}
|
|
}
|
|
|
|
const char *VoteOptions::GetVoteOptionsFile(int *outLen) const
|
|
{
|
|
if (outLen) {
|
|
*outLen = m_sBuffer.length();
|
|
}
|
|
|
|
return m_sBuffer.c_str();
|
|
}
|
|
|
|
bool VoteOptions::GetVoteOptionsMain(int index, str *outOptionCommand, voteoptiontype_t *outOptionType) const
|
|
{
|
|
SingleVoteOption *option;
|
|
int optionIndex;
|
|
|
|
if (index < 1) {
|
|
return false;
|
|
}
|
|
|
|
optionIndex = 1;
|
|
for (option = m_pHeadOption; optionIndex < index && option != NULL; option = option->m_pNext) {
|
|
optionIndex++;
|
|
}
|
|
|
|
if (!option) {
|
|
return false;
|
|
}
|
|
|
|
*outOptionCommand = option->m_sCommand;
|
|
*outOptionType = option->m_optionType;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool VoteOptions::GetVoteOptionSub(int index, int listIndex, str *outCommand) const
|
|
{
|
|
SingleVoteOption *option;
|
|
VoteOptionListItem *item;
|
|
int optionIndex;
|
|
int itemIndex;
|
|
|
|
if (index < 1 || listIndex < 1) {
|
|
return false;
|
|
}
|
|
|
|
optionIndex = 1;
|
|
for (option = m_pHeadOption; optionIndex < index && option != NULL; option = option->m_pNext) {
|
|
optionIndex++;
|
|
}
|
|
|
|
if (!option) {
|
|
return false;
|
|
}
|
|
|
|
if (option->m_optionType != VOTE_OPTION_LIST) {
|
|
return false;
|
|
}
|
|
|
|
itemIndex = 1;
|
|
for (item = option->m_pListItem; itemIndex < listIndex && option != NULL; item = item->m_pNext) {
|
|
itemIndex++;
|
|
}
|
|
|
|
if (!item) {
|
|
return false;
|
|
}
|
|
|
|
*outCommand = item->m_sCommand;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool VoteOptions::GetVoteOptionMainName(int index, str *outVoteName) const
|
|
{
|
|
SingleVoteOption *option;
|
|
int optionIndex;
|
|
|
|
if (index < 1) {
|
|
return false;
|
|
}
|
|
|
|
optionIndex = 1;
|
|
for (option = m_pHeadOption; optionIndex < index && option != NULL; option = option->m_pNext) {
|
|
optionIndex++;
|
|
}
|
|
|
|
if (!option) {
|
|
return false;
|
|
}
|
|
|
|
*outVoteName = option->m_sOptionName;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool VoteOptions::GetVoteOptionSubName(int index, int listIndex, str *outName) const
|
|
{
|
|
SingleVoteOption *option;
|
|
VoteOptionListItem *item;
|
|
int optionIndex;
|
|
int itemIndex;
|
|
|
|
if (index < 1 || listIndex < 1) {
|
|
return false;
|
|
}
|
|
|
|
optionIndex = 1;
|
|
for (option = m_pHeadOption; optionIndex < index && option != NULL; option = option->m_pNext) {
|
|
optionIndex++;
|
|
}
|
|
|
|
if (!option) {
|
|
return false;
|
|
}
|
|
|
|
if (option->m_optionType != VOTE_OPTION_LIST) {
|
|
return false;
|
|
}
|
|
|
|
itemIndex = 1;
|
|
for (item = option->m_pListItem; itemIndex < listIndex && option != NULL; item = item->m_pNext) {
|
|
itemIndex++;
|
|
}
|
|
|
|
if (!item) {
|
|
return false;
|
|
}
|
|
|
|
*outName = item->m_sItemName;
|
|
|
|
return true;
|
|
}
|