Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

improve: Outfit(addons) & Mounts database changes #2404

Open
wants to merge 58 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
650cc29
update
luanluciano93 Mar 9, 2024
11038b1
Update iologindata_load_player.cpp
luanluciano93 Mar 9, 2024
b1d024a
Lua code format - (Stylua)
github-actions[bot] Mar 9, 2024
d9c9f98
Update player.cpp
luanluciano93 Mar 14, 2024
17851c7
Code format - (Clang-format)
github-actions[bot] Mar 14, 2024
e447d8d
Update iologindata.cpp
luanluciano93 Mar 14, 2024
6db1b81
Update iologindata_save_player.hpp
luanluciano93 Mar 14, 2024
a1f7c42
Update iologindata_save_player.cpp
luanluciano93 Mar 14, 2024
15a4a94
Update iologindata.cpp
luanluciano93 Mar 14, 2024
46d6294
Update iologindata_save_player.cpp
luanluciano93 Mar 14, 2024
98c1176
Update game.hpp
luanluciano93 Mar 14, 2024
7f53ac1
Merge branch 'main' into update-outfits-and-mounts
luanluciano93 Mar 14, 2024
15b1588
Update player.cpp
luanluciano93 Mar 14, 2024
3c9408d
Update player.cpp
luanluciano93 Mar 14, 2024
cc6928f
Update iologindata_save_player.cpp
luanluciano93 Mar 14, 2024
a3e9626
Update player.cpp
luanluciano93 Mar 14, 2024
dad44e2
Update iologindata_save_player.cpp
luanluciano93 Mar 14, 2024
225974c
Code format - (Clang-format)
github-actions[bot] Mar 14, 2024
58a3303
Update 44.lua
luanluciano93 Mar 14, 2024
8a2633a
update
luanluciano93 Mar 14, 2024
5321873
Update player.cpp
luanluciano93 Mar 14, 2024
7e47cad
Update iologindata_load_player.cpp
luanluciano93 Mar 14, 2024
0193170
Merge branch 'main' into update-outfits-and-mounts
luanluciano93 Mar 19, 2024
0e88e66
Update player.cpp
luanluciano93 Mar 28, 2024
7ba95f9
Update player.cpp
luanluciano93 Mar 30, 2024
0399c23
Merge remote-tracking branch 'upstream/main' into update-outfits-and-…
luanluciano93 Mar 31, 2024
4a389e5
Update player.cpp
luanluciano93 Mar 31, 2024
81d1e0c
Update iologindata_load_player.cpp
luanluciano93 Mar 31, 2024
815b984
update
luanluciano93 Apr 3, 2024
5aef735
update
luanluciano93 Apr 3, 2024
cb3df6d
Merge branch 'main' into update-outfits-and-mounts
luanluciano93 Apr 3, 2024
14287bc
update
luanluciano93 Apr 3, 2024
27007c9
Update player.hpp
luanluciano93 Apr 4, 2024
0135f34
Update player.cpp
luanluciano93 Apr 4, 2024
16a7e72
Update player.hpp
luanluciano93 Apr 4, 2024
05b9e63
Merge branch 'main' into update-outfits-and-mounts
luanluciano93 Apr 6, 2024
360faf9
update
luanluciano93 Jun 13, 2024
5aa63f1
update
luanluciano93 Jun 14, 2024
51be044
Merge branch 'main' into update-outfits-and-mounts
luanluciano93 Jun 14, 2024
d19bbec
Update player.hpp
luanluciano93 Jun 16, 2024
e71ce30
Update player.cpp
luanluciano93 Jun 16, 2024
38859a1
Merge branch 'main' into update-outfits-and-mounts
luanluciano93 Jun 16, 2024
39970ff
Merge branch 'main' into update-outfits-and-mounts
luanluciano93 Jun 23, 2024
10dbd28
Merge branch 'main' into update-outfits-and-mounts
luanluciano93 Jul 3, 2024
953eab5
Merge branch 'main' into update-outfits-and-mounts
luanluciano93 Jul 7, 2024
76c135b
Merge branch 'main' into update-outfits-and-mounts
luanluciano93 Jul 8, 2024
9d110b7
Update iologindata_load_player.cpp
luanluciano93 Jul 8, 2024
a436e0b
Update player.cpp
luanluciano93 Jul 8, 2024
ef9b2a0
Update player.cpp
luanluciano93 Jul 8, 2024
eeeff79
Update iologindata_load_player.cpp
luanluciano93 Jul 8, 2024
6056866
Update iologindata_save_player.cpp
luanluciano93 Jul 8, 2024
48f36ef
Merge branch 'main' into update-outfits-and-mounts
luanluciano93 Jul 10, 2024
a4cc95e
Merge branch 'main' into update-outfits-and-mounts
luanluciano93 Jul 12, 2024
92e4add
Merge branch 'main' into update-outfits-and-mounts
luanluciano93 Jul 21, 2024
3205f7e
Update player_title.cpp
luanluciano93 Jul 21, 2024
467014a
Merge branch 'main' into update-outfits-and-mounts
luanluciano93 Aug 28, 2024
0b34cdf
Merge branch 'main' into update-outfits-and-mounts
luanluciano93 Sep 12, 2024
9a01da7
Merge branch 'main' into update-outfits-and-mounts
luanluciano93 Sep 24, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 58 additions & 1 deletion data-otservbr-global/migrations/46.lua
Original file line number Diff line number Diff line change
@@ -1,3 +1,60 @@
function onUpdateDatabase()
return false -- true = There are others migrations file | false = this is the last migration file
logger.info("Updating database to version 45 (rework on outfits(addons) & mount saving/loading)")

db.query([[
CREATE TABLE IF NOT EXISTS `player_outfits` (`player_id` int DEFAULT 0 NOT NULL,`outfit_id` smallint unsigned DEFAULT 0 NOT NULL,`addons` tinyint unsigned DEFAULT 0 NOT NULL,
PRIMARY KEY (`player_id`,`outfit_id`),
FOREIGN KEY (`player_id`) REFERENCES `players`(`id`) ON DELETE CASCADE)
ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;
]])

db.query([[
CREATE TABLE IF NOT EXISTS `player_mounts` (`player_id` int DEFAULT 0 NOT NULL,`mount_id` smallint unsigned DEFAULT 0 NOT NULL,
PRIMARY KEY (`player_id`,`mount_id`),
FOREIGN KEY (`player_id`) REFERENCES `players`(`id`) ON DELETE CASCADE)
ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;
]])

db.query([[
ALTER TABLE `players`
ADD `currentmount` smallint unsigned NOT NULL DEFAULT 0 AFTER `lookmountfeet`;
]])

local outfitRange = 10001000
local mountRange = 10002001

local resultId = db.storeQuery(string.format("SELECT `player_id`, `value` FROM `player_storage` WHERE `key` >= %d AND `key` <= %d", outfitRange, outfitRange + 500))
if resultId then
repeat
local playerId = Result.getNumber(resultId, "player_id")
local outfitId = bit.rshift(Result.getNumber(resultId, "value"), 16)
local addons = bit.band(Result.getNumber(resultId, "value"), 0xFF)

db.query(string.format("INSERT INTO `player_outfits` (`player_id`, `outfit_id`, `addons`) VALUES (%d, %d, %d)", playerId, outfitId, addons))
until not Result.next(resultId)
Result.free(resultId)
end

local resultId = db.storeQuery(string.format("SELECT `player_id`, `key`, `value` FROM `player_storage` WHERE `key` >= %d AND `key` <= %d", mountRange, mountRange + 10))
if resultId then
repeat
for i = 1, 200 do
local key = mountRange + ((i - 1) / 31)
if key == Result.getNumber(resultId, "key") then
local playerId = Result.getNumber(resultId, "player_id")
local lshift = bit.lshift(1, ((i - 1) % 31))
local mount = bit.band(lshift, Result.getNumber(resultId, "value"))

if mount ~= 0 then
db.query(string.format("INSERT INTO `player_mounts` (`player_id`, `mount_id`) VALUES (%d, %d)", playerId, i))
end
end
end
until not Result.next(resultId)
Result.free(resultId)
end

