Skip to content

Commit

Permalink
Merge pull request #85 from crankycyclops/develop
Browse files Browse the repository at this point in the history
Release 0.91.0
  • Loading branch information
crankycyclops authored Mar 6, 2022
2 parents 95717f5 + 4b22f54 commit 6271704
Show file tree
Hide file tree
Showing 30 changed files with 739 additions and 61 deletions.
31 changes: 31 additions & 0 deletions .github/workflows/actions/test_trogdord/entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,34 @@ make -j2 trogdord
# Compile and run the unit tests
make -j2 test_trogdord
timeout -s SIGQUIT 10 sudo -u app ./test_trogdord

# This last set of unit tests is testing trogdord's handling of environment
# variable overrides, hence the super long string of variables :)
export TROGDORD_PORT="trogdord_port"
export TROGDORD_REUSE_ADDRESS="reuse_address"
export TROGDORD_SEND_TCP_KEEPALIVE="send_keepalive"
export TROGDORD_LISTEN_IPS="listen_ip"
export TROGDORD_LOGTO="logto"
export TROGDORD_INPUT_LISTENERS="input_listen"
export TROGDORD_OUTPUT_DRIVER="out_drive"
export TROGDORD_REDIS_HOST="redis_host"
export TROGDORD_REDIS_USERNAME="redis_username"
export TROGDORD_REDIS_PASSWORD="redis_password"
export TROGDORD_REDIS_PORT="redis_port"
export TROGDORD_REDIS_CONNECTION_TIMEOUT="redis_timeout"
export TROGDORD_REDIS_CONNECTION_RETRY_INTERVAL="redis_retry"
export TROGDORD_REDIS_OUTPUT_CHANNEL="redis_output"
export TROGDORD_REDIS_INPUT_CHANNEL="redis_input"
export TROGDORD_DEFINITIONS_PATH="definitions_path"
export TROGDORD_STATE_ENABLED="state_enable"
export TROGDORD_STATE_AUTORESTORE_ENABLED="autorestore_enable"
export TROGDORD_STATE_DUMP_SHUTDOWN_ENABLED="state_dump_shutdown"
export TROGDORD_STATE_CRASH_RECOVERY_ENABLED="state_crash"
export TROGDORD_STATE_FORMAT="state_format"
export TROGDORD_STATE_PATH="state_path"
export TROGDORD_STATE_MAX_DUMPS_PER_GAME="state_max_dumps"
export TROGDORD_EXTENSIONS_PATH="ext_path"
export TROGDORD_EXTENSIONS_LOAD="ext_load"

make -j2 test_trogdord_envvar
timeout -s SIGQUIT 10 sudo -E -u app ./test_trogdord_envvar
18 changes: 17 additions & 1 deletion Changelog.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,22 @@

# Change Log

## [0.91.0] - 2022-03-06

### Added

- trogdord can now authenticate with redis using an optional username and password
- trogdord can now also be configured via environment variables, which take precedence over trogdord.ini

### Changed

- The timer period (tick interval) can now be changed after the timer's started and can be configured via a game definition file
- trogdord now only listens on 127.0.0.1 or ::1 by default

### Fixed

- Added missing validation for ALLOCATE_RESOURCE AST operation

## [0.90.0] - 2022-01-31

### Added
Expand Down Expand Up @@ -62,4 +78,4 @@

## [0.50.2] - Before 2021-03-16

This was the version of the engine right before I started tracking versions and their changes. If you're really curious, you can look through the very lengthy commit log for more history.
This was the version of the engine right before I started tracking versions and their changes. If you're really curious, you can look through the very lengthy commit log for more history.
11 changes: 11 additions & 0 deletions src/core/data/game.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,17 @@
<game>


<!-- Configuration options related to how the game keeps time (optional) -->
<timer>

<!-- The number of milliseconds that should pass between ticks of the clock.
The default value is 1000ms, or 1 second. Valid values are any integer
greater than or equal to 1. -->
<period>1000</period>

</timer>


<!-- Entity class definitions are optional. If they are used, they must
precede the definitions of the rooms, creatures, and objects that use
them. Otherwise, an Entity class undefined error will be thrown during
Expand Down
7 changes: 7 additions & 0 deletions src/core/game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -630,6 +630,13 @@ namespace trogdor {

/***************************************************************************/

void Game::setTickInterval(size_t period) {

timer->setTickInterval(period);
}

/***************************************************************************/

unsigned long Game::getTime() const {

return timer->getTime();
Expand Down
1 change: 1 addition & 0 deletions src/core/include/trogdor/game.h
Original file line number Diff line number Diff line change
Expand Up @@ -1065,6 +1065,7 @@ namespace trogdor {
*/
void insertTimerJob(std::shared_ptr<TimerJob> j);
void removeTimerJob(std::shared_ptr<TimerJob> j);
void setTickInterval(size_t period);

/*
Gets the current game time (in seconds.) Note that I can't inline
Expand Down
6 changes: 5 additions & 1 deletion src/core/include/trogdor/parser/ast.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ namespace trogdor {
INSERT_INTO_INVENTORY = 14,
INSERT_INTO_PLACE = 15,
CONNECT_ROOMS = 16,
ALLOCATE_RESOURCE = 17
ALLOCATE_RESOURCE = 17,
SET_TIMER_PERIOD = 18
};

/**************************************************************************/
Expand Down Expand Up @@ -279,6 +280,9 @@ namespace trogdor {
case ALLOCATE_RESOURCE:
return "ALLOCATE_RESOURCE";

case SET_TIMER_PERIOD:
return "SET_TIMER_PERIOD";

default:
return "UNDEFINED";
}
Expand Down
13 changes: 13 additions & 0 deletions src/core/include/trogdor/parser/parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,19 @@ namespace trogdor {
// instantiate the game
std::shared_ptr<ASTNode> ast;

/*
Returns an AST subtree representing a SET_TIMER_PERIOD operation.
Input:
Timer's period (std::string)
Current line number in the source being parsed (int)
Output:
ASTOperationNode
*/
std::shared_ptr<ASTOperationNode> ASTSetTimerPeriod(std::string period,
int lineNumber = 0);

/*
Returns an AST subtree representing a defineDirection operation.
Expand Down
11 changes: 11 additions & 0 deletions src/core/include/trogdor/parser/parsers/xmlparser.h
Original file line number Diff line number Diff line change
Expand Up @@ -608,6 +608,17 @@ namespace trogdor {
*/
void parseTangibleResources(std::string entityName, int depth);

/*
Parses timer-related settings.
Input:
(none)
Output:
(none)
*/
void parseTimer();

/*
Parses the <game> section of the XML file. Throws an exception if
there's a parse error.
Expand Down
15 changes: 15 additions & 0 deletions src/core/include/trogdor/timer/timer.h
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,21 @@ namespace trogdor {
queue.remove(job);
mutex.unlock();
}

/*
Sets the period of time between ticks in milliseconds. If the tick
interval is less than the amount of time we sleep before checking
if the timer should advance, that sleep time will be set to this
value as well.
Setting this value once the timer has started is safe and will
simply result in the timer advancing slower or faster starting with
the next tick.
Input: Timer period (size_t)
Output: (none)
*/
void setTickInterval(size_t period);
};
}

Expand Down
2 changes: 1 addition & 1 deletion src/core/include/trogdor/version.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

// Current version of the core library
#define TROGDOR_VERSION_MAJOR 0
#define TROGDOR_VERSION_MINOR 90
#define TROGDOR_VERSION_MINOR 91
#define TROGDOR_VERSION_PATCH 0


Expand Down
30 changes: 30 additions & 0 deletions src/core/instantiator/instantiator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -797,6 +797,36 @@ namespace trogdor {
" (line " + std::to_string(operation->getLineNumber()) + ")" : ""));
}
};

/**********/

preOperations[ALLOCATE_RESOURCE] = [this](const std::shared_ptr<ASTOperationNode> &operation) {

assertValidASTArguments(operation, 3);
std::string amount = operation->getChildren()[2]->getValue();

if (!isValidDouble(amount)) {
throw ValidationException("resource allocation: amount must be a valid integer or floating point value");
}
};

/**********/

// Validates new period for the timer
preOperations[SET_TIMER_PERIOD] = [this](const std::shared_ptr<ASTOperationNode> &operation) {

assertValidASTArguments(operation, 1);
std::string value = operation->getChildren()[0]->getValue();

if (!isValidInteger(value)) {
throw ValidationException("timer period must be an integer greater than or equal to 1");
}

// TODO: I should write an isValidUnsignedInteger function that I can use instead
else if ('-' == value[0] || 0 == value.compare("0")) {
throw ValidationException("timer period must be an integer greater than or equal to 1");
}
};
}

