Skip to content
This repository has been archived by the owner on May 20, 2023. It is now read-only.

Multiworld system #929

Closed
wants to merge 12 commits into from
Closed

Conversation

aurelion5670
Copy link

@aurelion5670 aurelion5670 commented Mar 16, 2020

Multiworld System for OTServ Global, multiworld flag is already enabled but it doesn't affect the main server at all.

What it contains?

  • - Separated players by worlds.
  • - Separated market lists by worlds
  • - Separated houses by worlds
  • - Separated house items by worlds
  • - World id is being loaded on startup to store it on the memory.
  • - Server configs has their own world_ids
  • - Gameworlds are being loaded with a XML File

Willing to do the neccesary changes to make it merged into the repo.

@aurelion5670
Copy link
Author

Any code that should be written better? I'm up to colaborate :P

@Xaekai
Copy link

Xaekai commented Mar 17, 2020

Well, in the end, by still supplying this code to this repo you come out looking like a consummate professional to me.

@aurelion5670
Copy link
Author

Added missing worldid on config.lua and a small note

@omarcopires
Copy link
Contributor

I believe that making changes directly to the database file is not the best option, wouldn't it be more interesting to use the migration system, since most users already have an online server?

Just a tip, not a criticism.

@slawkens
Copy link
Contributor

slawkens commented Mar 20, 2020

What I don't like, is that in some places you are calling it "WorldId" and in other "ServerId"

Let me show an example:

<servers>
	<server id="0" name="Testserver" ip="127.0.0.1" port="7172"/>

and in config there is:
worldId

So, my advice is: follow some rules. Either call it world ID, or server ID. Because now it's a bit confusing.

I would call it world overall.

Like this:
worlds.xml:

<worlds>
	<world id="0" name="Testserver" ip="127.0.0.1" port="7172"/>

@Donkey-Robot
Copy link

Please add credit for the original author of the code @Milice

https://otland.net/members/16727/
thanks for share this code again

@Xaekai
Copy link

Xaekai commented Mar 25, 2020

@Donkey-Robot
That was already done. Days ago. And it's even directly linked just below this comment here.

@aurelion5670
Copy link
Author

Please add credit for the original author of the code @Milice

https://otland.net/members/16727/
thanks for share this code again

He's kivera global, the hour of the post on his thread and this one are too similiar and it can't be just a coincidence, please try to ban him, as i'm sure that he's going just to bring shit here

@aurelion5670
Copy link
Author

The code has been updated by the changes suggested

schema.sql Outdated
@@ -57,7 +56,6 @@ CREATE TABLE IF NOT EXISTS `accounts` (

CREATE TABLE IF NOT EXISTS `players` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`world_id` int(11) NOT NULL DEFAULT '0',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did you removed this?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@omarcopires suggested a migration file for the new owners, so i made it a migration

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But you still need to include it in schema.sql

Schema.sql should be always up-to-date.

And migrations for old servers.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done and sorry, this is my first pull request xD

@Xaekai
Copy link

Xaekai commented Mar 25, 2020

It's fine I suppose @aurelion5670. It's just I spent a non-trivial amount of time doing that, and now it will not be represented in the commit log in a fashion GitHub understands.

Some other notes on git usage:
1.) When you're doing a feature, it's best to work in a feature branch. i.e. your work to be brought into develop or master should not be done in that same branch of your clone. It will spare you certain types of headache later. You do something like git checkout -b develop-mw and work inside there. After your PR is accepted you can delete that branch, checkout the branch it was pulled into and git pull upstream should fast forward it just fine. For more information read this or search the web for "feature branch workflow"
2.) Your initial PRs should be commit squashed. You can read about that here or search the web for "squash commits"

@gpedro
Copy link
Contributor

gpedro commented Apr 19, 2020

this is wonderful, but we cannot merge this right now cuz we are focused to improve features and performance and probably futures features will need world id and when we reach this time we will able to merge.

I will keep this open if anyone wants to use this on your own server.

we appreciate your contribution!

Copy link
Contributor

@jlcvp jlcvp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

// Original idea and template by Milice, continued and completed by Aurelion5670

#ifndef FS_GAMEWORLDCONFIG_H_8675309REMEMBER0MILICE0COVID2019
#define FS_GAMEWORLDCONFIG_H_8675309REMEMBER0MILICE0COVID2019
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice easteregg

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your welcome. 😈

@@ -0,0 +1,10 @@
function onUpdateDatabase()
print("> Updating database to version 1 (world system)")
db.query("ALTER TABLE `server_config` ADD `world_id` INT(11) NOT NULL DEFAULT '0' FIRST;")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this alter table fails. The column already exists on the first installation (schema.sql)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but required if you aren't starting from a fresh schema? like updating existing running server