-- deleting all outfit & mount storages at once
db.asyncQuery(string.format("DELETE FROM `player_storage` WHERE `key` >= %d AND `key` <= %d OR `key` >= %d AND `key` <= %d", outfitRange, outfitRange + 500, mountRange, mountRange + 10))
return true
end
3 changes: 3 additions & 0 deletions data-otservbr-global/migrations/47.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
function onUpdateDatabase()
return false -- true = There are others migrations file | false = this is the last migration file
end
24 changes: 23 additions & 1 deletion schema.sql
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ CREATE TABLE IF NOT EXISTS `server_config` (
CONSTRAINT `server_config_pk` PRIMARY KEY (`config`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO `server_config` (`config`, `value`) VALUES ('db_version', '46'), ('motd_hash', ''), ('motd_num', '0'), ('players_record', '0');
INSERT INTO `server_config` (`config`, `value`) VALUES ('db_version', '47'), ('motd_hash', ''), ('motd_num', '0'), ('players_record', '0');

-- Table structure `accounts`
CREATE TABLE IF NOT EXISTS `accounts` (
Expand Down Expand Up @@ -141,6 +141,7 @@ CREATE TABLE IF NOT EXISTS `players` (
`lookmountfeet` tinyint(3) unsigned NOT NULL DEFAULT '0',
`lookmounthead` tinyint(3) unsigned NOT NULL DEFAULT '0',
`lookmountlegs` tinyint(3) unsigned NOT NULL DEFAULT '0',
`currentmount` smallint(5) unsigned NOT NULL DEFAULT '0',
`lookfamiliarstype` int(11) unsigned NOT NULL DEFAULT '0',
`isreward` tinyint(1) NOT NULL DEFAULT '1',
`istutorial` tinyint(1) NOT NULL DEFAULT '0',
Expand Down Expand Up @@ -779,6 +780,27 @@ CREATE TABLE IF NOT EXISTS `player_storage` (
ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- Table structure `player_outfits`
CREATE TABLE IF NOT EXISTS `player_outfits` (
`player_id` int(11) NOT NULL DEFAULT '0',
`outfit_id` smallint(4) UNSIGNED NOT NULL DEFAULT '0',
`addons` tinyint(1) UNSIGNED NOT NULL DEFAULT '0',
CONSTRAINT `player_outfits_pk` PRIMARY KEY (`player_id`, `outfit_id`),
CONSTRAINT `player_outfits_players_fk`
FOREIGN KEY (`player_id`) REFERENCES `players`(`id`)
ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;

-- Table structure `player_mounts`
CREATE TABLE IF NOT EXISTS `player_mounts` (
`player_id` int(11) NOT NULL DEFAULT '0',
`mount_id` smallint(4) UNSIGNED NOT NULL DEFAULT '0',
CONSTRAINT `player_mounts_pk` PRIMARY KEY (`player_id`, `mount_id`),
CONSTRAINT `player_mounts_players_fk`
FOREIGN KEY (`player_id`) REFERENCES `players`(`id`)
ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;

-- Table structure `store_history`
CREATE TABLE IF NOT EXISTS `store_history` (
`id` int(11) NOT NULL AUTO_INCREMENT,
Expand Down
4 changes: 2 additions & 2 deletions src/creatures/appearance/mounts/mounts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ bool Mounts::loadFromXml() {
}

mounts.emplace(std::make_shared<Mount>(
static_cast<uint8_t>(pugi::cast<uint16_t>(mountNode.attribute("id").value())),
static_cast<uint16_t>(pugi::cast<uint32_t>(mountNode.attribute("id").value())),
lookType,
mountNode.attribute("name").as_string(),
pugi::cast<int32_t>(mountNode.attribute("speed").value()),
Expand All @@ -47,7 +47,7 @@ bool Mounts::loadFromXml() {
return true;
}

std::shared_ptr<Mount> Mounts::getMountByID(uint8_t id) {
std::shared_ptr<Mount> Mounts::getMountByID(uint16_t id) {
auto it = std::find_if(mounts.begin(), mounts.end(), [id](const std::shared_ptr<Mount> &mount) {
return mount->id == id; // Note the use of -> operator to access the members of the Mount object
});
Expand Down
6 changes: 3 additions & 3 deletions src/creatures/appearance/mounts/mounts.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@
#pragma once

struct Mount {
Mount(uint8_t initId, uint16_t initClientId, std::string initName, int32_t initSpeed, bool initPremium, std::string initType) :
Mount(uint16_t initId, uint16_t initClientId, std::string initName, int32_t initSpeed, bool initPremium, std::string initType) :
name(std::move(initName)), speed(initSpeed), clientId(initClientId), id(initId), premium(initPremium),
type(std::move(initType)) { }

std::string name;
int32_t speed;
uint16_t clientId;
uint8_t id;
uint16_t id;
bool premium;
std::string type;
};
Expand All @@ -26,7 +26,7 @@ class Mounts {
public:
bool reload();
bool loadFromXml();
std::shared_ptr<Mount> getMountByID(uint8_t id);
std::shared_ptr<Mount> getMountByID(uint16_t id);
std::shared_ptr<Mount> getMountByName(const std::string &name);
std::shared_ptr<Mount> getMountByClientID(uint16_t clientId);

Expand Down
1 change: 1 addition & 0 deletions src/creatures/creature.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -773,6 +773,7 @@ class Creature : virtual public Thing, public SharedObject {

Outfit_t currentOutfit;
Outfit_t defaultOutfit;
uint16_t currentMount;

Position lastPosition;
LightInfo internalLight;
Expand Down
1 change: 1 addition & 0 deletions src/creatures/creatures_definitions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1666,6 +1666,7 @@ struct Outfit_t {
uint8_t lookMountBody = 0;
uint8_t lookMountLegs = 0;
uint8_t lookMountFeet = 0;
uint16_t currentMount = 0;
uint16_t lookFamiliarsType = 0;
};

Expand Down
2 changes: 1 addition & 1 deletion src/creatures/players/cyclopedia/player_title.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ bool PlayerTitle::checkMount(uint32_t amount) {
}

bool PlayerTitle::checkOutfit(uint32_t amount) {
return m_player.outfits.size() >= amount;
return m_player.outfitsMap.size() >= amount;
}

bool PlayerTitle::checkLevel(uint32_t amount) {
Expand Down
104 changes: 36 additions & 68 deletions src/creatures/players/player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -877,15 +877,7 @@ uint16_t Player::getLookCorpse() const {

void Player::addStorageValue(const uint32_t key, const int32_t value, const bool isLogin /* = false*/) {
if (IS_IN_KEYRANGE(key, RESERVED_RANGE)) {
if (IS_IN_KEYRANGE(key, OUTFITS_RANGE)) {
outfits.emplace_back(
value >> 16,
value & 0xFF
);
return;
} else if (IS_IN_KEYRANGE(key, MOUNTS_RANGE)) {
// do nothing
} else if (IS_IN_KEYRANGE(key, FAMILIARS_RANGE)) {
if (IS_IN_KEYRANGE(key, FAMILIARS_RANGE)) {
familiars.emplace_back(
value >> 16
);
Expand Down Expand Up @@ -4936,11 +4928,13 @@ bool Player::canWear(uint16_t lookType, uint8_t addons) const {
return true;
}

for (const OutfitEntry &outfitEntry : outfits) {
if (outfitEntry.lookType != lookType) {
continue;
for (const auto &outfitEntry : outfitsMap) {
if (outfitEntry.lookType == lookType) {
if (outfitEntry.addons == addons || outfitEntry.addons == 3 || addons == 0) {
return true;
}
return false; // have lookType on list and addons don't match
}
return (outfitEntry.addons & addons) == addons;
}
return false;
}
Expand All @@ -4967,11 +4961,6 @@ bool Player::canLogout() {
}

void Player::genReservedStorageRange() {
// generate outfits range
uint32_t outfits_key = PSTRG_OUTFITS_RANGE_START;
for (const OutfitEntry &entry : outfits) {
storageMap[++outfits_key] = (entry.lookType << 16) | entry.addons;
}
// generate familiars range
uint32_t familiar_key = PSTRG_FAMILIARS_RANGE_START;
for (const FamiliarEntry &entry : familiars) {
Expand All @@ -4980,28 +4969,28 @@ void Player::genReservedStorageRange() {
}

void Player::addOutfit(uint16_t lookType, uint8_t addons) {
for (OutfitEntry &outfitEntry : outfits) {
for (auto &outfitEntry : outfitsMap) {
if (outfitEntry.lookType == lookType) {
outfitEntry.addons |= addons;
return;
}
}
outfits.emplace_back(lookType, addons);
outfitsMap.emplace_back(lookType, addons);
}

bool Player::removeOutfit(uint16_t lookType) {
for (auto it = outfits.begin(), end = outfits.end(); it != end; ++it) {
OutfitEntry &entry = *it;
if (entry.lookType == lookType) {
outfits.erase(it);
for (auto it = outfitsMap.begin(), end = outfitsMap.end(); it != end; ++it) {
auto &outfitEntry = *it;
if (outfitEntry.lookType == lookType) {
outfitsMap.erase(it);
return true;
}
}
return false;
}

bool Player::removeOutfitAddon(uint16_t lookType, uint8_t addons) {
for (OutfitEntry &outfitEntry : outfits) {
for (auto &outfitEntry : outfitsMap) {
if (outfitEntry.lookType == lookType) {
outfitEntry.addons &= ~addons;
return true;
Expand All @@ -5020,7 +5009,7 @@ bool Player::getOutfitAddons(const std::shared_ptr<Outfit> &outfit, uint8_t &add
return false;
}

for (const OutfitEntry &outfitEntry : outfits) {
for (const auto &outfitEntry : outfitsMap) {
if (outfitEntry.lookType != outfit->lookType) {
continue;
}
Expand Down Expand Up @@ -5774,24 +5763,19 @@ void Player::sendUnjustifiedPoints() {
}
}

uint8_t Player::getLastMount() const {
int32_t value = getStorageValue(PSTRG_MOUNTS_CURRENTMOUNT);
if (value > 0) {
return value;
uint16_t Player::getLastMount() const {
if (currentMount > 0) {
return currentMount;
}
return static_cast<uint8_t>(kv()->get("last-mount")->get<int>());
}

uint8_t Player::getCurrentMount() const {
int32_t value = getStorageValue(PSTRG_MOUNTS_CURRENTMOUNT);
if (value > 0) {
return value;
}
return 0;
uint16_t Player::getCurrentMount() const {
return currentMount;
}

void Player::setCurrentMount(uint8_t mount) {
addStorageValue(PSTRG_MOUNTS_CURRENTMOUNT, mount);
void Player::setCurrentMount(uint16_t mountId) {
currentMount = mountId;
}

bool Player::hasAnyMount() const {
Expand All @@ -5804,8 +5788,8 @@ bool Player::hasAnyMount() const {
return false;
}

uint8_t Player::getRandomMountId() const {
std::vector<uint8_t> playerMounts;
uint16_t Player::getRandomMountId() const {
std::vector<uint16_t> playerMounts;
const auto mounts = g_game().mounts.getMounts();
for (const auto &mount : mounts) {
if (hasMount(mount)) {
Expand Down Expand Up @@ -5844,7 +5828,7 @@ bool Player::toggleMount(bool mount) {
return false;
}

uint8_t currentMountId = getLastMount();
uint16_t currentMountId = getLastMount();
if (currentMountId == 0) {
sendOutfitWindow();
return false;
Expand Down Expand Up @@ -5896,40 +5880,31 @@ bool Player::toggleMount(bool mount) {
return true;
}

bool Player::tameMount(uint8_t mountId) {
bool Player::tameMount(uint16_t mountId) {
if (!g_game().mounts.getMountByID(mountId)) {
return false;
}

const uint8_t tmpMountId = mountId - 1;
const uint32_t key = PSTRG_MOUNTS_RANGE_START + (tmpMountId / 31);

int32_t value = getStorageValue(key);
if (value != -1) {
value |= (1 << (tmpMountId % 31));
} else {
value = (1 << (tmpMountId % 31));
const auto mount = g_game().mounts.getMountByID(mountId);
if (hasMount(mount)) {
return false;
}

addStorageValue(key, value);
mountsMap.emplace(mountId);
return true;
}

bool Player::untameMount(uint8_t mountId) {
bool Player::untameMount(uint16_t mountId) {
if (!g_game().mounts.getMountByID(mountId)) {
return false;
}

const uint8_t tmpMountId = mountId - 1;
const uint32_t key = PSTRG_MOUNTS_RANGE_START + (tmpMountId / 31);

int32_t value = getStorageValue(key);
if (value == -1) {
return true;
const auto mount = g_game().mounts.getMountByID(mountId);
if (!hasMount(mount)) {
return false;
}

value &= ~(1 << (tmpMountId % 31));
addStorageValue(key, value);
mountsMap.erase(mountId);

if (getCurrentMount() == mountId) {
if (isMounted()) {
Expand All @@ -5953,14 +5928,7 @@ bool Player::hasMount(const std::shared_ptr<Mount> mount) const {
return false;
}

const uint8_t tmpMountId = mount->id - 1;

int32_t value = getStorageValue(PSTRG_MOUNTS_RANGE_START + (tmpMountId / 31));
if (value == -1) {
return false;
}

return ((1 << (tmpMountId % 31)) & value) != 0;
return mountsMap.find(mount->id) != mountsMap.end();
}

void Player::dismount() {
Expand Down
Loading
Loading