after weeks of hard work, I finnaly managed to make a "working" multiplayer campaign mod. And i share It with you guys, so you can make others life better.
(i am a noob in presenting/explaining something, so excuse me)
THIS IS NOT A PLAYABLE VERSION YET!!!
here you can see the very old first design of multicamp
WARNING! BAD ENGLISH BELOW!!!!!!!
I must warn you now that modding this requires PHP knowledge!!! If you don't have any PHP knowledge, then quit reading this.
So first let's start with how to set up everything.
What you need to set up:
What you need to know about modding it:
Client modding
Server modding
Your main file for modding webserver is code.php.
Here is a example of how to make and use a new event:
Changelog
multiplayer campaign mod files download -> HERE .
Credits:
*taleworlds for creating warband
*Gotha for indirectly giving me the ideea that multi camp is possible
*MadocComadrin for madmin (i took the chat presentation from there)
What you are not allowed:
it is not allowed to use scripts/part of scripts without giving credits to me
first appearence of this kind of mod was here!
Thread created in 3+ hours.
(i am a noob in presenting/explaining something, so excuse me)
THIS IS NOT A PLAYABLE VERSION YET!!!
here you can see the very old first design of multicamp
WARNING! BAD ENGLISH BELOW!!!!!!!
I must warn you now that modding this requires PHP knowledge!!! If you don't have any PHP knowledge, then quit reading this.
So first let's start with how to set up everything.
What you need to set up:
This mod allows you to play singleplayer world map into multiplayer. In order to play a multiplayer game, you need a server. The server that we use in this case is a webserver.
So the first thing that you need to set up is a webserver. I use xampp simple because it is easy to install and it is very easy to use. After you choosed your webserver and after you installed it, you need to find the root folder of it.
Download the mod from the link at the bottom. Then unzip it, and copy the files from webserver files folder (you need to copy the files, not hte folder!!!!) and paste them inside the root of the server.
Now the server setup is complete.
Next you will need to test your server. To do that, open your web browser, and type in the adress bar this "127.0.0.1/test.php" and press enter. Now you should see the message "All setups are fine!". If you do not see this message, then you did something wrong, or there are some permissions that needs to be edited(google.com is your best friend)
If you see that message, then it is good, and you will need to test with your external ip. Open the web browser again and type in "your_external_ip/test.php" , where your_external_ip needs to be replaced with your ip(you can get your ip here http://whatismyipaddress.com/). You should see the same message. If you do not see that message, then you did something wrong, or there are some permissions that needs to be edited.
If you see that message, then to make sure that it is all good, give the link with the external ip to a friend, and let him confirm that it works.]
Now the server setup is completed and it is working.
So the first thing that you need to set up is a webserver. I use xampp simple because it is easy to install and it is very easy to use. After you choosed your webserver and after you installed it, you need to find the root folder of it.
Download the mod from the link at the bottom. Then unzip it, and copy the files from webserver files folder (you need to copy the files, not hte folder!!!!) and paste them inside the root of the server.
Now the server setup is complete.
Next you will need to test your server. To do that, open your web browser, and type in the adress bar this "127.0.0.1/test.php" and press enter. Now you should see the message "All setups are fine!". If you do not see this message, then you did something wrong, or there are some permissions that needs to be edited(google.com is your best friend)
If you see that message, then it is good, and you will need to test with your external ip. Open the web browser again and type in "your_external_ip/test.php" , where your_external_ip needs to be replaced with your ip(you can get your ip here http://whatismyipaddress.com/). You should see the same message. If you do not see that message, then you did something wrong, or there are some permissions that needs to be edited.
If you see that message, then to make sure that it is all good, give the link with the external ip to a friend, and let him confirm that it works.]
Now the server setup is completed and it is working.
The client is just a regular warband mod, but the module system needs an extra setup. After you put your export dir in module_info, you need to specifie the ip of the server that the mod will play.
Setting the ip is very simple: open up module_strings and scrool down to the bottom. The last string should be called "ip", and it's content should be "http://127.0.0.1/multiplayer.php?".Replace "127.0.0.1" with the ip of the server that you want to connect..and you are done!
Setting the ip is very simple: open up module_strings and scrool down to the bottom. The last string should be called "ip", and it's content should be "http://127.0.0.1/multiplayer.php?".Replace "127.0.0.1" with the ip of the server that you want to connect..and you are done!
What you need to know about modding it:
This mod only allows you to send messages(ints and strs) between server and client. It is like the normal multiplayer warband, but instead of having hardwired syncs (player movement, scene props positions, attack, defense) , you would need to write them manually with "multiplayer_send_int_to_server" and "multiplayer_send_string_to_server" (and the others) .
Client modding
The messages that you receive from the server will get into the "code" (that is the name of the script) script.
At the beggining, there is this part
:args stores a slot (troop slot), that contains all the integers that you need to use received from the server (not actually all, you will understand later). the index 0 will always store the event!
:num_integers stores the number of integers (ex: if you have these integers "2,45,123", num_integers will be 3).
:num_strings stores the number of strings (ex as the integers)
all the received strings will be stored into string regs starting from s1!!!(ex: if you have the first string "asd" and the second "test", then s1 will store"asd" and s2 will store "test")
At the beggining, there is this part
Code:
(store_script_param,":args",1),
(store_script_param,":num_integers",2),
(store_script_param,":num_strings",3),
:args stores a slot (troop slot), that contains all the integers that you need to use received from the server (not actually all, you will understand later). the index 0 will always store the event!
:num_integers stores the number of integers (ex: if you have these integers "2,45,123", num_integers will be 3).
:num_strings stores the number of strings (ex as the integers)
all the received strings will be stored into string regs starting from s1!!!(ex: if you have the first string "asd" and the second "test", then s1 will store"asd" and s2 will store "test")
Sending messages to server is quite easy. You need to use these 2 sintaxes
To send ints to server, you will first put the event (you can use/define new mpcamp events in module_constants (search for this "MULTI CAMP SLOTS" without quotes)) , then you will put the total number of ints that you want to send (ex: if you want to send ints "2,5,76", then the total nr will be 3), then you will need to put the ints (variables or constants), separated with comma.
ex: for sending the variables ":id",":gold",":cost" , with the event "mpcamp_event_example" you will use (call_script,"script_send_int_to_server",mpcamp_event_example , 3 ,":id",":gold",":cost"),
To send strings to server, you need to specifie the event, how many strings you want to save, and the string registers.
Ex: if you want to send 2 strings (s7 and s13) with the event "mpcamp_event_example", you will use this (call_script,"script_send_string_to_server",mpcamp_event_example,2,s7,s13),
If you want to send strings and ints, then you can store the ints into strings, and then send the entire thing with (call_script,"script_send_string_to_server",<event>,<number of strings>),
Code:
(call_script,"script_send_string_to_server",<event>,<number of strings>,<str1>,<str2>,...),
(call_script,"script_send_int_to_server",<event>,<number_of_ints>,<int1>,<int2>...),
ex: for sending the variables ":id",":gold",":cost" , with the event "mpcamp_event_example" you will use (call_script,"script_send_int_to_server",mpcamp_event_example , 3 ,":id",":gold",":cost"),
To send strings to server, you need to specifie the event, how many strings you want to save, and the string registers.
Ex: if you want to send 2 strings (s7 and s13) with the event "mpcamp_event_example", you will use this (call_script,"script_send_string_to_server",mpcamp_event_example,2,s7,s13),
If you want to send strings and ints, then you can store the ints into strings, and then send the entire thing with (call_script,"script_send_string_to_server",<event>,<number of strings>),
Server modding
Your main file for modding webserver is code.php.
the first line is this
$unique_id stores the unique id of the player that sended that message
$event stores the event number
$args is a array of all ints and strings received. Note $args[0] stores the event number (idk why i did put the parameter $event...i will fix this in the future version)
$nr_args stores the number of ints and strings
Code:
main_code($unique_id,$event,$nr_args,$args)
$event stores the event number
$args is a array of all ints and strings received. Note $args[0] stores the event number (idk why i did put the parameter $event...i will fix this in the future version)
$nr_args stores the number of ints and strings
sending messages to client is done using this syntax
<unique_id> the unique id of the player that we want the message to be sended
<data_array> is an array that needs to store the desired ints and strs to send. Note!!!! data_array[0] needs to be the event number!!!!!!!!!!!!
[strings_number] needs to be the number of strings (if it is not set, then the nr of strs is 0)
lets have a look at a example
$unique_id is the id that we will send data to
the first int (1) represents the event number
the second int(23) represents a constant int that will be sended
$example_var is a variable that will be sended
and also the nr of strings is 0, because it is not specified
another example
$unique_id is the id that we will send data to
the first int (2) represents the event number
the second int(46) represents a constant int that will be sended
"this is just a test" is a string
$example_var is a variable that will be sended
"just a string" another string that we will send
2 represents the nr of strings
Code:
send_data_to_player(<unique_id>,<data_array>,[strings_number])
<unique_id> the unique id of the player that we want the message to be sended
<data_array> is an array that needs to store the desired ints and strs to send. Note!!!! data_array[0] needs to be the event number!!!!!!!!!!!!
[strings_number] needs to be the number of strings (if it is not set, then the nr of strs is 0)
lets have a look at a example
Code:
send_data_to_player($unique_id,[1,23,$example_var])
the first int (1) represents the event number
the second int(23) represents a constant int that will be sended
$example_var is a variable that will be sended
and also the nr of strings is 0, because it is not specified
another example
Code:
send_data_to_player($unique_id,[2,46,"this is just a test",$example_var,"just a string"],2)
$unique_id is the id that we will send data to
the first int (2) represents the event number
the second int(46) represents a constant int that will be sended
"this is just a test" is a string
$example_var is a variable that will be sended
"just a string" another string that we will send
2 represents the nr of strings
--to be done
The structure is a bit complicated...All of the variables are stored in a .txt database (idk if anybody else done this before).
Every player have a unique id. This id is given by the server when the player registers first time (actually it is just a counter). When the player log in, to his unique id is attribuite a local id (1-10).The local id can vary if you logout and then log back in.
(I took this entire ideea from the actual warband mp.Each player have a unique id (based on his cd-key), and when he joins a server, the server will attribuite a local id (0-250).)
When a player registers, a new folder with the name of his unique id is created under "players" folder, then inside are created some .txt files, that will holds his variables( ip, local id, gold , etc). You will notice that the folder "to_send" will be created.
Now i hope you understood what the unique id represents.
Every player have a unique id. This id is given by the server when the player registers first time (actually it is just a counter). When the player log in, to his unique id is attribuite a local id (1-10).The local id can vary if you logout and then log back in.
(I took this entire ideea from the actual warband mp.Each player have a unique id (based on his cd-key), and when he joins a server, the server will attribuite a local id (0-250).)
When a player registers, a new folder with the name of his unique id is created under "players" folder, then inside are created some .txt files, that will holds his variables( ip, local id, gold , etc). You will notice that the folder "to_send" will be created.
Now i hope you understood what the unique id represents.
Here is a example of how to make and use a new event:
So now, that you know how to send/receive, lets have an example.I choosed the chat function, just because it is simple and it's easy to understand.
To create the chat, first we need a way to get a input.The best way (and the only way) is to make a chat presentation.So i grab the madmin admin chat presentation, and tweaked it a bit and it looked like this
The most important thing is this
So we checked if the string is not empty, and then we send it to server with "(call_script,"script_send_string_to_server",mpcamp_event_chat,1,s1),".
The client-server sending is done.
Now the string arrived to the server.
In code.php, we add a new case, case 3. then we check if there is a string (because the cheaty player can use a modified version of the mod)
.
If everything is ok, we will need to send the username of the player that wants to send the message, and we do it with get_player_username($unique_id) (you can see all the defined function in the readme.txt file)
Now that we got the message, and also the username, we want to send them to each player that is online.So we make a loop that will check every local id
then we get the unique id of the specific local id.
then we check if there is an online player at the specified local id(0 = no player)
and if everything is ok, then we send the message string and teh username to the client
The server-client sending is done!
Now the message is received by all online players. Next we want to display it in the clients. So we go to "code" script, and we add a new case
and then we display the message
and that's it! that is how the chat function is made...
To create the chat, first we need a way to get a input.The best way (and the only way) is to make a chat presentation.So i grab the madmin admin chat presentation, and tweaked it a bit and it looked like this
Code:
("chat_message",prsntf_manual_end_only, 0,[
(ti_on_presentation_load,
[
(set_fixed_point_multiplier, 1000),
(init_position, pos1),
(str_store_string, s1, "@Send to everybody:"),
(create_text_overlay, reg1, s1,tf_with_outline),
(overlay_set_color, reg1, 0xFFFF0000),
(position_set_x, pos1, 200),
(position_set_y, pos1, 530),
(overlay_set_position, reg1, pos1),
(overlay_set_text, reg1, s1),
(position_set_x, pos1, 1000),
(position_set_y, pos1, 1000),
(overlay_set_size, reg1, pos1),
(create_simple_text_box_overlay, "$g_message", tf_center_justify),
(position_set_x, pos1, 200),
(position_set_y, pos1, 500),
(overlay_set_position, "$g_message", pos1),
(position_set_x, pos1, 600),
(position_set_y, pos1, 1000),
(overlay_set_size, "$g_message", pos1),
(overlay_obtain_focus, "$g_message"),
(assign, "$g_waiting_to_sendMessage", 1),
(str_clear, s0),
(overlay_set_text, "$g_message", s0),
(assign,"$g_waiting_for_confirmation_to_terminate", 1),
(presentation_set_duration, 999999),
]),
(ti_on_presentation_event_state_change,
[ (try_begin),
(neq,"$g_waiting_to_sendMessage",1),
(try_begin),
(neg|str_is_empty, s0),
(str_store_string_reg, s1, s0),
(call_script,"script_send_string_to_server",mpcamp_event_chat,1,s1),
(try_end),
(assign, "$g_waiting_for_confirmation_to_terminate", 0),
(presentation_set_duration, 0),
(try_end),
]),
(ti_on_presentation_run,
[
(try_begin),
(key_clicked, key_escape),
(assign, "$g_waiting_for_confirmation_to_terminate", 0),
(presentation_set_duration, 0),
(assign, "$g_waiting_to_sendMessage", 0),
(else_try),
(key_clicked, key_enter),
(assign, "$g_waiting_to_sendMessage", 0),
(try_end),
]),
multiplayer_sync,
]),
Code:
(ti_on_presentation_event_state_change,
[ (try_begin),
(neq,"$g_waiting_to_sendMessage",1),
(try_begin),
(neg|str_is_empty, s0),
(str_store_string_reg, s1, s0),
(call_script,"script_send_string_to_server",mpcamp_event_chat,1,s1),
(try_end),
(assign, "$g_waiting_for_confirmation_to_terminate", 0),
(presentation_set_duration, 0),
(try_end),
]),
The client-server sending is done.
Now the string arrived to the server.
In code.php, we add a new case, case 3. then we check if there is a string (because the cheaty player can use a modified version of the mod)
Code:
if(isset($args[1]))
If everything is ok, we will need to send the username of the player that wants to send the message, and we do it with get_player_username($unique_id) (you can see all the defined function in the readme.txt file)
Now that we got the message, and also the username, we want to send them to each player that is online.So we make a loop that will check every local id
Code:
for($i=1;$i<=10;$i++)
Code:
$u_id = get_unique_id_by_local($i)
then we check if there is an online player at the specified local id(0 = no player)
Code:
if($u_id!=0)
and if everything is ok, then we send the message string and teh username to the client
Code:
send_data_to_player($u_id,[3,$args[1],$username],2);
The server-client sending is done!
Now the message is received by all online players. Next we want to display it in the clients. So we go to "code" script, and we add a new case
Code:
(else_try),
(eq,":event",mpcamp_event_chat),
and then we display the message
Code:
(display_message,"@[{s2}]:{s1}"),
and that's it! that is how the chat function is made...
Hardwired stuffs
-the events register and log in
-"to_send" folder and all contents from it
-the folder "players/0"
-the scripts "send_string_to_server","send_int_to_server","send_data"
-the slots
-all string registers above the string 65. USE ONLY STRINGS WITH INDEX BELOW 65!!!!!!!!all the string above 65 (66 - 127) are HARDWIRED!!!!!!!!
Note: there are more stuffs, but i need to think of them...
Limitations
-supports up to 10 players
-You can't send more than 10 send_str or send_int per 0.1 ingame hour(you can tweak this from module_triggers, but make sure you don't put it too fast, because the game will **** up)
-everything that will pop up(tutorial messages, game menues, presentations, all game windows(inventory, party, character etc) , etc) will lead to desync, and you will need to log in again. Only use presentations, and at the end of them add "multiplayer_sync," to keep everything in sync.
-You can send 31 max strings one time (don't force it...will lead to broke output)
-You can receive 31 max strings(again, don't use too many)
Note: there are much many things...
How sending/receiving works
Every time you use (call_script,"script_send blah blah, it doesen't sends them immediately, but it actually save the contents into a slot(it is is int), or into strings from 66-96, and when the script "send_data" is called , it reads all the slots and all the strings and send them to server. the same thing hapens on the server too, the int/strs are saved into a file in the folder to_send.
-the events register and log in
-"to_send" folder and all contents from it
-the folder "players/0"
-the scripts "send_string_to_server","send_int_to_server","send_data"
-the slots
Code:
slot_to_send_1 =200
slot_to_send_2 =201
slot_to_send_3 =202
slot_to_send_4 =203
slot_to_send_5 =204
slot_to_send_6 =205
slot_to_send_7 =206
slot_to_send_8 =207
slot_to_send_9 =208
slot_to_send_10 =209
slot_nr_arg =210
slot_data_type =211 #1 for int,2 for string
slot_temp =212
slot_event_to_use =213
Note: there are more stuffs, but i need to think of them...
Limitations
-supports up to 10 players
-You can't send more than 10 send_str or send_int per 0.1 ingame hour(you can tweak this from module_triggers, but make sure you don't put it too fast, because the game will **** up)
-everything that will pop up(tutorial messages, game menues, presentations, all game windows(inventory, party, character etc) , etc) will lead to desync, and you will need to log in again. Only use presentations, and at the end of them add "multiplayer_sync," to keep everything in sync.
-You can send 31 max strings one time (don't force it...will lead to broke output)
-You can receive 31 max strings(again, don't use too many)
Note: there are much many things...
How sending/receiving works
Every time you use (call_script,"script_send blah blah, it doesen't sends them immediately, but it actually save the contents into a slot(it is is int), or into strings from 66-96, and when the script "send_data" is called , it reads all the slots and all the strings and send them to server. the same thing hapens on the server too, the int/strs are saved into a file in the folder to_send.
Changelog
v0.1:
-this is the initial version
v0.2:
-fixed server sending invalid messages to client, causing fake events
-changed server sending syntax from "send_data_to_player(<unique_id>,<arguments_number>,<data_array>,[strings_number])" to send_data_to_player(<unique_id>,<data_array>,[strings_number])
-changed client sending syntax from (call_script,"script_send_string_to_server",<event>,<nr_of_strings>), to (call_script,"script_send_string_to_server",<event>,<nr_of_strings>,<first_string>,<second_string>,...),
-inventory and gold are now synced with the server
-added new events like show color text
-added player stats window, by pressing the button TAB
-added ping function
-added FPS counter on the key N (i will add more stuffs on this key)
-added a simple menu window, on key M
-added a simple inventory window
-added two server simple triggers : on_connect , on_deconnect
-added server logs
-added server config file
-added anti-teleport (you can enable or disable from server config; now the player movement is server controlled)
-optimized a little the receiving server part
-this is the initial version
v0.2:
-fixed server sending invalid messages to client, causing fake events
-changed server sending syntax from "send_data_to_player(<unique_id>,<arguments_number>,<data_array>,[strings_number])" to send_data_to_player(<unique_id>,<data_array>,[strings_number])
-changed client sending syntax from (call_script,"script_send_string_to_server",<event>,<nr_of_strings>), to (call_script,"script_send_string_to_server",<event>,<nr_of_strings>,<first_string>,<second_string>,...),
-inventory and gold are now synced with the server
-added new events like show color text
-added player stats window, by pressing the button TAB
-added ping function
-added FPS counter on the key N (i will add more stuffs on this key)
-added a simple menu window, on key M
-added a simple inventory window
-added two server simple triggers : on_connect , on_deconnect
-added server logs
-added server config file
-added anti-teleport (you can enable or disable from server config; now the player movement is server controlled)
-optimized a little the receiving server part
multiplayer campaign mod files download -> HERE .
v0.1: link.
Credits:
*taleworlds for creating warband
*Gotha for indirectly giving me the ideea that multi camp is possible
*MadocComadrin for madmin (i took the chat presentation from there)
What you are not allowed:
it is not allowed to use scripts/part of scripts without giving credits to me
first appearence of this kind of mod was here!
Thread created in 3+ hours.