/***************************************************************************/
Expand Down
21 changes: 17 additions & 4 deletions src/core/instantiator/instantiators/runtime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -603,10 +603,6 @@ namespace trogdor {
std::string resourceName = operation->getChildren()[1]->getValue();
std::string amount = operation->getChildren()[2]->getValue();

if (!isValidDouble(amount)) {
throw ValidationException("resource allocation: amount must be a valid integer or floating point value");
}

auto status = game->getResource(resourceName)->allocate(
game->getTangible(entityName),
stod(amount)
Expand Down Expand Up @@ -656,6 +652,23 @@ namespace trogdor {
);
}
});

/**********/

registerOperation(SET_TIMER_PERIOD, [this]
(const std::shared_ptr<ASTOperationNode> &operation) {

size_t period;
char *end; // required for strtoul/strtoull. Otherwise, not used.

#if SIZE_MAX == UINT64_MAX
period = strtoull(operation->getChildren()[0]->getValue().c_str(), &end, 10);
#else
period = strtoul(operation->getChildren()[0]->getValue().c_str(), &end, 10);
#endif

game->setTickInterval(period);
});
}

/***************************************************************************/
Expand Down
19 changes: 19 additions & 0 deletions src/core/parser/parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,25 @@ namespace trogdor {

/**************************************************************************/

std::shared_ptr<ASTOperationNode> Parser::ASTSetTimerPeriod(
std::string period, int lineNumber) {

auto operation = std::make_shared<ASTOperationNode>(
SET_TIMER_PERIOD,
lineNumber
);

operation->appendChild(std::make_shared<ASTNode>(
period,
AST_VALUE,
lineNumber
));

return operation;
}

/**************************************************************************/

std::shared_ptr<ASTOperationNode> Parser::ASTDefineDirection(
std::string direction, int lineNumber) {

Expand Down
33 changes: 32 additions & 1 deletion src/core/parser/parsers/xmlparser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,11 @@ namespace trogdor {
// parse the remaining sections
while (nextTag() && 1 == getDepth()) {

if (0 == getTagName().compare("classes")) {
if (0 == getTagName().compare("timer")) {
parseTimer();
}

else if (0 == getTagName().compare("classes")) {
parseClasses();
}

Expand Down Expand Up @@ -306,6 +310,33 @@ namespace trogdor {

/***************************************************************************/

void XMLParser::parseTimer() {

while (nextTag() && 2 == getDepth()) {

std::string tag = getTagName();

if (0 == getTagName().compare("period")) {

ast->appendChild(ASTSetTimerPeriod(
parseString(),
xmlTextReaderGetParserLineNumber(reader)
));

checkClosingTag("period");
}

else {
throw ParseException(std::string("invalid tag <") + tag
+ "> in <timer>");
}
}

checkClosingTag("timer");
}

/***************************************************************************/

void XMLParser::parseClasses() {

while (nextTag() && 2 == getDepth()) {
Expand Down
22 changes: 17 additions & 5 deletions src/core/timer/timer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,7 @@ namespace trogdor {
Timer::Timer(Game *gameRef, std::optional<size_t> interval):
game(gameRef), active(false), time(0), jobThread(nullptr), lastTickTime(0) {

tickInterval = std::chrono::milliseconds(interval ? *interval : TIMER_DEFAULT_TICK_MILLISECONDS);

jobThreadSleepTime =
std::chrono::milliseconds(THREAD_SLEEP_MILLISECONDS) > tickInterval ?
tickInterval : std::chrono::milliseconds(THREAD_SLEEP_MILLISECONDS);
setTickInterval(interval ? *interval : TIMER_DEFAULT_TICK_MILLISECONDS);
}

/******************************************************************************/
Expand Down Expand Up @@ -76,6 +72,22 @@ namespace trogdor {
}
}

/******************************************************************************/

void Timer::setTickInterval(size_t period) {

mutex.lock();

tickInterval = std::chrono::milliseconds(period);
jobThreadSleepTime = std::chrono::milliseconds(THREAD_SLEEP_MILLISECONDS);

if (tickInterval < jobThreadSleepTime) {
jobThreadSleepTime = tickInterval;
}

mutex.unlock();
}

/******************************************************************************/

std::shared_ptr<serial::Serializable> Timer::serialize() {
Expand Down
Loading

0 comments on commit 6271704

Please sign in to comment.