diff --git a/api/apisettings.php b/api/apisettings.php index 89f689f..319ceaf 100644 --- a/api/apisettings.php +++ b/api/apisettings.php @@ -65,6 +65,12 @@ $APIS = [ "id" => "/[0-9]+/" ] ], + "placeact" => [ + "load" => "placeact.php", + "vars" => [ + "id" => "/[0-9]+/" + ] + ], "getchat" => [ "load" => "getchat.php", "vars" => [ diff --git a/database.mwb b/database.mwb index 0751eb3..8a7db55 100644 Binary files a/database.mwb and b/database.mwb differ diff --git a/database/migrate_v1.sql b/database/migrate_v1.sql index 3dadfed..ad67210 100644 --- a/database/migrate_v1.sql +++ b/database/migrate_v1.sql @@ -147,4 +147,22 @@ CHANGE COLUMN `message` `message` TEXT NOT NULL ; ALTER TABLE `terranquest`.`items` ADD COLUMN `icon` VARCHAR(100) NULL DEFAULT NULL AFTER `weight`, -ADD COLUMN `color` VARCHAR(45) NULL DEFAULT NULL AFTER `icon`; \ No newline at end of file +ADD COLUMN `color` VARCHAR(45) NULL DEFAULT NULL AFTER `icon`; + +CREATE TABLE IF NOT EXISTS `terranquest`.`player_stats` ( + `accountid` VARCHAR(60) CHARACTER SET 'utf8' NOT NULL, + `claims` INT(11) NOT NULL DEFAULT 0, + `attacks` INT(11) NOT NULL DEFAULT 0, + `defends` INT(11) NOT NULL DEFAULT 0, + `scans` INT(11) NOT NULL DEFAULT 0, + `distancekm` DECIMAL(8,3) NOT NULL DEFAULT 0.0, + PRIMARY KEY (`accountid`), + UNIQUE INDEX `accountid_UNIQUE` (`accountid` ASC), + CONSTRAINT `fk_player_stats_players1` + FOREIGN KEY (`accountid`) + REFERENCES `terranquest`.`players` (`accountid`) + ON DELETE NO ACTION + ON UPDATE NO ACTION) +ENGINE = InnoDB +DEFAULT CHARACTER SET = utf8 +COLLATE = utf8_bin; \ No newline at end of file diff --git a/lib/Energy.lib.php b/lib/Energy.lib.php new file mode 100644 index 0000000..a5c243a --- /dev/null +++ b/lib/Energy.lib.php @@ -0,0 +1,53 @@ +energy = $energy; + $this->maxenergy = $max; + } + + public function getEnergy(): int { + return $this->energy; + } + + public function setEnergy(int $energy) { + if ($energy <= 0) { + $energy = 0; + } + if ($energy > $this->maxenergy) { + $energy = $this->maxenergy; + } + $this->energy = $energy; + } + + public function getMaxEnergy(): int { + return $this->maxenergy; + } + + public function setMaxEnergy(int $maxenergy) { + if ($maxenergy < 0) { + $maxenergy = 0; + } + if ($this->energy > $maxenergy) { + $this->energy = $maxenergy; + } + $this->maxenergy = $maxenergy; + } + +} diff --git a/lib/Place.lib.php b/lib/Place.lib.php new file mode 100644 index 0000000..24dab32 --- /dev/null +++ b/lib/Place.lib.php @@ -0,0 +1,166 @@ +osmid = $osmid; + $this->energy = new Energy(0, 100); + + if ($database->has("locations", ["osmid" => $osmid])) { + $game = $database->get("locations", ["locationid", "teamid", "ownerid", "osmid", "currentlife", "maxlife", "data", "lastactivity"], ["osmid" => $osmid]); + + $this->teamid = $game["teamid"]; + $this->ownerid = $game["ownerid"]; + $this->energy->setMaxEnergy($game["maxlife"]); + $this->energy->setEnergy($game["currentlife"]); + $this->data = $game["data"]; + $this->lastactivity = strtotime($game["lastactivity"]); + $this->gameexists = true; + } else { + $this->gameexists = false; + } + } + + /** + * Fetch IRL location data from the mapping server + * @global array $SETTINGS + * @return boolean True if successful, false on failure + */ + public function fetchIRLData(): bool { + global $SETTINGS; + + try { + $poiurl = $SETTINGS["poi"]["server"] . "?osmid=" . $this->osmid; + + $place = json_decode(file_get_contents($poiurl), true); + if ($place["type"] == "Feature") { + $this->name = $place["properties"]["name"]; + $this->longitude = $place["geometry"]["coordinates"][0]; + $this->latitude = $place["geometry"]["coordinates"][1]; + $this->placeexists = true; + return true; + } else { + $this->placeexists = false; + return false; + } + } catch (Exception $ex) { + $this->placeexists = false; + return false; + } + } + + /** + * Check if this place is claimed by a player/team. + * @return bool + */ + public function isClaimed(): bool { + if (empty($this->teamid)) { + return false; + } + if (empty($this->ownerid)) { + return false; + } + if ($this->energy->getEnergy() == 0) { + return false; + } + return true; + } + + /** + * Add the specified amount of energy to the place. + * @param int $diff + */ + public function changeEnergy(int $diff) { + $this->energy->setEnergy($this->energy->getEnergy() + $diff); + if ($this->energy->getEnergy() == 0) { + $this->unclaim(); + } + } + + public function getTeamID(): int { + return $this->teamid; + } + + /** + * Set the last activity on this place to now. + */ + public function updateLastActivity() { + $this->lastactivity = time(); + } + + /** + * Claim a place for the specified User. + * @param \Player $owner + */ + public function claim(\Player $owner) { + $this->energy = new Energy(25, 100); + $this->ownerid = $owner->getUID(); + $this->teamid = $owner->getTeamID(); + $this->updateLastActivity(); + } + + public function unclaim() { + $this->energy = new Energy(0, 0); + $this->ownerid = null; + $this->teamid = null; + $this->updateLastActivity(); + } + + public function save() { + global $database; + if ($this->gameexists) { + $database->update("locations", [ + "teamid" => $this->teamid, + "ownerid" => $this->ownerid, + "currentlife" => $this->energy->getEnergy(), + "maxlife" => $this->energy->getMaxEnergy(), + "lastactivity" => date("Y-m-d H:i:s", $this->lastactivity) + ], [ + "osmid" => $this->osmid + ] + ); + } else { + $database->insert("locations", [ + "teamid" => $this->teamid, + "ownerid" => $this->ownerid, + "currentlife" => $this->energy->getEnergy(), + "maxlife" => $this->energy->getMaxEnergy(), + "lastactivity" => date("Y-m-d H:i:s", $this->lastactivity), + "osmid" => $this->osmid + ]); + $this->gameexists = true; + } + } + +} diff --git a/lib/Player.lib.php b/lib/Player.lib.php new file mode 100644 index 0000000..9446bed --- /dev/null +++ b/lib/Player.lib.php @@ -0,0 +1,164 @@ +exists()) { + throw new InvalidArgumentException("User must exist."); + } + $this->user = $user; + + $this->energy = new Energy(100, 100); + $this->stats = new PlayerStats($user); + + if ($database->has("players", ["accountid" => $user->getUID()])) { + $profile = $database->get("players", ["accountid (id)", "nickname (name)", "level", "energy", "maxenergy", "teamid", "lastping", "stealth"], ["accountid" => $user->getUID()]); + $this->name = $profile["name"]; + $this->level = $profile["level"] * 1.0; + $this->energy->setMaxEnergy($profile["maxenergy"]); + $this->energy->setEnergy($profile["energy"]); + $this->teamid = $profile["teamid"]; + $this->lastping = strtotime($profile["lastping"]); + $this->stealth = $profile["stealth"] == true; + $this->exists = true; + } else { + $this->exists = false; + } + } + + public function exists(): bool { + return $this->exists; + } + + public function toArray(): array { + //"accountid (id)", "nickname (name)", "level", "energy", "maxenergy", "teamid" + return [ + "id" => $this->getUID(), + "name" => $this->name, + "level" => floor($this->level), + "energy" => $this->energy->getEnergy(), + "maxenergy" => $this->energy->getMaxEnergy(), + "teamid" => $this->getTeamID() + ]; + } + + public function getUID(): int { + return $this->user->getUID(); + } + + public function getLevel(): float { + return $this->level; + } + + public function getTeamID(): int { + return $this->teamid; + } + + public function setTeamID(int $id) { + $this->teamid = $id; + } + + public function getCredits(): int { + return $this->credits; + } + + /** + * Add the specified amount of energy to the player. + * @param int $diff + */ + public function changeEnergy(int $diff) { + $this->energy->setEnergy($this->energy->getEnergy() + $diff); + } + + /** + * Set the player's last ping time to now. + */ + public function doPing() { + $this->lastping = time(); + } + + /** + * Add experience to the user's level for doing something. + */ + public function addExp() { + $exp = pow(pow(floor($this->level * 1.0) + 1, 2), -1.2); + $this->level = $this->level + $exp; + $this->recalculateStats(); + } + + public function recalculateStats() { + $healthpercent = ($this->energy->getEnergy() * 1.0) / ($this->energy->getMaxEnergy() * 1.0); + + $maxenergy = $this->energy->getMaxEnergy(); + $this->energy->setMaxEnergy(floor($this->level) * 100); + + // If the max energy increased, adjust the current energy + // to the same percentage as it was before + if ($this->energy->getMaxEnergy() != $maxenergy) { + $this->energy->setEnergy($this->energy->getMaxEnergy() * $healthpercent); + } + } + + public function createPlayer() { + global $database; + + if ($this->exists) { + throw new Exception("This player already exists."); + } + $database->insert("players", [ + "accountid" => $this->user->getUID(), + "level" => $this->getLevel(), + "energy" => $this->energy->getEnergy(), + "maxenergy" => $this->energy->getMaxEnergy(), + "credits" => $this->getCredits(), + "lastping" => date("Y-m-d H:i:s", $this->lastping), + "teamid" => $this->getTeamID(), + "nickname" => $this->user->getName() + ]); + $this->stats->save(); + $this->exists = true; + } + + public function save() { + global $database; + if (!$this->exists) { + $this->createPlayer(); + return; + } + + $database->update("players", + [ + "level" => $this->getLevel(), + "energy" => $this->energy->getEnergy(), + "maxenergy" => $this->energy->getMaxEnergy(), + "credits" => $this->getCredits(), + "lastping" => date("Y-m-d H:i:s", $this->lastping), + "teamid" => $this->getTeamID(), + "nickname" => $this->user->getName() + ], + [ + "accountid" => $this->user->getUID() + ] + ); + $this->stats->save(); + } + +} diff --git a/lib/PlayerStats.lib.php b/lib/PlayerStats.lib.php new file mode 100644 index 0000000..d6becbb --- /dev/null +++ b/lib/PlayerStats.lib.php @@ -0,0 +1,102 @@ +userid = $user->getUID(); + + if ($database->has("player_stats", ["accountid" => $this->userid])) { + $stats = $database->get("player_stats", ["claims", "attacks", "defends", "scans", "distancekm"], ["accountid" => $this->userid]); + $this->claims = $stats["claims"]; + $this->attacks = $stats["attacks"]; + $this->defends = $stats["defends"]; + $this->scans = $stats["scans"]; + $this->distancekm = $stats["distancekm"]; + } + } + + public function getStat(int $stat) { + switch ($stat) { + case PlayerStats::CLAIMS: + return $this->claims; + case PlayerStats::ATTACKS: + return $this->attacks; + case PlayerStats::DEFENDS: + return $this->defends; + case PlayerStats::SCANS: + return $this->scans; + case PlayerStats::DISTANCEKM: + return $this->distancekm; + default: + return null; + } + } + + public function updateStat(int $stat, $diff) { + switch ($stat) { + case PlayerStats::CLAIMS: + $this->claims += $diff; + break; + case PlayerStats::ATTACKS: + $this->attacks += $diff; + break; + case PlayerStats::DEFENDS: + $this->defends += $diff; + break; + case PlayerStats::SCANS: + $this->scans += $diff; + break; + case PlayerStats::DISTANCEKM: + $this->distancekm += $diff; + break; + } + } + + public function save() { + global $database; + if ($database->has("player_stats", ["accountid" => $this->userid])) { + $database->update("player_stats", [ + "claims" => $this->claims, + "attacks" => $this->attacks, + "defends" => $this->defends, + "scans" => $this->scans, + "distancekm" => $this->distancekm + ], [ + "accountid" => $this->userid + ] + ); + } else { + $database->insert("player_stats", [ + "accountid" => $this->userid, + "claims" => $this->claims, + "attacks" => $this->attacks, + "defends" => $this->defends, + "scans" => $this->scans, + "distancekm" => $this->distancekm + ] + ); + } + } + +}