db.query("ALTER TABLE `market_offers` ADD `world_id` INT(11) NOT NULL DEFAULT '0' AFTER `id`;")
db.query("ALTER TABLE `players_online` ADD `world_id` INT(11) NOT NULL DEFAULT '0' FIRST;")
db.query("ALTER TABLE `tile_store` ADD `world_id` INT(11) NOT NULL DEFAULT '0' FIRST;")
return false
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

all these alter tables will fail if doing an clean install. You must either use migration or change the schema

@@ -20,6 +20,7 @@ We use the [issue tracker on GitHub](https://github.com/opentibiabr/OTServBR-Glo
- [fear lucien](https://github.com/FearLucien)
- [cjaker](https://github.com/Eternal-Scripts)
- [slavidodo](https://github.com/slavidodo)
- [aurelion and milice for multiworld system](https://github.com/aurelion5670)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think only the maintainers are allowed to change the readme

@Costallat Costallat added Priority: Low This issue can probably be picked up by anyone looking to contribute to the project, as an entry fix Status: Review Needed Type: Enhancement Most issues will probably ask for additions or changes. labels May 13, 2020
@Costallat Costallat added the code label May 13, 2020
@@ -201,7 +201,7 @@ void IOLoginData::updateOnlineStatus(uint32_t guid, bool login)

std::ostringstream query;
if (login) {
query << "INSERT INTO `players_online` VALUES (" << guid << ')';
query << "INSERT INTO `players_online` VALUES (" << guid << ') WHERE `world_id` = "<< g_gameserver.getWorldId() <<"';
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

g_gameserver or g_gameworld?

@eCov19
Copy link

eCov19 commented May 20, 2020

when I login my client debug :S

@Costallat
Copy link
Contributor

@eCov19 try to update items of the server, this PR uses an old items

@tysonstrange
Copy link

tysonstrange commented Jun 3, 2020

I've tried to implement on the current nostalrius distro, but the client just debugs when fetching the character list.

The getCharacterList function calls for an account number, but an account name in this source. maybe theres something else required for the nostalrius account number method?

Debug Assertion 7.7x Control.cpp 1174
Wed Jun 03 21:23:07 2020
Windows Version: 6.2 Build 9200 on 2
Graphic Engine:2
Last Packet Types 006 040 020 000 000 000 000 000 000 000
Last Pakther: 214 000 020 008 000 056 010 084 101 115 116 032 049 040 006 000
Player.cpp 383: exception occured, reason:
Network.cpp 885: exception occured (ErrorCode = 0), reason:
Control.cpp 1280: exception occured (Type = 6), reason:
Control.cpp 1274: unknown packet type during game (Type = 6)

Another I had when trying from the view file instead of compare changes

Wed Jun 03 21:31:26 2020
Windows Version: 6.2 build 9200 on 2
Graphic Engine: 2
Last Packet Types: 100 020 010 000 000 000 000 000 000 000
Last Packet: 201 000 020 008 000 056 010 084 101 115 116 032 049 100 001 000
Player.cpp 383: exception occurred, reason:
Network.cpp 885: exception occurred (ErrorCode = 0), reason:
Control.cpp 1280: exception occurred (Type = 100), reason:
Communication.cpp 1162: exception occurred (Count = 1), reason:
Network.cpp 470: exception occurred (MaxLength = 30), reason:
Utils.cpp 340: assertion failed (Position = 19) (Size—Length = —2355), reason: Positionc=Size—Length

@@ -0,0 +1,10 @@
function onUpdateDatabase()
print("> Updating database to version 1 (world system)")
db.query("ALTER TABLE `server_config` ADD `world_id` INT(11) NOT NULL DEFAULT '0' FIRST;")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but required if you aren't starting from a fresh schema? like updating existing running server

print("> Updating database to version 1 (world system)")
db.query("ALTER TABLE `server_config` ADD `world_id` INT(11) NOT NULL DEFAULT '0' FIRST;")
db.query("ALTER TABLE `players` ADD `world_id` INT(11) NOT NULL DEFAULT '0' AFTER `id`;")
db.query("ALTER TABLE `houses` ADD `world_id` INT(11) NOT NULL DEFAULT '0' AFTER `house_id`;")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't there also be:

Suggested change
db.query("ALTER TABLE `houses` ADD `world_id` INT(11) NOT NULL DEFAULT '0' AFTER `house_id`;")
db.query("ALTER TABLE `houses` ADD `world_id` INT(11) NOT NULL DEFAULT '0' AFTER `house_id`;")

The schema is updated to make this change, but no the live database?


PropWriteStream stream;
for (const auto& it : g_game.map.houses.getHouses()) {
//save house items
House* house = it.second;

if (house->getOwner() == 0) // CUSTOM

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this save a lot of time?

Copy link

@Colandus Colandus Jun 4, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if this could cause item cloning... If a player has a house full of items, and then takes the items out and lose ownership of the house, the house will keep its previous save state, when it still contained the player's items. And if items aren't cleaned when a new owner takes it, then they might get some cloned items?

@lgrossi
Copy link
Contributor

lgrossi commented Jun 3, 2020

Not the solution I'd choose for that. Splitting the database in global (with account amd some others global info) and them having db instamces per world (since each world will run a servet instance) sounds much nicer and simpler, imho.

@tysonstrange
Copy link

Not the solution I'd choose for that. Splitting the database in global (with account amd some others global info) and them having db instamces per world (since each world will run a servet instance) sounds much nicer and simpler, imho.

Do you have any documentation on implmenting something liek this?

I'm just looking for options to support multiple words using the same client, so all connection info/webpage/database is the same

@@ -37,7 +37,7 @@ function onStartup()
end

local time = os.time()
db.asyncQuery('TRUNCATE TABLE `players_online`')
db.asyncQuery('TRUNCATE TABLE `players_online` WHERE `world_id` = '..configManager.getNumber(configKeys.WORLD_ID)..'')
Copy link

@Colandus Colandus Jun 4, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TRUNCATE WHERE? Not possible 😛 Truncate will empty whole table. Should be DELETE.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, just make it DELETE FROM instead of TRUNCATE TABLE

@lgrossi
Copy link
Contributor

lgrossi commented Jun 4, 2020

Not the solution I'd choose for that. Splitting the database in global (with account amd some others global info) and them having db instamces per world (since each world will run a servet instance) sounds much nicer and simpler, imho.

Do you have any documentation on implmenting something liek this?

I'm just looking for options to support multiple words using the same client, so all connection info/webpage/database is the same

No, I have not. However, you simply need a few steps:

  • Split the main database into two: global_db, world_db.
  • Improve server db connection to connect to global and world dbs, and improve methods to look to the correct target db (global methods targets global db, world only methods targets world db).
  • Improve config.lua.dist to load global and world db names.
  • Improve protocol to send char list world name based on some configurable attribute.

As each server instance is an 'world instance' and has it own world_db, you don't need to worry about per world customization.

Site related, you can make an api that controls your website db operations. Some kind of per world router.

GET/POST 
  /.../{worldId}/{charId}

handler:
{
  // validates if the account has permission to read/change the given character and if the character belongs to the given world.
performAction(worldDB[worldId], charId)
}

something like that.

@@ -408,6 +410,7 @@ CREATE TABLE IF NOT EXISTS `guild_membership` (

CREATE TABLE IF NOT EXISTS `houses` (

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Houses Id is the primary key and house ID, with multiple worlds, wouldn't we need to import all 800 and whatever houses per world, setting the ID accordingly.

So if real map has 800 houses, 2 worlds with 2 real maps will need houses inserted twice with 2nd world ID and so on.

startupErrorMessage("Unable to load gameworlds!");
return;
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

g_gameworld.setWorldId(g_config.getNumber(ConfigManager::WORLD_ID));

Otherwise getWorldId() will always be 0

@Olimpotibia
Copy link
Contributor

not work with two servers in raid. Anyone tested it with two computers with separated database?

@Tazer89
Copy link
Contributor

Tazer89 commented Jul 13, 2020

not work with two servers in raid. Anyone tested it with two computers with separated database?

This is only made for using one database just with diffrent world_id

print("> Updating database to version 1 (world system)")
db.query("ALTER TABLE `server_config` ADD `world_id` INT(11) NOT NULL DEFAULT '0' FIRST;")
db.query("ALTER TABLE `players` ADD `world_id` INT(11) NOT NULL DEFAULT '0' AFTER `id`;")
db.query("ALTER TABLE `houses` ADD `world_id` INT(11) NOT NULL DEFAULT '0' AFTER `house_id`;")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
db.query("ALTER TABLE `houses` ADD `world_id` INT(11) NOT NULL DEFAULT '0' AFTER `house_id`;")
db.query("ALTER TABLE `houses` ADD `world_id` INT(11) NOT NULL DEFAULT '0' AFTER `id`;")

@dudantas
Copy link
Contributor

dudantas commented Oct 7, 2020

Hello. Since there are many issues to be solved, many systems to finish and new things to be done, we will close the pull, as it is very unlikely that he will go to develop. But, we are very happy with your contribution and in the future it may be reopened and reused. We hope your understanding.

@dudantas dudantas closed this Oct 7, 2020
@dudantas dudantas removed Priority: Low This issue can probably be picked up by anyone looking to contribute to the project, as an entry fix Review: Needed Type: Enhancement Most issues will probably ask for additions or changes. code labels Oct 7, 2020
@PeachieDude
Copy link
Contributor

I know its closed but is this one usable?
did anyone test it with new releases?
im trying to find a way to have multiworld w/o having to have two sites/db and so and this one is the only related thing that ive found.

@tysonstrange
Copy link

Yes it works fine

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet