diff --git a/changelog.txt b/changelog.txt index 7647ea8ec..cde46e646 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,12 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 08/23/2016 == +noudess: Force mobs on a depop @ end pathgrid to still do this on idle zones. +This makes them be more random after a zone is idle, rather than always showing +up at start point when 1st person logs into an idle zone. Much more like live. +I dion't think this will be much of a performance problem. Once they path and +depop, no mkore cpu usage. + == 08/14/2016 == mackal: Implement Linked Spell Reuse Timers - For whatever reason this is a bit unfriendly, but that's how it is on live. diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index a1b614b97..cf411ef72 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -2509,23 +2509,25 @@ struct BookRequest_Struct { */ struct Object_Struct { /*00*/ uint32 linked_list_addr[2];// They are, get this, prev and next, ala linked list -/*08*/ uint16 size; // +/*08*/ float size; // /*10*/ uint16 solidtype; // /*12*/ uint32 drop_id; // Unique object id for zone /*16*/ uint16 zone_id; // Redudant, but: Zone the object appears in /*18*/ uint16 zone_instance; // /*20*/ uint32 unknown020; // /*24*/ uint32 unknown024; // -/*28*/ float heading; // heading -/*32*/ float z; // z coord -/*36*/ float x; // x coord -/*40*/ float y; // y coord -/*44*/ char object_name[32]; // Name of object, usually something like IT63_ACTORDEF -/*76*/ uint32 unknown076; // -/*80*/ uint32 object_type; // Type of object, not directly translated to OP_OpenObject -/*84*/ uint32 unknown084; //set to 0xFF -/*88*/ uint32 spawn_id; // Spawn Id of client interacting with object -/*92*/ +/*28*/ float tilt_x; +/*32*/ float tilt_y; +/*36*/ float heading; // heading +/*40*/ float z; // z coord +/*44*/ float x; // x coord +/*76*/ float y; // y coord +/*80*/ char object_name[32]; // Name of object, usually something like IT63_ACTORDEF +/*84*/ uint32 unknown076; // +/*88*/ uint32 object_type; // Type of object, not directly translated to OP_OpenObject +/*92*/ uint32 unknown084; //set to 0xFF + uint32 spawn_id; // Spawn Id of client interacting with object + }; // 01 = generic drop, 02 = armor, 19 = weapon //[13:40] and 0xff seems to be indicative of the tradeskill/openable items that end up returning the old style item type in the OP_OpenObject diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index 7c5f302cb..8ab38905f 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -987,8 +987,8 @@ namespace RoF VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->drop_id); // Some unique id VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); // Same for all objects in the zone VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->heading); - VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0); // X tilt - VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0); // Y tilt + VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->tilt_x); // X tilt + VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->tilt_y); // Y tilt VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->size != 0 && (float)emu->size < 5000.f ? (float)((float)emu->size / 100.0f) : 1.f ); // This appears to be the size field. Hackish logic because some PEQ DB items were corrupt. VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->y); VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->x); diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index 5bb93f14a..aedd7b592 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -1062,8 +1062,8 @@ namespace RoF2 VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->drop_id); // Some unique id VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); // Same for all objects in the zone VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->heading); - VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0); // X tilt - VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0); // Y tilt + VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->tilt_x); // X tilt + VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->tilt_y); // Y tilt VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->size != 0 && (float)emu->size < 5000.f ? (float)((float)emu->size / 100.0f) : 1.f ); // This appears to be the size field. Hackish logic because some PEQ DB items were corrupt. VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->y); VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->x); diff --git a/common/patches/titanium.cpp b/common/patches/titanium.cpp index cc10f6487..9e93051b1 100644 --- a/common/patches/titanium.cpp +++ b/common/patches/titanium.cpp @@ -595,6 +595,46 @@ namespace Titanium dest->FastQueuePacket(&in, ack_req); } + ENCODE(OP_GroundSpawn) + { + // We are not encoding the spawn_id field here, but it doesn't appear to matter. + // + EQApplicationPacket *in = *p; + *p = nullptr; + + //store away the emu struct + unsigned char *__emu_buffer = in->pBuffer; + Object_Struct *emu = (Object_Struct *)__emu_buffer; + + in->size = strlen(emu->object_name) + sizeof(structs::Object_Struct) - 1; + in->pBuffer = new unsigned char[in->size]; + + structs::Object_Struct *eq = (structs::Object_Struct *) in->pBuffer; + + eq->drop_id = emu->drop_id; + eq->heading = emu->heading; + eq->linked_list_addr[0] = 0; + eq->linked_list_addr[1] = 0; + strcpy(eq->object_name, emu->object_name); + eq->object_type = emu->object_type; + eq->spawn_id = 0; + eq->unknown008[0] = 0; + eq->unknown008[1] = 0; + eq->unknown020 = 0; + eq->unknown024 = 0; + eq->unknown076 = 0; + eq->unknown084 = 0xffffffff; + eq->z = emu->z; + eq->x = emu->x; + eq->y = emu->y; + eq->zone_id = emu->zone_id; + eq->zone_instance = emu->zone_instance; + + + delete[] __emu_buffer; + dest->FastQueuePacket(&in, ack_req); + } + ENCODE(OP_GuildMemberList) { //consume the packet diff --git a/common/patches/titanium_ops.h b/common/patches/titanium_ops.h index 9ca0ba770..5e65dd7c0 100644 --- a/common/patches/titanium_ops.h +++ b/common/patches/titanium_ops.h @@ -40,6 +40,7 @@ E(OP_DzLeaderStatus) E(OP_DzMemberList) E(OP_Emote) E(OP_FormattedMessage) +E(OP_GroundSpawn) E(OP_GuildMemberLevelUpdate) E(OP_GuildMemberList) E(OP_Illusion) diff --git a/common/patches/uf.cpp b/common/patches/uf.cpp index af81fea06..ba5bf7622 100644 --- a/common/patches/uf.cpp +++ b/common/patches/uf.cpp @@ -875,8 +875,8 @@ namespace UF // This next field is actually a float. There is a groundspawn in freeportwest (sack of money sitting on some barrels) which requires this // field to be set to (float)255.0 to appear at all, and also the size field below to be 5, to be the correct size. I think SoD has the same // issue. - VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0); //X tilt - VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0); //Y tilt + VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->tilt_x); //X tilt + VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->tilt_y); //Y tilt VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->size != 0 && (float)emu->size < 5000.f ? (float)((float)emu->size / 100.0f) : 1.f ); // This appears to be the size field. Hackish logic because some PEQ DB items were corrupt. VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->y); VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->x); diff --git a/common/version.h b/common/version.h index 38731b3ba..f06a68c05 100644 --- a/common/version.h +++ b/common/version.h @@ -30,7 +30,7 @@ Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt */ -#define CURRENT_BINARY_DATABASE_VERSION 9097 +#define CURRENT_BINARY_DATABASE_VERSION 9098 #ifdef BOTS #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9008 #else diff --git a/utils/scripts/eqemu_server.pl b/utils/scripts/eqemu_server.pl index 39c2a9fd3..e91df2914 100644 --- a/utils/scripts/eqemu_server.pl +++ b/utils/scripts/eqemu_server.pl @@ -27,6 +27,7 @@ $db_run_stage = 0; #::: Sets database run stage check $console_output .= " Operating System is: $Config{osname}\n"; if($Config{osname}=~/freebsd|linux/i){ $OS = "Linux"; } if($Config{osname}=~/Win|MS/i){ $OS = "Windows"; } +$has_internet_connection = check_internet_connection(); #::: Check for script self update do_self_update_check_routine(); @@ -201,6 +202,8 @@ if($ARGV[0] eq "installer"){ lua_modules_fetch(); fetch_utility_scripts(); + + #::: Database Routines print "[Database] Creating Database '" . $db_name . "'\n"; print `"$path" --host $host --user $user --password="$pass" -N -B -e "DROP DATABASE IF EXISTS $db_name;"`; @@ -241,10 +244,37 @@ if($ARGV[0] eq "login_server_setup"){ exit; } +sub check_internet_connection { + if($OS eq "Linux"){ + $count = "c"; + } + if($OS eq "Windows"){ + $count = "n"; + } + + if (`ping 8.8.8.8 -$count 1 -w 500`=~/Reply from|1 received/i) { + # print "[Update] We have a connection to the internet, continuing...\n"; + return 1; + } + elsif (`ping 4.2.2.2 -$count 1 -w 500`=~/Reply from|1 received/i) { + # print "[Update] We have a connection to the internet, continuing...\n"; + return 1; + } + else{ + print "[Update] No connection to the internet, can't check update\n"; + return; + } +} + sub do_self_update_check_routine { #::: Check Version passed from world to update script - get_remote_file($eqemu_repository_request_url . "utils/scripts/eqemu_server.pl", "updates_staged/eqemu_server.pl", 0, 1); + get_remote_file($eqemu_repository_request_url . "utils/scripts/eqemu_server.pl", "updates_staged/eqemu_server.pl", 0, 1, 1); + if(!$has_internet_connection){ + print "[Update] Cannot check update without internet connection...\n"; + return; + } + if(-e "updates_staged/eqemu_server.pl") { my $remote_script_size = -s "updates_staged/eqemu_server.pl"; @@ -285,7 +315,12 @@ sub do_self_update_check_routine { sub get_installation_variables{ #::: Fetch installation variables before building the config - open (INSTALL_VARS, "../install_variables.txt"); + if($OS eq "Linux"){ + open (INSTALL_VARS, "../install_variables.txt"); + } + if($OS eq "Windows"){ + open (INSTALL_VARS, "install_variables.txt"); + } while (){ chomp; $o = $_; @@ -412,14 +447,14 @@ sub show_menu_prompt { print " [lua_modules] Download latest lua_modules\n"; print " [utility_scripts] Download utility scripts to run and operate the EQEmu Server\n"; if($OS eq "Windows"){ - print "--- Windows\n"; - print " windows_server_download Updates server code from latest stable\n"; - print " windows_server_download_bots Updates server code (bots enabled) from latest\n"; - print " fetch_dlls Grabs dll's needed to run windows binaries\n"; - print " setup_loginserver Sets up loginserver for Windows\n"; + print ">>> Windows\n"; + print " [windows_server_download] Updates server code from latest stable\n"; + print " [windows_server_download_bots] Updates server code (bots enabled) from latest\n"; + print " [fetch_dlls] Grabs dll's needed to run windows binaries\n"; + print " [setup_loginserver] Sets up loginserver for Windows\n"; } print " \n> main - go back to main menu\n"; - print "Enter a command #> "; + print "Enter a command #> "; $last_menu = trim($input); } elsif($input eq "backup_database"){ database_dump(); $dc = 1; } @@ -560,6 +595,12 @@ sub get_remote_file{ my $destination_file = $_[1]; my $content_type = $_[2]; my $no_retry = $_[3]; + my $silent_download = $_[4]; + + if(!$has_internet_connection){ + print "[Download] Cannot download without internet connection...\n"; + return; + } #::: Build file path of the destination file so that we may check for the folder's existence and make it if necessary @@ -600,7 +641,7 @@ sub get_remote_file{ #::: Make sure the file exists before continuing... if(-e $destination_file) { $break = 1; - print "[Download] Saved: (" . $destination_file . ") from " . $request_url . "\n"; + print "[Download] Saved: (" . $destination_file . ") from " . $request_url . "\n" if !$silent_download; } else { $break = 0; } usleep(500); @@ -613,7 +654,7 @@ sub get_remote_file{ $break = 0; while($break == 0) { require LWP::UserAgent; - my $ua = LWP::UserAgent->new; + my $ua = LWP::UserAgent->new; $ua->timeout(10); $ua->env_proxy; my $response = $ua->get($request_url); @@ -627,7 +668,7 @@ sub get_remote_file{ } if(-e $destination_file) { $break = 1; - print "[Download] Saved: (" . $destination_file . ") from " . $request_url . "\n"; + print "[Download] Saved: (" . $destination_file . ") from " . $request_url . "\n" if !$silent_download; } else { $break = 0; } usleep(500); @@ -640,7 +681,7 @@ sub get_remote_file{ if($OS eq "Linux"){ #::: wget -O db_update/db_update_manifest.txt https://raw.githubusercontent.com/EQEmu/Server/master/utils/sql/db_update_manifest.txt $wget = `wget --no-check-certificate --quiet -O $destination_file $request_url`; - print "[Download] Saved: (" . $destination_file . ") from " . $request_url . "\n"; + print "[Download] Saved: (" . $destination_file . ") from " . $request_url . "\n" if !$silent_download; if($wget=~/unable to resolve/i){ print "Error, no connection or failed request...\n\n"; #die; @@ -1736,4 +1777,4 @@ sub generate_random_password { map $alphanumeric[rand @alphanumeric], 0..$passwordsize; return $randpassword; -} \ No newline at end of file +} diff --git a/utils/scripts/eqemu_update.pl b/utils/scripts/eqemu_update.pl index a7da3c792..e794a3710 100644 --- a/utils/scripts/eqemu_update.pl +++ b/utils/scripts/eqemu_update.pl @@ -1,74 +1,56 @@ #!/usr/bin/perl ########################################################### -#::: Automatic (Database) Upgrade Script -#::: Author: Akkadius +#::: General EQEmu Server Administration Script +#::: Purpose - Handles: +#::: Automatic database versioning (bots and normal DB) +#::: Updating server assets (binary, opcodes, maps, configuration files) +#::: Original Author: Akkadius +#::: Contributors: Uleat #::: Purpose: To upgrade databases with ease and maintain versioning ########################################################### -$menu_displayed = 0; - use Config; use File::Copy qw(copy); use POSIX qw(strftime); use File::Path; use File::Find; -use URI::Escape; -use Time::HiRes qw(usleep); +use Time::HiRes qw(usleep); +#::: Variables +$install_repository_request_url = "https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/"; +$eqemu_repository_request_url = "https://raw.githubusercontent.com/EQEmu/Server/master/"; + +#::: Globals $time_stamp = strftime('%m-%d-%Y', gmtime()); - +$db_run_stage = 0; #::: Sets database run stage check $console_output .= " Operating System is: $Config{osname}\n"; if($Config{osname}=~/freebsd|linux/i){ $OS = "Linux"; } if($Config{osname}=~/Win|MS/i){ $OS = "Windows"; } +$has_internet_connection = check_internet_connection(); -#::: If current version is less than what world is reporting, then download a new one... -$current_version = 14; +#::: Check for script self update +do_self_update_check_routine(); -if($ARGV[0] eq "V"){ - if($ARGV[1] > $current_version){ - print "eqemu_update.pl Automatic Database Upgrade Needs updating...\n"; - print " Current version: " . $current_version . "\n"; - print " New version: " . $ARGV[1] . "\n"; - get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/eqemu_update.pl", "eqemu_update.pl"); - exit; - } - else{ - print "[Upgrade Script] No script update necessary \n"; - } - exit; -} - -#::: Sets database run stage check -$db_run_stage = 0; +print "[Info] For EQEmu Server management utilities - run eqemu_server.pl\n"; +#::: Check Perl version $perl_version = $^V; $perl_version =~s/v//g; -print "Perl Version is " . $perl_version . "\n"; -if($perl_version > 5.12){ no warnings 'uninitialized'; } +print "[Update] Perl Version is " . $perl_version . "\n"; +if($perl_version > 5.12){ + no warnings 'uninitialized'; +} no warnings; +#::: Remove old eqemu_update.pl +if(-e "eqemu_update.pl"){ + unlink("eqemu_update.pl"); +} + ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(); -my $confile = "eqemu_config.xml"; #default -open(F, "<$confile"); -my $indb = 0; -while() { - s/\r//g; - if(//i) { $indb = 1; } - next unless($indb == 1); - if(/<\/database>/i) { $indb = 0; last; } - if(/(.*)<\/host>/i) { $host = $1; } - elsif(/(.*)<\/username>/i) { $user = $1; } - elsif(/(.*)<\/password>/i) { $pass = $1; } - elsif(/(.*)<\/db>/i) { $db = $1; } -} - -$console_output = -"============================================================ - EQEmu: Automatic Upgrade Check -============================================================ -"; +read_eqemu_config_xml(); if($OS eq "Windows"){ $has_mysql_path = `echo %PATH%`; @@ -81,9 +63,6 @@ if($OS eq "Windows"){ last; } } - $console_output .= " (Windows) MySQL is in system path \n"; - $console_output .= " Path = " . $path . "\n"; - $console_output .= "============================================================\n"; } } @@ -91,101 +70,14 @@ if($OS eq "Windows"){ if($OS eq "Linux"){ $path = `which mysql`; if ($path eq "") { - $path = `which mariadb`; + $path = `which mariadb`; } $path =~s/\n//g; - - $console_output .= " (Linux) MySQL is in system path \n"; - $console_output .= " Path = " . $path . "\n"; - $console_output .= "============================================================\n"; } #::: Path not found, error and exit if($path eq ""){ - print "MySQL path not found, please add the path for automatic database upgrading to continue... \n\n"; - print "script_exiting...\n"; - exit; -} - -if($ARGV[0] eq "install_peq_db"){ - - $db_name = "peq"; - if($ARGV[1]){ - $db_name = $ARGV[1]; - } - - $db = $db_name; - - #::: Database Routines - print "MariaDB :: Creating Database '" . $db_name . "'\n"; - print `"$path" --host $host --user $user --password="$pass" -N -B -e "DROP DATABASE IF EXISTS $db_name;"`; - print `"$path" --host $host --user $user --password="$pass" -N -B -e "CREATE DATABASE $db_name"`; - if($OS eq "Windows"){ @db_version = split(': ', `world db_version`); } - if($OS eq "Linux"){ @db_version = split(': ', `./world db_version`); } - $bin_db_ver = trim($db_version[1]); - check_db_version_table(); - $local_db_ver = trim(get_mysql_result("SELECT version FROM db_version LIMIT 1")); - fetch_peq_db_full(); - print "\nFetching Latest Database Updates...\n"; - main_db_management(); - print "\nApplying Latest Database Updates...\n"; - main_db_management(); - - print get_mysql_result("UPDATE `launcher` SET `dynamics` = 30 WHERE `name` = 'zone'"); -} - -if($ARGV[0] eq "remove_duplicate_rules"){ - remove_duplicate_rule_values(); - exit; -} - -if($ARGV[0] eq "installer"){ - print "Running EQEmu Server installer routines...\n"; - mkdir('logs'); - mkdir('updates_staged'); - mkdir('shared'); - fetch_latest_windows_binaries(); - map_files_fetch_bulk(); - opcodes_fetch(); - plugins_fetch(); - quest_files_fetch(); - lua_modules_fetch(); - - #::: Binary dll's - get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/lua51.dll", "lua51.dll", 1); - get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/zlib1.dll", "zlib1.dll", 1); - get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/libmysql.dll", "libmysql.dll", 1); - - #::: Server scripts - fetch_utility_scripts(); - - #::: Database Routines - print "MariaDB :: Creating Database 'peq'\n"; - print `"$path" --host $host --user $user --password="$pass" -N -B -e "DROP DATABASE IF EXISTS peq;"`; - print `"$path" --host $host --user $user --password="$pass" -N -B -e "CREATE DATABASE peq"`; - if($OS eq "Windows"){ @db_version = split(': ', `world db_version`); } - if($OS eq "Linux"){ @db_version = split(': ', `./world db_version`); } - $bin_db_ver = trim($db_version[1]); - check_db_version_table(); - $local_db_ver = trim(get_mysql_result("SELECT version FROM db_version LIMIT 1")); - fetch_peq_db_full(); - print "\nFetching Latest Database Updates...\n"; - main_db_management(); - print "\nApplying Latest Database Updates...\n"; - main_db_management(); - - print get_mysql_result("UPDATE `launcher` SET `dynamics` = 30 WHERE `name` = 'zone'"); - - if($OS eq "Windows"){ - check_windows_firewall_rules(); - do_windows_login_server_setup(); - } - exit; -} - -if($ARGV[0] eq "db_dump_compress"){ database_dump_compress(); exit; } -if($ARGV[0] eq "login_server_setup"){ - do_windows_login_server_setup(); + print "[Error:eqemu_server.pl] MySQL path not found, please add the path for automatic database upgrading to continue... \n\n"; exit; } @@ -195,7 +87,7 @@ mkdir('db_update'); #::: Check if db_version table exists... if(trim(get_mysql_result("SHOW COLUMNS FROM db_version LIKE 'Revision'")) ne "" && $db){ print get_mysql_result("DROP TABLE db_version"); - print "Old db_version table present, dropping...\n\n"; + print "[Database] Old db_version table present, dropping...\n\n"; } sub check_db_version_table{ @@ -205,7 +97,7 @@ sub check_db_version_table{ version int(11) DEFAULT '0' ) ENGINE=InnoDB DEFAULT CHARSET=latin1; INSERT INTO db_version (version) VALUES ('1000');"); - print "Table 'db_version' does not exists.... Creating...\n\n"; + print "[Database] Table 'db_version' does not exists.... Creating...\n\n"; } } @@ -218,173 +110,406 @@ $bin_db_ver = trim($db_version[1]); $local_db_ver = trim(get_mysql_result("SELECT version FROM db_version LIMIT 1")); #::: If ran from Linux startup script, supress output -if($bin_db_ver == $local_db_ver && $ARGV[0] eq "ran_from_start"){ - print "Database up to date...\n"; +if($bin_db_ver == $local_db_ver && $ARGV[0] eq "ran_from_world"){ + print "[Update] Database up to date...\n"; exit; } -else{ - print $console_output if $db; +else { + + #::: We ran world - Database needs to update, lets backup and run updates and continue world bootup + if($local_db_ver < $bin_db_ver && $ARGV[0] eq "ran_from_world"){ + print "[Update] Database not up to date with binaries... Automatically updating...\n"; + print "[Update] Issuing database backup first...\n"; + database_dump_compress(); + print "[Update] Updating database...\n"; + sleep(1); + main_db_management(); + main_db_management(); + print "[Update] Continuing bootup\n"; + exit; + } + + #::: Make sure that we didn't pass any arugments to the script + if(!$ARGV[0]){ + if(!$db){ print "[eqemu_server.pl] No database connection found... Running without\n"; } + show_menu_prompt(); + } } if($db){ - print " Binary Revision / Local: (" . $bin_db_ver . " / " . $local_db_ver . ")\n"; + print "[Update] MySQL Path/Location: " . $path . "\n"; + print "[Update] Binary Revision / Local: (" . $bin_db_ver . " / " . $local_db_ver . ")\n"; #::: Bots #::: Make sure we're running a bots binary to begin with if(trim($db_version[2]) > 0){ $bots_local_db_version = get_bots_db_version(); if($bots_local_db_version > 0){ - print " (Bots) Binary Revision / Local: (" . trim($db_version[2]) . " / " . $bots_local_db_version . ")\n"; + print "[Update] (Bots) Binary Revision / Local: (" . trim($db_version[2]) . " / " . $bots_local_db_version . ")\n"; } } - #::: If World ran this script, and our version is up to date, continue... + #::: If World ran this script, and our version is up to date, continue... if($bin_db_ver <= $local_db_ver && $ARGV[0] eq "ran_from_world"){ - print " Database up to Date: Continuing World Bootup...\n"; - print "============================================================\n"; + print "[Update] Database up to Date: Continuing World Bootup...\n"; exit; } +} +if($ARGV[0] eq "remove_duplicate_rules"){ + remove_duplicate_rule_values(); + exit; } -if($local_db_ver < $bin_db_ver && $ARGV[0] eq "ran_from_world"){ - print "You have missing database updates, type 1 or 2 to backup your database before running them as recommended...\n\n"; - #::: Display Menu - show_menu_prompt(); -} -else{ - #::: Most likely ran standalone - print "\n"; - show_menu_prompt(); +if($ARGV[0] eq "map_files_fetch_bulk"){ + map_files_fetch_bulk(); + exit; } -sub do_update_self{ - get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/eqemu_update.pl", "eqemu_update.pl"); - die "Rerun eqemu_update.pl"; +if($ARGV[0] eq "loginserver_install_linux"){ + do_linux_login_server_setup(); + exit; +} + +if($ARGV[0] eq "installer"){ + print "[Install] Running EQEmu Server installer routines...\n"; + + #::: Make some local server directories... + mkdir('logs'); + mkdir('updates_staged'); + mkdir('shared'); + + do_install_config_xml(); + read_eqemu_config_xml(); + get_installation_variables(); + + $db_name = "peq"; + if($installation_variables{"mysql_eqemu_db_name"}){ + $db_name = $installation_variables{"mysql_eqemu_db_name"}; + } + + #::: Download assets + if($OS eq "Windows"){ + fetch_latest_windows_binaries(); + get_remote_file($install_repository_request_url . "lua51.dll", "lua51.dll", 1); + get_remote_file($install_repository_request_url . "zlib1.dll", "zlib1.dll", 1); + get_remote_file($install_repository_request_url . "libmysql.dll", "libmysql.dll", 1); + } + map_files_fetch_bulk(); + opcodes_fetch(); + plugins_fetch(); + quest_files_fetch(); + lua_modules_fetch(); + fetch_utility_scripts(); + + #::: Database Routines + print "[Database] Creating Database '" . $db_name . "'\n"; + print `"$path" --host $host --user $user --password="$pass" -N -B -e "DROP DATABASE IF EXISTS $db_name;"`; + print `"$path" --host $host --user $user --password="$pass" -N -B -e "CREATE DATABASE $db_name"`; + + #::: Get Binary DB version + if($OS eq "Windows"){ @db_version = split(': ', `world db_version`); } + if($OS eq "Linux"){ @db_version = split(': ', `./world db_version`); } + $bin_db_ver = trim($db_version[1]); + + #::: Local DB Version + check_db_version_table(); + $local_db_ver = trim(get_mysql_result("SELECT version FROM db_version LIMIT 1")); + + #::: Download PEQ latest + fetch_peq_db_full(); + print "[Database] Fetching Latest Database Updates...\n"; + main_db_management(); + print "[Database] Applying Latest Database Updates...\n"; + main_db_management(); + + if($OS eq "Windows"){ + check_windows_firewall_rules(); + do_windows_login_server_setup(); + } + if($OS eq "Linux"){ + do_linux_login_server_setup(); + + print "[Install] Installation complete!\n"; + } + + exit; +} + +if($ARGV[0] eq "db_dump_compress"){ database_dump_compress(); exit; } +if($ARGV[0] eq "login_server_setup"){ + do_windows_login_server_setup(); + exit; +} + +sub check_internet_connection { + if($OS eq "Linux"){ + $count = "c"; + } + if($OS eq "Windows"){ + $count = "n"; + } + + if (`ping 8.8.8.8 -$count 1 -w 500`=~/Reply from|1 received/i) { + # print "[Update] We have a connection to the internet, continuing...\n"; + return 1; + } + elsif (`ping 4.2.2.2 -$count 1 -w 500`=~/Reply from|1 received/i) { + # print "[Update] We have a connection to the internet, continuing...\n"; + return 1; + } + else{ + print "[Update] No connection to the internet, can't check update\n"; + return; + } +} + +sub do_self_update_check_routine { + #::: Check Version passed from world to update script + get_remote_file($eqemu_repository_request_url . "utils/scripts/eqemu_server.pl", "updates_staged/eqemu_server.pl", 0, 1, 1); + + if(!$has_internet_connection){ + print "[Update] Cannot check update without internet connection...\n"; + return; + } + + if(-e "updates_staged/eqemu_server.pl") { + + my $remote_script_size = -s "updates_staged/eqemu_server.pl"; + my $local_script_size = -s "eqemu_server.pl"; + + if($remote_script_size != $local_script_size){ + print "[Update] Script has been updated, updating...\n"; + + my @files; + my $start_dir = "updates_staged/"; + find( + sub { push @files, $File::Find::name unless -d; }, + $start_dir + ); + for my $file (@files) { + if($file=~/eqemu_server/i){ + $destination_file = $file; + $destination_file =~s/updates_staged\///g; + print "[Install] Installing :: " . $destination_file . "\n"; + unlink($destination_file); + copy_file($file, $destination_file); + if($OS eq "Linux"){ + system("chmod 755 eqemu_server.pl"); + system("chown eqemu eqemu_server.pl"); + } + system("perl eqemu_server.pl start_from_world"); + } + } + print "[Install] Done\n"; + } + else { + print "[Update] No script update necessary...\n"; + } + + unlink("updates_staged/eqemu_server.pl"); + } +} + +sub get_installation_variables{ + #::: Fetch installation variables before building the config + open (INSTALL_VARS, "../install_variables.txt"); + while (){ + chomp; + $o = $_; + @data = split(":", $o); + $installation_variables{trim($data[0])} = trim($data[1]); + } + close (INSTALL_VARS); +} + +sub do_install_config_xml { + get_installation_variables(); + + #::: Fetch XML template + get_remote_file($install_repository_request_url . "eqemu_config.xml", "eqemu_config_template.xml"); + + #::: Open new config file + open (NEW_CONFIG, '>', 'eqemu_config.xml'); + + $in_database_tag = 0; + + #::: Iterate through template and replace variables... + open (FILE_TEMPLATE, "eqemu_config_template.xml"); + while (){ + chomp; + $o = $_; + + #::: Find replace variables + + if($o=~/\<\!--/i){ + next; + } + + if($o=~/database/i && $o=~/\<\//i){ + $in_database_tag = 0; + } + if($o=~/database/i){ + $in_database_tag = 1; + } + + if($o=~/key/i){ + my($replace_key) = $o =~ />(\w+)/i && $in_database_tag){ + my($replace_username) = $o =~ />(\w+)/i && $in_database_tag){ + my($replace_password) = $o =~ />(\w+)/i){ + my($replace_db_name) = $o =~ />(\w+) \&database_dump, - 2 => \&database_dump_compress, - 3 => \&main_db_management, - 4 => \&bots_db_management, - 5 => \&opcodes_fetch, - 6 => \&map_files_fetch, - 7 => \&plugins_fetch, - 8 => \&quest_files_fetch, - 9 => \&lua_modules_fetch, - 10 => \&aa_fetch, - 11 => \&fetch_latest_windows_binaries, - 12 => \&fetch_server_dlls, - 13 => \&do_windows_login_server_setup, - 14 => \&remove_duplicate_rule_values, - 15 => \&fetch_utility_scripts, - 18 => \&fetch_latest_windows_binaries_bots, - 19 => \&do_bots_db_schema_drop, - 20 => \&do_update_self, - 21 => \&database_dump_player_tables, - 0 => \&script_exit, - ); - while (1) { - { - local $| = 1; - if(!$menu_show && ($ARGV[0] eq "ran_from_world" || $ARGV[0] eq "ran_from_start")){ - $menu_show++; - next; - } - print menu_options(), '> '; - $menu_displayed++; - if($menu_displayed > 50){ - print "Safety: Menu looping too many times, exiting...\n"; - exit; - } + $dc = 0; + while (1) { + $input = trim($input); + + $errored_command = 0; + + if($input eq "database"){ + print "\n>>> Database Menu\n\n"; + print " [backup_database] Back up database to backups/ directory\n"; + print " [backup_player_tables] Back up player tables to backups/ directory\n"; + print " [backup_database_compressed] Back up database compressed to backups/ directory\n"; + print " \n"; + print " [check_db_updates] Checks for database updates manually\n"; + print " [check_bot_db_updates] Checks for bot database updates\n"; + print " \n"; + print " [aa_tables] Downloads and installs clean slate AA data from PEQ\n"; + print " [remove_duplicate_rules] Removes duplicate rules from rule_values table\n"; + print " [drop_bots_db_schema] Removes bot database schema\n"; + + print " \n> main - go back to main menu\n"; + print "Enter a command #> "; + $last_menu = trim($input); } - - my $choice = <>; - - $choice =~ s/\A\s+//; - $choice =~ s/\s+\z//; - - if (defined(my $handler = $dispatch{$choice})) { - my $result = $handler->(); - unless (defined $result) { - exit 0; + elsif($input eq "assets"){ + print "\n>>> Server Assets Menu\n\n"; + print " [maps] Download latest maps\n"; + print " [opcodes] Download opcodes (Patches for eq clients)\n"; + print " [quests] Download latest quests\n"; + print " [plugins] Download latest plugins\n"; + print " [lua_modules] Download latest lua_modules\n"; + print " [utility_scripts] Download utility scripts to run and operate the EQEmu Server\n"; + if($OS eq "Windows"){ + print "--- Windows\n"; + print " windows_server_download Updates server code from latest stable\n"; + print " windows_server_download_bots Updates server code (bots enabled) from latest\n"; + print " fetch_dlls Grabs dll's needed to run windows binaries\n"; + print " setup_loginserver Sets up loginserver for Windows\n"; } + print " \n> main - go back to main menu\n"; + print "Enter a command #> "; + $last_menu = trim($input); + } + elsif($input eq "backup_database"){ database_dump(); $dc = 1; } + elsif($input eq "backup_player_tables"){ database_dump_player_tables(); $dc = 1; } + elsif($input eq "backup_database_compressed"){ database_dump_compress(); $dc = 1; } + elsif($input eq "drop_bots_db_schema"){ do_bots_db_schema_drop(); $dc = 1; } + elsif($input eq "aa_tables"){ aa_fetch(); $dc = 1; } + elsif($input eq "remove_duplicate_rules"){ remove_duplicate_rule_values(); $dc = 1; } + elsif($input eq "maps"){ map_files_fetch_bulk(); $dc = 1; } + elsif($input eq "opcodes"){ opcodes_fetch(); $dc = 1; } + elsif($input eq "plugins"){ plugins_fetch(); $dc = 1; } + elsif($input eq "quests"){ quest_files_fetch(); $dc = 1; } + elsif($input eq "lua_modules"){ lua_modules_fetch(); $dc = 1; } + elsif($input eq "windows_server_download"){ fetch_latest_windows_binaries(); $dc = 1; } + elsif($input eq "windows_server_download_bots"){ fetch_latest_windows_binaries_bots(); $dc = 1; } + elsif($input eq "fetch_dlls"){ fetch_server_dlls(); $dc = 1; } + elsif($input eq "utility_scripts"){ fetch_utility_scripts(); $dc = 1; } + elsif($input eq "check_db_updates"){ main_db_management(); $dc = 1; } + elsif($input eq "check_bot_db_updates"){ bots_db_management(); $dc = 1; } + elsif($input eq "setup_loginserver"){ do_windows_login_server_setup(); $dc = 1; } + elsif($input eq "exit"){ + exit; + } + elsif($input eq "main"){ + print "Returning to main menu...\n"; + print_main_menu(); + $last_menu = trim($input); + } + elsif($input eq "" && $last_menu ne ""){ + $errored_command = 1; + } + elsif($input ne ""){ + print "Invalid command '" . $input . "'\n"; + $errored_command = 1; } else { - if($ARGV[0] ne "ran_from_world"){ - # warn "\n\nInvalid selection\n\n"; - } + print_main_menu(); + } + + #::: Errored command checking + if($errored_command == 1){ + $input = $last_menu; + } + elsif($dc == 1){ + $dc = 0; + $input = ""; + } + else { + $input = <>; } } } -sub menu_options { - if(@total_updates){ - if($bots_db_management == 1){ - $option[3] = "Check and stage pending REQUIRED Database updates"; - $bots_management = "Run pending REQUIRED updates... (" . scalar (@total_updates) . ")"; - } - else{ - $option[3] = "Run pending REQUIRED updates... (" . scalar (@total_updates) . ")"; - if(get_mysql_result("SHOW TABLES LIKE 'bots'") eq ""){ - $bots_management = "Install bots database pre-requisites (Requires bots server binaries)"; - } - else{ - $bots_management = "Check for Bot pending REQUIRED database updates... (Must have bots enabled)"; - } - } - } - else{ - $option[3] = "Check and stage pending REQUIRED Database updates"; - $bots_management = "Check for Bot REQUIRED database updates... (Must have bots enabled)"; - } - -return <>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"; + print ">>> EQEmu Server Main Menu >>>>>>>>>>>>\n"; + print ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n\n"; + print " [database] Enter database management menu \n"; + print " [assets] Manage server assets \n\n"; + print " exit \n"; + print "\n"; + print "Enter a command #> "; } sub check_for_database_dump_script{ @@ -392,25 +517,21 @@ sub check_for_database_dump_script{ return; } else{ - print "db_dumper.pl not found... retrieving...\n\n"; - get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/db_dumper.pl", "db_dumper.pl"); + print "[Database] db_dumper.pl not found... retrieving...\n"; + get_remote_file($eqemu_repository_request_url . "utils/scripts/db_dumper.pl", "db_dumper.pl"); } } -sub ran_from_world { - print "Running from world...\n"; -} - sub database_dump { check_for_database_dump_script(); - print "Performing database backup....\n"; + print "[Database] Performing database backup....\n"; print `perl db_dumper.pl database="$db" loc="backups"`; } sub database_dump_player_tables { check_for_database_dump_script(); - print "Performing database backup of player tables....\n"; - get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/master/utils/sql/character_table_list.txt", "backups/character_table_list.txt"); + print "[Database] Performing database backup of player tables....\n"; + get_remote_file($eqemu_repository_request_url . "utils/sql/character_table_list.txt", "backups/character_table_list.txt"); $tables = ""; open (FILE, "backups/character_table_list.txt"); @@ -424,7 +545,7 @@ sub database_dump_player_tables { print `perl db_dumper.pl database="$db" loc="backups" tables="$tables" backup_name="player_tables_export" nolock`; - print "\nPress any key to continue...\n"; + print "[Database] Press any key to continue...\n"; <>; #Read from STDIN @@ -432,7 +553,7 @@ sub database_dump_player_tables { sub database_dump_compress { check_for_database_dump_script(); - print "Performing database backup....\n"; + print "[Database] Performing database backup....\n"; print `perl db_dumper.pl database="$db" loc="backups" compress`; } @@ -460,30 +581,40 @@ sub get_mysql_result_from_file{ if($OS eq "Linux"){ return `"$path" --host $host --user $user --password="$pass" --force $db < $update_file`; } } -#::: Gets Remote File based on URL (1st Arg), and saves to destination file (2nd Arg) -#::: Example: get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/master/utils/sql/db_update_manifest.txt", "db_update/db_update_manifest.txt"); +#::: Gets Remote File based on request_url (1st Arg), and saves to destination file (2nd Arg) +#::: Example: get_remote_file($eqemu_repository_request_url . "utils/sql/db_update_manifest.txt", "db_update/db_update_manifest.txt"); sub get_remote_file{ - my $URL = $_[0]; - my $Dest_File = $_[1]; + my $request_url = $_[0]; + my $destination_file = $_[1]; my $content_type = $_[2]; + my $no_retry = $_[3]; + my $silent_download = $_[4]; + + if(!$has_internet_connection){ + print "[Download] Cannot download without internet connection...\n"; + return; + } #::: Build file path of the destination file so that we may check for the folder's existence and make it if necessary - if($Dest_File=~/\//i){ - my @dir_path = split('/', $Dest_File); + + if($destination_file=~/\//i){ + my @directory_path = split('/', $destination_file); $build_path = ""; - $di = 0; - while($dir_path[$di]){ - $build_path .= $dir_path[$di] . "/"; + $directory_index = 0; + while($directory_path[$directory_index] && $directory_path[$directory_index + 1]){ + $build_path .= $directory_path[$directory_index] . "/"; + # print "checking '" . $build_path . "'\n"; #::: If path does not exist, create the directory... - if (!-d $build_path) { + if (!-d $build_path) { + print "[Copy] folder doesn't exist, creating '" . $build_path . "'\n"; mkdir($build_path); } - if(!$dir_path[$di + 2] && $dir_path[$di + 1]){ + if(!$directory_indexr_path[$directory_index + 2] && $directory_indexr_path[$directory_index + 1]){ # print $actual_path . "\n"; $actual_path = $build_path; last; } - $di++; + $directory_index++; } } @@ -492,51 +623,59 @@ sub get_remote_file{ if($content_type == 1){ $break = 0; while($break == 0) { - use LWP::Simple qw(getstore); - if(!getstore($URL, $Dest_File)){ - # print "Error, no connection or failed request...\n\n"; + eval "use LWP::Simple qw(getstore);"; + # use LWP::Simple qw(getstore); + # print "request is " . $request_url . "\n"; + # print "destination file is supposed to be " . $destination_file . "\n"; + if(!getstore($request_url, $destination_file)){ + print "[Download] Error, no connection or failed request...\n\n"; } # sleep(1); #::: Make sure the file exists before continuing... - if(-e $Dest_File) { + if(-e $destination_file) { $break = 1; - print " [URL] :: " . $URL . "\n"; - print " [Saved] :: " . $Dest_File . "\n"; + print "[Download] Saved: (" . $destination_file . ") from " . $request_url . "\n" if !$silent_download; } else { $break = 0; } usleep(500); + + if($no_retry){ + $break = 1; + } } } else{ $break = 0; while($break == 0) { require LWP::UserAgent; - my $ua = LWP::UserAgent->new; + my $ua = LWP::UserAgent->new; $ua->timeout(10); $ua->env_proxy; - my $response = $ua->get($URL); + my $response = $ua->get($request_url); if ($response->is_success){ - open (FILE, '> ' . $Dest_File . ''); + open (FILE, '> ' . $destination_file . ''); print FILE $response->decoded_content; close (FILE); } else { - # print "Error, no connection or failed request...\n\n"; + print "[Download] Error, no connection or failed request...\n\n"; } - if(-e $Dest_File) { + if(-e $destination_file) { $break = 1; - print " [URL] :: " . $URL . "\n"; - print " [Saved] :: " . $Dest_File . "\n"; + print "[Download] Saved: (" . $destination_file . ") from " . $request_url . "\n" if !$silent_download; } else { $break = 0; } usleep(500); + + if($no_retry){ + $break = 1; + } } } } if($OS eq "Linux"){ #::: wget -O db_update/db_update_manifest.txt https://raw.githubusercontent.com/EQEmu/Server/master/utils/sql/db_update_manifest.txt - $wget = `wget --no-check-certificate --quiet -O $Dest_File $URL`; - print " o URL: (" . $URL . ")\n"; - print " o Saved: (" . $Dest_File . ") \n"; - if($wget=~/unable to resolve/i){ + $wget = `wget --no-check-certificate --quiet -O $destination_file $request_url`; + print "[Download] Saved: (" . $destination_file . ") from " . $request_url . "\n" if !$silent_download; + if($wget=~/unable to resolve/i){ print "Error, no connection or failed request...\n\n"; #die; } @@ -551,6 +690,22 @@ sub trim { return $string; } +sub read_eqemu_config_xml { + my $confile = "eqemu_config.xml"; #default + open(F, "<$confile"); + my $indb = 0; + while() { + s/\r//g; + if(//i) { $indb = 1; } + next unless($indb == 1); + if(/<\/database>/i) { $indb = 0; last; } + if(/(.*)<\/host>/i) { $host = $1; } + elsif(/(.*)<\/username>/i) { $user = $1; } + elsif(/(.*)<\/password>/i) { $pass = $1; } + elsif(/(.*)<\/db>/i) { $db = $1; } + } +} + #::: Fetch Latest PEQ AA's sub aa_fetch{ if(!$db){ @@ -558,48 +713,48 @@ sub aa_fetch{ return; } - print "Pulling down PEQ AA Tables...\n"; - get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/master/utils/sql/peq_aa_tables_post_rework.sql", "db_update/peq_aa_tables_post_rework.sql"); - print "\n\nInstalling AA Tables...\n"; + print "[Install] Pulling down PEQ AA Tables...\n"; + get_remote_file($eqemu_repository_request_url . "utils/sql/peq_aa_tables_post_rework.sql", "db_update/peq_aa_tables_post_rework.sql"); + print "[Install] Installing AA Tables...\n"; print get_mysql_result_from_file("db_update/peq_aa_tables_post_rework.sql"); - print "\nDone...\n\n"; + print "[Install] Done...\n\n"; } #::: Fetch Latest Opcodes sub opcodes_fetch{ - print "Pulling down latest opcodes...\n"; + print "[Update] Pulling down latest opcodes...\n"; %opcodes = ( - 1 => ["opcodes", "https://raw.githubusercontent.com/EQEmu/Server/master/utils/patches/opcodes.conf"], - 2 => ["mail_opcodes", "https://raw.githubusercontent.com/EQEmu/Server/master/utils/patches/mail_opcodes.conf"], - 3 => ["Titanium", "https://raw.githubusercontent.com/EQEmu/Server/master/utils/patches/patch_Titanium.conf"], - 4 => ["Secrets of Faydwer", "https://raw.githubusercontent.com/EQEmu/Server/master/utils/patches/patch_SoF.conf"], - 5 => ["Seeds of Destruction", "https://raw.githubusercontent.com/EQEmu/Server/master/utils/patches/patch_SoD.conf"], - 6 => ["Underfoot", "https://raw.githubusercontent.com/EQEmu/Server/master/utils/patches/patch_UF.conf"], - 7 => ["Rain of Fear", "https://raw.githubusercontent.com/EQEmu/Server/master/utils/patches/patch_RoF.conf"], - 8 => ["Rain of Fear 2", "https://raw.githubusercontent.com/EQEmu/Server/master/utils/patches/patch_RoF2.conf"], + 1 => ["opcodes", $eqemu_repository_request_url . "utils/patches/opcodes.conf"], + 2 => ["mail_opcodes", $eqemu_repository_request_url . "utils/patches/mail_opcodes.conf"], + 3 => ["Titanium", $eqemu_repository_request_url . "utils/patches/patch_Titanium.conf"], + 4 => ["Secrets of Faydwer", $eqemu_repository_request_url . "utils/patches/patch_SoF.conf"], + 5 => ["Seeds of Destruction", $eqemu_repository_request_url . "utils/patches/patch_SoD.conf"], + 6 => ["Underfoot", $eqemu_repository_request_url . "utils/patches/patch_UF.conf"], + 7 => ["Rain of Fear", $eqemu_repository_request_url . "utils/patches/patch_RoF.conf"], + 8 => ["Rain of Fear 2", $eqemu_repository_request_url . "utils/patches/patch_RoF2.conf"], ); $loop = 1; while($opcodes{$loop}[0]){ - #::: Split the URL by the patches folder to get the file name from URL + #::: Split the request_url by the patches folder to get the file name from request_url @real_file = split("patches/", $opcodes{$loop}[1]); $find = 0; while($real_file[$find]){ $file_name = $real_file[$find]; $find++; } - - print "\nDownloading (" . $opcodes{$loop}[0] . ") File: '" . $file_name . "'...\n\n"; + get_remote_file($opcodes{$loop}[1], $file_name); $loop++; } - print "\nDone...\n\n"; + print "[Update] Done...\n"; } -sub remove_duplicate_rule_values{ +sub remove_duplicate_rule_values { $ruleset_id = trim(get_mysql_result("SELECT `ruleset_id` FROM `rule_sets` WHERE `name` = 'default'")); - print "Default Ruleset ID: " . $ruleset_id . "\n"; + print "[Database] Default Ruleset ID: " . $ruleset_id . "\n"; $total_removed = 0; + #::: Store Default values... $mysql_result = get_mysql_result("SELECT * FROM `rule_values` WHERE `ruleset_id` = " . $ruleset_id); my @lines = split("\n", $mysql_result); @@ -607,50 +762,51 @@ sub remove_duplicate_rule_values{ my @values = split("\t", $val); $rule_set_values{$values[1]}[0] = $values[2]; } + #::: Compare default values against other rulesets to check for duplicates... $mysql_result = get_mysql_result("SELECT * FROM `rule_values` WHERE `ruleset_id` != " . $ruleset_id); my @lines = split("\n", $mysql_result); foreach my $val (@lines){ my @values = split("\t", $val); if($values[2] == $rule_set_values{$values[1]}[0]){ - print "DUPLICATE : " . $values[1] . " (Ruleset (" . $values[0] . ")) matches default value of : " . $values[2] . ", removing...\n"; + print "[Database] Removing duplicate : " . $values[1] . " (Ruleset (" . $values[0] . ")) matches default value of : " . $values[2] . "\n"; get_mysql_result("DELETE FROM `rule_values` WHERE `ruleset_id` = " . $values[0] . " AND `rule_name` = '" . $values[1] . "'"); $total_removed++; } } - print "Total duplicate rules removed... " . $total_removed . "\n"; + print "[Database] Total duplicate rules removed... " . $total_removed . "\n"; } -sub copy_file{ +sub copy_file { $l_source_file = $_[0]; - $l_dest_file = $_[1]; - if($l_dest_file=~/\//i){ - my @dir_path = split('/', $l_dest_file); + $l_destination_file = $_[1]; + if($l_destination_file=~/\//i){ + my @directory_path = split('/', $l_destination_file); $build_path = ""; - $di = 0; - while($dir_path[$di]){ - $build_path .= $dir_path[$di] . "/"; + $directory_index = 0; + while($directory_path[$directory_index]){ + $build_path .= $directory_path[$directory_index] . "/"; #::: If path does not exist, create the directory... if (!-d $build_path) { mkdir($build_path); } - if(!$dir_path[$di + 2] && $dir_path[$di + 1]){ + if(!$directory_path[$directory_index + 2] && $directory_path[$directory_index + 1]){ # print $actual_path . "\n"; $actual_path = $build_path; last; } - $di++; + $directory_index++; } } - copy $l_source_file, $l_dest_file; + copy $l_source_file, $l_destination_file; } -sub fetch_latest_windows_binaries{ - print "\n --- Fetching Latest Windows Binaries... --- \n"; - get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/master_windows_build.zip", "updates_staged/master_windows_build.zip", 1); - print "\n --- Fetched Latest Windows Binaries... --- \n"; - print "\n --- Extracting... --- \n"; +sub fetch_latest_windows_binaries { + print "[Update] Fetching Latest Windows Binaries... \n"; + get_remote_file($install_repository_request_url . "master_windows_build.zip", "updates_staged/master_windows_build.zip", 1); + print "[Update] Fetched Latest Windows Binaries... \n"; + print "[Update] Extracting... --- \n"; unzip('updates_staged/master_windows_build.zip', 'updates_staged/binaries/'); my @files; my $start_dir = "updates_staged/binaries"; @@ -659,21 +815,21 @@ sub fetch_latest_windows_binaries{ $start_dir ); for my $file (@files) { - $dest_file = $file; - $dest_file =~s/updates_staged\/binaries\///g; - print "Installing :: " . $dest_file . "\n"; - copy_file($file, $dest_file); + $destination_file = $file; + $destination_file =~s/updates_staged\/binaries\///g; + print "[Update] Installing :: " . $destination_file . "\n"; + copy_file($file, $destination_file); } - print "\n --- Done... --- \n"; + print "[Update] Done\n"; rmtree('updates_staged'); } -sub fetch_latest_windows_binaries_bots{ - print "\n --- Fetching Latest Windows Binaries with Bots... --- \n"; - get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/master_windows_build_bots.zip", "updates_staged/master_windows_build_bots.zip", 1); - print "\n --- Fetched Latest Windows Binaries with Bots... --- \n"; - print "\n --- Extracting... --- \n"; +sub fetch_latest_windows_binaries_bots { + print "[Update] Fetching Latest Windows Binaries with Bots...\n"; + get_remote_file($install_repository_request_url . "master_windows_build_bots.zip", "updates_staged/master_windows_build_bots.zip", 1); + print "[Update] Fetched Latest Windows Binaries with Bots...\n"; + print "[Update] Extracting...\n"; unzip('updates_staged/master_windows_build_bots.zip', 'updates_staged/binaries/'); my @files; my $start_dir = "updates_staged/binaries"; @@ -682,20 +838,20 @@ sub fetch_latest_windows_binaries_bots{ $start_dir ); for my $file (@files) { - $dest_file = $file; - $dest_file =~s/updates_staged\/binaries\///g; - print "Installing :: " . $dest_file . "\n"; - copy_file($file, $dest_file); + $destination_file = $file; + $destination_file =~s/updates_staged\/binaries\///g; + print "[Install] Installing :: " . $destination_file . "\n"; + copy_file($file, $destination_file); } - print "\n --- Done... --- \n"; + print "[Update] Done...\n"; rmtree('updates_staged'); } -sub do_windows_login_server_setup{ - print "\n --- Fetching Loginserver... --- \n"; - get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/login_server.zip", "updates_staged/login_server.zip", 1); - print "\n --- Extracting... --- \n"; +sub do_windows_login_server_setup { + print "[Install] Fetching Loginserver... \n"; + get_remote_file($install_repository_request_url . "login_server.zip", "updates_staged/login_server.zip", 1); + print "[Install] Extracting... \n"; unzip('updates_staged/login_server.zip', 'updates_staged/login_server/'); my @files; my $start_dir = "updates_staged/login_server"; @@ -704,31 +860,85 @@ sub do_windows_login_server_setup{ $start_dir ); for my $file (@files) { - $dest_file = $file; - $dest_file =~s/updates_staged\/login_server\///g; - print "Installing :: " . $dest_file . "\n"; - copy_file($file, $dest_file); + $destination_file = $file; + $destination_file =~s/updates_staged\/login_server\///g; + print "[Install] Installing :: " . $destination_file . "\n"; + copy_file($file, $destination_file); } - print "\n Done... \n"; + print "[Install] Done... \n"; - print "Pulling down Loginserver database tables...\n"; - get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/login_server_tables.sql", "db_update/login_server_tables.sql"); - print "\n\nInstalling Loginserver tables...\n"; + print "[Install] Pulling down Loginserver database tables...\n"; + get_remote_file($install_repository_request_url . "login_server_tables.sql", "db_update/login_server_tables.sql"); + print "[Install] Installing Loginserver tables...\n"; print get_mysql_result_from_file("db_update/login_server_tables.sql"); - print "\nDone...\n\n"; + print "[Install] Done...\n"; add_login_server_firewall_rules(); rmtree('updates_staged'); rmtree('db_update'); - print "\nPress any key to continue...\n"; + print "[Install] Press any key to continue...\n"; + + <>; #Read from STDIN + +} + +sub do_linux_login_server_setup { + + for my $file (@files) { + $destination_file = $file; + $destination_file =~s/updates_staged\/login_server\///g; + print "[Install] Installing :: " . $destination_file . "\n"; + copy_file($file, $destination_file); + } + print "\n Done... \n"; + + print "[Install] Pulling down Loginserver database tables...\n"; + get_remote_file($install_repository_request_url . "login_server_tables.sql", "db_update/login_server_tables.sql"); + print "[Install] Installing Loginserver tables...\n"; + print get_mysql_result_from_file("db_update/login_server_tables.sql"); + print "[Install] Done...\n\n"; + + rmtree('updates_staged'); + rmtree('db_update'); + + get_remote_file($install_repository_request_url . "linux/login.ini", "login_template.ini"); + get_remote_file($install_repository_request_url . "linux/login_opcodes.conf", "login_opcodes.conf"); + get_remote_file($install_repository_request_url . "linux/login_opcodes.conf", "login_opcodes_sod.conf"); + + get_installation_variables(); + my $db_name = $installation_variables{"mysql_eqemu_db_name"}; + my $db_user = $installation_variables{"mysql_eqemu_user"}; + my $db_password = $installation_variables{"mysql_eqemu_password"}; + + #::: Open new config file + open (NEW_CONFIG, '>', 'login.ini'); + + #::: Iterate through template and replace variables... + open (FILE_TEMPLATE, "login_template.ini"); + while (){ + chomp; + $o = $_; + #::: Find replace variables + if($o=~/db/i){ $o = "db = " . $db_name; } + if($o=~/user/i){ $o = "user = " . $db_user; } + if($o=~/password/i){ $o = "password = " . $db_password; } + + print NEW_CONFIG $o . "\n"; + } + + close(FILE_TEMPLATE); + close(NEW_CONFIG); + unlink("login_template.ini"); + + print "[Install] Press any key to continue...\n"; <>; #Read from STDIN } -sub add_login_server_firewall_rules{ +sub add_login_server_firewall_rules { #::: Check Loginserver Firewall install for Windows if($OS eq "Windows"){ $output = `netsh advfirewall firewall show rule name=all`; @@ -750,22 +960,22 @@ sub add_login_server_firewall_rules{ } if($has_loginserver_rules_titanium == 0){ - print "Attempting to add EQEmu Loginserver Firewall Rules (Titanium) (TCP) port 5998 \n"; + print "[Install] Attempting to add EQEmu Loginserver Firewall Rules (Titanium) (TCP) port 5998 \n"; print `netsh advfirewall firewall add rule name="EQEmu Loginserver (Titanium) (5998) TCP" dir=in action=allow protocol=TCP localport=5998`; - print "Attempting to add EQEmu Loginserver Firewall Rules (Titanium) (UDP) port 5998 \n"; + print "[Install] Attempting to add EQEmu Loginserver Firewall Rules (Titanium) (UDP) port 5998 \n"; print `netsh advfirewall firewall add rule name="EQEmu Loginserver (Titanium) (5998) UDP" dir=in action=allow protocol=UDP localport=5998`; } if($has_loginserver_rules_sod == 0){ - print "Attempting to add EQEmu Loginserver Firewall Rules (SOD+) (TCP) port 5999 \n"; + print "[Install] Attempting to add EQEmu Loginserver Firewall Rules (SOD+) (TCP) port 5999 \n"; print `netsh advfirewall firewall add rule name="EQEmu Loginserver (SOD+) (5999) TCP" dir=in action=allow protocol=TCP localport=5999`; - print "Attempting to add EQEmu Loginserver Firewall Rules (SOD+) (UDP) port 5999 \n"; + print "[Install] Attempting to add EQEmu Loginserver Firewall Rules (SOD+) (UDP) port 5999 \n"; print `netsh advfirewall firewall add rule name="EQEmu Loginserver (SOD+) (5999) UDP" dir=in action=allow protocol=UDP localport=5999`; } - print "If firewall rules don't add you must run this script (eqemu_update.pl) as administrator\n"; + print "If firewall rules don't add you must run this script (eqemu_server.pl) as administrator\n"; print "\n"; - print "#::: Instructions \n"; - print "In order to connect your server to the loginserver you must point your eqemu_config.xml to your local server similar to the following:\n"; + print "[Install] Instructions \n"; + print "[Install] In order to connect your server to the loginserver you must point your eqemu_config.xml to your local server similar to the following:\n"; print " login.eqemulator.net @@ -780,7 +990,7 @@ sub add_login_server_firewall_rules{ "; - print "\nWhen done, make sure your EverQuest client points to your loginserver's IP (In this case it would be 127.0.0.1) in the eqhosts.txt file\n"; + print "[Install] When done, make sure your EverQuest client points to your loginserver's IP (In this case it would be 127.0.0.1) in the eqhosts.txt file\n"; } } @@ -794,84 +1004,84 @@ sub check_windows_firewall_rules{ $val=~s/Rule Name://g; if($val=~/EQEmu World/i){ $has_world_rules = 1; - print "Found existing rule :: " . trim($val) . "\n"; + print "[Install] Found existing rule :: " . trim($val) . "\n"; } if($val=~/EQEmu Zone/i){ $has_zone_rules = 1; - print "Found existing rule :: " . trim($val) . "\n"; + print "[Install] Found existing rule :: " . trim($val) . "\n"; } } } if($has_world_rules == 0){ - print "Attempting to add EQEmu World Firewall Rules (TCP) port 9000 \n"; + print "[Install] Attempting to add EQEmu World Firewall Rules (TCP) port 9000 \n"; print `netsh advfirewall firewall add rule name="EQEmu World (9000) TCP" dir=in action=allow protocol=TCP localport=9000`; - print "Attempting to add EQEmu World Firewall Rules (UDP) port 9000 \n"; + print "[Install] Attempting to add EQEmu World Firewall Rules (UDP) port 9000 \n"; print `netsh advfirewall firewall add rule name="EQEmu World (9000) UDP" dir=in action=allow protocol=UDP localport=9000`; } if($has_zone_rules == 0){ - print "Attempting to add EQEmu Zones (7000-7500) TCP \n"; + print "[Install] Attempting to add EQEmu Zones (7000-7500) TCP \n"; print `netsh advfirewall firewall add rule name="EQEmu Zones (7000-7500) TCP" dir=in action=allow protocol=TCP localport=7000-7500`; - print "Attempting to add EQEmu Zones (7000-7500) UDP \n"; + print "[Install] Attempting to add EQEmu Zones (7000-7500) UDP \n"; print `netsh advfirewall firewall add rule name="EQEmu Zones (7000-7500) UDP" dir=in action=allow protocol=UDP localport=7000-7500`; } } sub fetch_server_dlls{ - print "Fetching lua51.dll, zlib1.dll, libmysql.dll...\n"; - get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/lua51.dll", "lua51.dll", 1); - get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/zlib1.dll", "zlib1.dll", 1); - get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/libmysql.dll", "libmysql.dll", 1); + print "[Download] Fetching lua51.dll, zlib1.dll, libmysql.dll...\n"; + get_remote_file($install_repository_request_url . "lua51.dll", "lua51.dll", 1); + get_remote_file($install_repository_request_url . "zlib1.dll", "zlib1.dll", 1); + get_remote_file($install_repository_request_url . "libmysql.dll", "libmysql.dll", 1); } sub fetch_peq_db_full{ - print "Downloading latest PEQ Database... Please wait...\n"; + print "[Install] Downloading latest PEQ Database... Please wait...\n"; get_remote_file("http://edit.peqtgc.com/weekly/peq_beta.zip", "updates_staged/peq_beta.zip", 1); - print "Downloaded latest PEQ Database... Extracting...\n"; + print "[Install] Downloaded latest PEQ Database... Extracting...\n"; unzip('updates_staged/peq_beta.zip', 'updates_staged/peq_db/'); - my $start_dir = "updates_staged\\peq_db"; + my $start_dir = "updates_staged/peq_db"; find( sub { push @files, $File::Find::name unless -d; }, $start_dir ); for my $file (@files) { - $dest_file = $file; - $dest_file =~s/updates_staged\\peq_db\///g; + $destination_file = $file; + $destination_file =~s/updates_staged\/peq_db\///g; if($file=~/peqbeta|player_tables/i){ - print "MariaDB :: Installing :: " . $dest_file . "\n"; + print "[Install] DB :: Installing :: " . $destination_file . "\n"; get_mysql_result_from_file($file); } if($file=~/eqtime/i){ - print "Installing eqtime.cfg\n"; + print "[Install] Installing eqtime.cfg\n"; copy_file($file, "eqtime.cfg"); } } } sub map_files_fetch_bulk{ - print "\n --- Fetching Latest Maps... (This could take a few minutes...) --- \n"; + print "[Install] Fetching Latest Maps... (This could take a few minutes...)\n"; get_remote_file("http://github.com/Akkadius/EQEmuMaps/archive/master.zip", "maps/maps.zip", 1); unzip('maps/maps.zip', 'maps/'); my @files; - my $start_dir = "maps\\EQEmuMaps-master\\maps"; + my $start_dir = "maps/EQEmuMaps-master/maps"; find( sub { push @files, $File::Find::name unless -d; }, $start_dir ); for my $file (@files) { - $dest_file = $file; - $dest_file =~s/maps\\EQEmuMaps-master\\maps\///g; - print "Installing :: " . $dest_file . "\n"; + $destination_file = $file; + $destination_file =~s/maps\/EQEmuMaps-master\/maps\///g; + print "[Install] Installing :: " . $destination_file . "\n"; copy_file($file, "maps/" . $new_file); } - print "\n --- Fetched Latest Maps... --- \n"; + print "[Install] Fetched Latest Maps\n"; rmtree('maps/EQEmuMaps-master'); unlink('maps/maps.zip'); } sub map_files_fetch{ - print "\n --- Fetching Latest Maps --- \n"; + print "[Install] Fetching Latest Maps --- \n"; get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuMaps/master/!eqemu_maps_manifest.txt", "updates_staged/eqemu_maps_manifest.txt"); @@ -894,22 +1104,22 @@ sub map_files_fetch{ my $file_existing = $maps_manifest[$m][0]; my $file_existing_size = (stat $file_existing)[7]; if($file_existing_size != $maps_manifest[$m][1]){ - print "Updating: '" . $maps_manifest[$m][0] . "'\n"; + print "[Install] Updating: '" . $maps_manifest[$m][0] . "'\n"; get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuMaps/master/" . $maps_manifest[$m][0], $maps_manifest[$m][0], 1); $fc++; } } if($fc == 0){ - print "\nNo Map Updates found... \n\n"; + print "[Install] No Map Updates found... \n\n"; } } sub quest_files_fetch{ if (!-e "updates_staged/Quests-Plugins-master/quests/") { - print "\n --- Fetching Latest Quests --- \n"; + print "[Update] Fetching Latest Quests --- \n"; get_remote_file("https://github.com/EQEmu/Quests-Plugins/archive/master.zip", "updates_staged/Quests-Plugins-master.zip", 1); - print "\nFetched latest quests...\n"; + print "[Install] Fetched latest quests...\n"; mkdir('updates_staged'); unzip('updates_staged/Quests-Plugins-master.zip', 'updates_staged/'); } @@ -927,30 +1137,30 @@ sub quest_files_fetch{ for my $file (@files) { if($file=~/\.pl|\.lua|\.ext/i){ $staged_file = $file; - $dest_file = $file; - $dest_file =~s/updates_staged\/Quests-Plugins-master\///g; + $destination_file = $file; + $destination_file =~s/updates_staged\/Quests-Plugins-master\///g; - if (!-e $dest_file) { - copy_file($staged_file, $dest_file); - print "Installing :: '" . $dest_file . "'\n"; + if (!-e $destination_file) { + copy_file($staged_file, $destination_file); + print "[Install] Installing :: '" . $destination_file . "'\n"; $fc++; } else{ - $diff = do_file_diff($dest_file, $staged_file); - if($diff ne ""){ - $backup_dest = "updates_backups/" . $time_stamp . "/" . $dest_file; + $directory_indexff = do_file_diff($destination_file, $staged_file); + if($directory_indexff ne ""){ + $backup_dest = "updates_backups/" . $time_stamp . "/" . $destination_file; - print $diff . "\n"; - print "\nFile Different :: '" . $dest_file . "'\n"; - print "\nDo you wish to update this Quest? '" . $dest_file . "' [Yes (Enter) - No (N)] \nA backup will be found in '" . $backup_dest . "'\n"; + print $directory_indexff . "\n"; + print "[Update] File Different :: '" . $destination_file . "'\n"; + print "[Update] Do you wish to update this Quest? '" . $destination_file . "' [Yes (Enter) - No (N)] \nA backup will be found in '" . $backup_dest . "'\n"; my $input = ; if($input=~/N/i){} else{ #::: Make a backup - copy_file($dest_file, $backup_dest); + copy_file($destination_file, $backup_dest); #::: Copy staged to running - copy($staged_file, $dest_file); - print "Installing :: '" . $dest_file . "'\n\n"; + copy($staged_file, $destination_file); + print "[Install] Installing :: '" . $destination_file . "'\n\n"; } $fc++; } @@ -961,15 +1171,15 @@ sub quest_files_fetch{ rmtree('updates_staged'); if($fc == 0){ - print "\nNo Quest Updates found... \n\n"; + print "[Update] No Quest Updates found... \n\n"; } } -sub lua_modules_fetch{ +sub lua_modules_fetch { if (!-e "updates_staged/Quests-Plugins-master/quests/lua_modules/") { - print "\n --- Fetching Latest LUA Modules --- \n"; + print "[Update] Fetching Latest LUA Modules --- \n"; get_remote_file("https://github.com/EQEmu/Quests-Plugins/archive/master.zip", "updates_staged/Quests-Plugins-master.zip", 1); - print "\nFetched latest LUA Modules...\n"; + print "[Update] Fetched latest LUA Modules...\n"; unzip('updates_staged/Quests-Plugins-master.zip', 'updates_staged/'); } @@ -986,29 +1196,29 @@ sub lua_modules_fetch{ for my $file (@files) { if($file=~/\.pl|\.lua|\.ext/i){ $staged_file = $file; - $dest_file = $file; - $dest_file =~s/updates_staged\/Quests-Plugins-master\/quests\///g; + $destination_file = $file; + $destination_file =~s/updates_staged\/Quests-Plugins-master\/quests\///g; - if (!-e $dest_file) { - copy_file($staged_file, $dest_file); - print "Installing :: '" . $dest_file . "'\n"; + if (!-e $destination_file) { + copy_file($staged_file, $destination_file); + print "[Install] Installing :: '" . $destination_file . "'\n"; $fc++; } else{ - $diff = do_file_diff($dest_file, $staged_file); - if($diff ne ""){ - $backup_dest = "updates_backups/" . $time_stamp . "/" . $dest_file; - print $diff . "\n"; - print "\nFile Different :: '" . $dest_file . "'\n"; - print "\nDo you wish to update this LUA Module? '" . $dest_file . "' [Yes (Enter) - No (N)] \nA backup will be found in '" . $backup_dest . "'\n"; + $directory_indexff = do_file_diff($destination_file, $staged_file); + if($directory_indexff ne ""){ + $backup_dest = "updates_backups/" . $time_stamp . "/" . $destination_file; + print $directory_indexff . "\n"; + print "[Update] File Different :: '" . $destination_file . "'\n"; + print "[Update] Do you wish to update this LUA Module? '" . $destination_file . "' [Yes (Enter) - No (N)] \nA backup will be found in '" . $backup_dest . "'\n"; my $input = ; if($input=~/N/i){} else{ #::: Make a backup - copy_file($dest_file, $backup_dest); + copy_file($destination_file, $backup_dest); #::: Copy staged to running - copy($staged_file, $dest_file); - print "Installing :: '" . $dest_file . "'\n\n"; + copy($staged_file, $destination_file); + print "[Install] Installing :: '" . $destination_file . "'\n\n"; } $fc++; } @@ -1017,15 +1227,15 @@ sub lua_modules_fetch{ } if($fc == 0){ - print "\nNo LUA Modules Updates found... \n\n"; + print "[Update] No LUA Modules Updates found... \n\n"; } } sub plugins_fetch{ if (!-e "updates_staged/Quests-Plugins-master/plugins/") { - print "\n --- Fetching Latest Plugins --- \n"; + print "[Update] Fetching Latest Plugins\n"; get_remote_file("https://github.com/EQEmu/Quests-Plugins/archive/master.zip", "updates_staged/Quests-Plugins-master.zip", 1); - print "\nFetched latest plugins...\n"; + print "[Update] Fetched latest plugins\n"; unzip('updates_staged/Quests-Plugins-master.zip', 'updates_staged/'); } @@ -1042,29 +1252,29 @@ sub plugins_fetch{ for my $file (@files) { if($file=~/\.pl|\.lua|\.ext/i){ $staged_file = $file; - $dest_file = $file; - $dest_file =~s/updates_staged\/Quests-Plugins-master\///g; + $destination_file = $file; + $destination_file =~s/updates_staged\/Quests-Plugins-master\///g; - if (!-e $dest_file) { - copy_file($staged_file, $dest_file); - print "Installing :: '" . $dest_file . "'\n"; + if (!-e $destination_file) { + copy_file($staged_file, $destination_file); + print "[Install] Installing :: '" . $destination_file . "'\n"; $fc++; } else{ - $diff = do_file_diff($dest_file, $staged_file); - if($diff ne ""){ - $backup_dest = "updates_backups/" . $time_stamp . "/" . $dest_file; - print $diff . "\n"; - print "\nFile Different :: '" . $dest_file . "'\n"; - print "\nDo you wish to update this Plugin? '" . $dest_file . "' [Yes (Enter) - No (N)] \nA backup will be found in '" . $backup_dest . "'\n"; + $directory_indexff = do_file_diff($destination_file, $staged_file); + if($directory_indexff ne ""){ + $backup_dest = "updates_backups/" . $time_stamp . "/" . $destination_file; + print $directory_indexff . "\n"; + print "[Update] File Different :: '" . $destination_file . "'\n"; + print "[Update] Do you wish to update this Plugin? '" . $destination_file . "' [Yes (Enter) - No (N)] \nA backup will be found in '" . $backup_dest . "'\n"; my $input = ; if($input=~/N/i){} else{ #::: Make a backup - copy_file($dest_file, $backup_dest); + copy_file($destination_file, $backup_dest); #::: Copy staged to running - copy($staged_file, $dest_file); - print "Installing :: '" . $dest_file . "'\n\n"; + copy($staged_file, $destination_file); + print "[Install] Installing :: '" . $destination_file . "'\n\n"; } $fc++; } @@ -1073,7 +1283,7 @@ sub plugins_fetch{ } if($fc == 0){ - print "\nNo Plugin Updates found... \n\n"; + print "[Update] No Plugin Updates found... \n\n"; } } @@ -1082,8 +1292,8 @@ sub do_file_diff{ $file_2 = $_[1]; if($OS eq "Windows"){ eval "use Text::Diff"; - $diff = diff($file_1, $file_2, { STYLE => "Unified" }); - return $diff; + $directory_indexff = diff($file_1, $file_2, { STYLE => "Unified" }); + return $directory_indexff; } if($OS eq "Linux"){ # print 'diff -u "$file_1" "$file_2"' . "\n"; @@ -1091,7 +1301,7 @@ sub do_file_diff{ } } -sub unzip{ +sub unzip { $archive_to_unzip = $_[0]; $dest_folder = $_[1]; @@ -1101,11 +1311,11 @@ sub unzip{ unless ( $zip->read($archive_to_unzip) == AZ_OK ) { die 'read error'; } - print "Extracting...\n"; + print "[Unzip] Extracting...\n"; $zip->extractTree('', $dest_folder); } if($OS eq "Linux"){ - print `unzip -o "$archive_to_unzip" -d "$dest_folder"`; + print `unzip -o -q "$archive_to_unzip" -d "$dest_folder"`; } } @@ -1123,11 +1333,11 @@ sub are_file_sizes_different{ sub do_bots_db_schema_drop{ #"drop_bots.sql" is run before reverting database back to 'normal' - print "Fetching drop_bots.sql...\n"; - get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/master/utils/sql/git/bots/drop_bots.sql", "db_update/drop_bots.sql"); + print "[Database] Fetching drop_bots.sql...\n"; + get_remote_file($eqemu_repository_request_url . "utils/sql/git/bots/drop_bots.sql", "db_update/drop_bots.sql"); print get_mysql_result_from_file("db_update/drop_bots.sql"); - print "Restoring normality...\n"; + print "[Database] Removing bot database tables...\n"; print get_mysql_result("DELETE FROM `rule_values` WHERE `rule_name` LIKE 'Bots:%';"); if(get_mysql_result("SHOW TABLES LIKE 'commands'") ne "" && $db){ @@ -1153,11 +1363,12 @@ sub do_bots_db_schema_drop{ if(get_mysql_result("SHOW COLUMNS FROM `db_version` LIKE 'bots_version'") ne "" && $db){ print get_mysql_result("UPDATE `db_version` SET `bots_version` = 0;"); } + print "[Database] Done...\n"; } sub modify_db_for_bots{ #Called after the db bots schema (2015_09_30_bots.sql) has been loaded - print "Modifying database for bots...\n"; + print "[Database] Modifying database for bots...\n"; print get_mysql_result("UPDATE `spawn2` SET `enabled` = 1 WHERE `id` IN (59297,59298);"); if(get_mysql_result("SHOW KEYS FROM `guild_members` WHERE `Key_name` LIKE 'PRIMARY'") ne "" && $db){ @@ -1238,7 +1449,7 @@ sub modify_db_for_bots{ sub convert_existing_bot_data{ if(get_mysql_result("SHOW TABLES LIKE 'bots'") ne "" && $db){ - print "Converting existing bot data...\n"; + print "[Database] Converting existing bot data...\n"; print get_mysql_result("INSERT INTO `bot_data` (`bot_id`, `owner_id`, `spells_id`, `name`, `last_name`, `zone_id`, `gender`, `race`, `class`, `level`, `creation_day`, `last_spawn`, `time_spawned`, `size`, `face`, `hair_color`, `hair_style`, `beard`, `beard_color`, `eye_color_1`, `eye_color_2`, `drakkin_heritage`, `drakkin_tattoo`, `drakkin_details`, `ac`, `atk`, `hp`, `mana`, `str`, `sta`, `cha`, `dex`, `int`, `agi`, `wis`, `fire`, `cold`, `magic`, `poison`, `disease`, `corruption`) SELECT `BotID`, `BotOwnerCharacterID`, `BotSpellsID`, `Name`, `LastName`, `LastZoneId`, `Gender`, `Race`, `Class`, `BotLevel`, UNIX_TIMESTAMP(`BotCreateDate`), UNIX_TIMESTAMP(`LastSpawnDate`), `TotalPlayTime`, `Size`, `Face`, `LuclinHairColor`, `LuclinHairStyle`, `LuclinBeard`, `LuclinBeardColor`, `LuclinEyeColor`, `LuclinEyeColor2`, `DrakkinHeritage`, `DrakkinTattoo`, `DrakkinDetails`, `AC`, `ATK`, `HP`, `Mana`, `STR`, `STA`, `CHA`, `DEX`, `_INT`, `AGI`, `WIS`, `FR`, `CR`, `MR`, `PR`, `DR`, `Corrup` FROM `bots`;"); print get_mysql_result("INSERT INTO `bot_inspect_messages` (`bot_id`, `inspect_message`) SELECT `BotID`, `BotInspectMessage` FROM `bots`;"); @@ -1335,7 +1546,7 @@ sub get_bots_db_version{ #::: Check if bots_version column exists... if(get_mysql_result("SHOW COLUMNS FROM db_version LIKE 'bots_version'") eq "" && $db){ print get_mysql_result("ALTER TABLE db_version ADD bots_version int(11) DEFAULT '0' AFTER version;"); - print "\nColumn 'bots_version' does not exists.... Adding to 'db_version' table...\n\n"; + print "[Database] Column 'bots_version' does not exists.... Adding to 'db_version' table...\n\n"; } $bots_local_db_version = trim(get_mysql_result("SELECT bots_version FROM db_version LIMIT 1")); return $bots_local_db_version; @@ -1351,7 +1562,7 @@ sub bots_db_management{ } if($bin_db_ver == 0){ - print "Your server binaries (world/zone) are not compiled for bots...\n"; + print "[Database] Your server binaries (world/zone) are not compiled for bots...\n\n"; return; } @@ -1397,22 +1608,22 @@ sub run_database_check{ if(!@total_updates){ #::: Pull down bots database manifest if($bots_db_management == 1){ - print "Retrieving latest bots database manifest...\n"; - get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/master/utils/sql/git/bots/bots_db_update_manifest.txt", "db_update/db_update_manifest.txt"); + print "[Database] Retrieving latest bots database manifest...\n"; + get_remote_file($eqemu_repository_request_url . "utils/sql/git/bots/bots_db_update_manifest.txt", "db_update/db_update_manifest.txt"); } #::: Pull down mainstream database manifest else{ - print "Retrieving latest database manifest...\n"; - get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/master/utils/sql/db_update_manifest.txt", "db_update/db_update_manifest.txt"); + print "[Database] Retrieving latest database manifest...\n"; + get_remote_file($eqemu_repository_request_url . "utils/sql/db_update_manifest.txt", "db_update/db_update_manifest.txt"); } } #::: Run 2 - Running pending updates... - if(@total_updates){ + if(@total_updates || $db_run_stage == 1){ @total_updates = sort @total_updates; foreach my $val (@total_updates){ $file_name = trim($m_d{$val}[1]); - print "Running Update: " . $val . " - " . $file_name . "\n"; + print "[Database] Running Update: " . $val . " - " . $file_name . "\n"; print get_mysql_result_from_file("db_update/$file_name"); print get_mysql_result("UPDATE db_version SET version = $val WHERE version < $val"); @@ -1424,7 +1635,7 @@ sub run_database_check{ } #::: Run 1 - Initial checking of needed updates... else{ - print "Reading manifest...\n\n"; + print "[Database] Reading manifest...\n"; use Data::Dumper; open (FILE, "db_update/db_update_manifest.txt"); while () { @@ -1458,23 +1669,23 @@ sub run_database_check{ #::: Match type update if($match_type eq "contains"){ if(trim(get_mysql_result($query_check))=~/$match_text/i){ - print "Missing DB Update " . $i . " '" . $file_name . "' \n"; + print "[Database] missing update: " . $i . " '" . $file_name . "' \n"; fetch_missing_db_update($i, $file_name); push(@total_updates, $i); } else{ - print "DB up to date with: " . $i . " - '" . $file_name . "' \n"; + print "[Database] has update: " . $i . " - '" . $file_name . "' \n"; } print_match_debug(); print_break(); } if($match_type eq "missing"){ if(get_mysql_result($query_check)=~/$match_text/i){ - print "DB up to date with: " . $i . " - '" . $file_name . "' \n"; + print "[Database] has update: " . $i . " - '" . $file_name . "' \n"; next; } else{ - print "Missing DB Update " . $i . " '" . $file_name . "' \n"; + print "[Database] missing update: " . $i . " '" . $file_name . "' \n"; fetch_missing_db_update($i, $file_name); push(@total_updates, $i); } @@ -1483,24 +1694,24 @@ sub run_database_check{ } if($match_type eq "empty"){ if(get_mysql_result($query_check) eq ""){ - print "Missing DB Update " . $i . " '" . $file_name . "' \n"; + print "[Database] missing update: " . $i . " '" . $file_name . "' \n"; fetch_missing_db_update($i, $file_name); push(@total_updates, $i); } else{ - print "DB up to date with: " . $i . " - '" . $file_name . "' \n"; + print "[Database] has update: " . $i . " - '" . $file_name . "' \n"; } print_match_debug(); print_break(); } if($match_type eq "not_empty"){ if(get_mysql_result($query_check) ne ""){ - print "Missing DB Update " . $i . " '" . $file_name . "' \n"; + print "[Database] missing update: " . $i . " '" . $file_name . "' \n"; fetch_missing_db_update($i, $file_name); push(@total_updates, $i); } else{ - print "DB up to date with: " . $i . " - '" . $file_name . "' \n"; + print "[Database] has update: " . $i . " - '" . $file_name . "' \n"; } print_match_debug(); print_break(); @@ -1509,13 +1720,13 @@ sub run_database_check{ print "\n"; if(scalar (@total_updates) == 0 && $db_run_stage == 2){ - print "No updates need to be run...\n"; + print "[Database] No updates need to be run...\n"; if($bots_db_management == 1){ - print "Setting Database to Bots Binary Version (" . $bin_db_ver . ") if not already...\n\n"; + print "[Database] Setting Database to Bots Binary Version (" . $bin_db_ver . ") if not already...\n\n"; get_mysql_result("UPDATE db_version SET bots_version = $bin_db_ver"); } - else{ - print "Setting Database to Binary Version (" . $bin_db_ver . ") if not already...\n\n"; + else{ + print "[Database] Setting Database to Binary Version (" . $bin_db_ver . ") if not already...\n\n"; get_mysql_result("UPDATE db_version SET version = $bin_db_ver"); } @@ -1528,14 +1739,14 @@ sub fetch_missing_db_update{ $update_file = $_[1]; if($db_update >= 9000){ if($bots_db_management == 1){ - get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/master/utils/sql/git/bots/required/" . $update_file, "db_update/" . $update_file . ""); + get_remote_file($eqemu_repository_request_url . "utils/sql/git/bots/required/" . $update_file, "db_update/" . $update_file . ""); } else{ - get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/master/utils/sql/git/required/" . $update_file, "db_update/" . $update_file . ""); + get_remote_file($eqemu_repository_request_url . "utils/sql/git/required/" . $update_file, "db_update/" . $update_file . ""); } } elsif($db_update >= 5000 && $db_update <= 9000){ - get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/master/utils/sql/svn/" . $update_file, "db_update/" . $update_file . ""); + get_remote_file($eqemu_repository_request_url . "utils/sql/svn/" . $update_file, "db_update/" . $update_file . ""); } } @@ -1546,7 +1757,17 @@ sub print_match_debug{ print " Query Check: '" . $query_check . "'\n"; print " Result: '" . trim(get_mysql_result($query_check)) . "'\n"; } + sub print_break{ if(!$debug){ return; } print "\n==============================================\n"; } + +sub generate_random_password { + my $passwordsize = shift; + my @alphanumeric = ('a'..'z', 'A'..'Z', 0..9); + my $randpassword = join '', + map $alphanumeric[rand @alphanumeric], 0..$passwordsize; + + return $randpassword; +} diff --git a/utils/sql/db_update_manifest.txt b/utils/sql/db_update_manifest.txt index 283500c3b..4030395c3 100644 --- a/utils/sql/db_update_manifest.txt +++ b/utils/sql/db_update_manifest.txt @@ -351,6 +351,7 @@ 9095|2016_01_08_command_find_aliases.sql|SELECT * FROM `command_settings` WHERE `command` LIKE 'findaliases'|empty| 9096|2016_03_05_secondary_recall.sql|SHOW COLUMNS FROM `character_bind` LIKE 'slot'|empty| 9097|2016_07_03_npc_class_as_last_name.sql|SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'NPC:UseClassAsLastName'|empty| +9098|2016_08_26_object_size_tilt.sql|SHOW COLUMNS FROM `object` LIKE 'size'|empty| # Upgrade conditions: # This won't be needed after this system is implemented, but it is used database that are not diff --git a/utils/sql/git/required/2016_08_26_object_size_tilt.sql b/utils/sql/git/required/2016_08_26_object_size_tilt.sql new file mode 100644 index 000000000..ded4d841d --- /dev/null +++ b/utils/sql/git/required/2016_08_26_object_size_tilt.sql @@ -0,0 +1,4 @@ +ALTER TABLE `object` + ADD COLUMN `size` FLOAT NOT NULL DEFAULT '100' AFTER `unknown84`, + ADD COLUMN `tilt_x` FLOAT NOT NULL DEFAULT '0' AFTER `size`, + ADD COLUMN `tilt_y` FLOAT NOT NULL DEFAULT '0' AFTER `tilt_x`; \ No newline at end of file diff --git a/zone/entity.cpp b/zone/entity.cpp index 2e2f79058..08e1534c8 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -478,14 +478,18 @@ void EntityList::MobProcess() size_t sz = mob_list.size(); #ifdef IDLE_WHEN_EMPTY - // spawn_events can cause spawns and deaths while zone empty. - // At the very least, process that. - if (numclients < 1) { - mob_dead = mob->CastToNPC()->GetDepop(); - } - else { + if (numclients > 0 || + mob->GetWanderType() == 4 || mob->GetWanderType() == 6) { + // Normal processing, or assuring that spawns that should + // path and depop do that. Otherwise all of these type mobs + // will be up and at starting positions when idle zone wakes up. mob_dead = !mob->Process(); } + else { + // spawn_events can cause spawns and deaths while zone empty. + // At the very least, process that. + mob_dead = mob->CastToNPC()->GetDepop(); + } #else mob_dead = !mob->Process(); #endif diff --git a/zone/mob.h b/zone/mob.h index 927ecf862..22e4bf357 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -847,6 +847,7 @@ public: inline void SetFocused(bool nState) { focused = nState; } inline const bool IsFocused() const { return focused; } inline const bool IsRoamer() const { return roamer; } + inline const int GetWanderType() const { return wandertype; } inline const bool IsRooted() const { return rooted || permarooted; } inline const bool HasVirus() const { return has_virus; } int GetSnaredAmount(); diff --git a/zone/object.cpp b/zone/object.cpp index f74d2dd0d..a9672ee4f 100644 --- a/zone/object.cpp +++ b/zone/object.cpp @@ -63,6 +63,9 @@ Object::Object(uint32 id, uint32 type, uint32 icon, const Object_Struct& object, // Set drop_id to zero - it will be set when added to zone with SetID() m_data.drop_id = 0; + m_data.size = object.size; + m_data.tilt_x = object.tilt_x; + m_data.tilt_y = object.tilt_y; } //creating a re-ocurring ground spawn. @@ -653,10 +656,12 @@ void ZoneDatabase::UpdateObject(uint32 id, uint32 type, uint32 icon, const Objec // Save new record for object std::string query = StringFormat("UPDATE object SET " "zoneid = %i, xpos = %f, ypos = %f, zpos = %f, heading = %f, " - "itemid = %i, charges = %i, objectname = '%s', type = %i, icon = %i " + "itemid = %i, charges = %i, objectname = '%s', type = %i, icon = %i, " + "size = %f, tilt_x = %f, tilt_y = %f " "WHERE id = %i", object.zone_id, object.x, object.y, object.z, object.heading, - item_id, charges, object_name, type, icon, id); + item_id, charges, object_name, type, icon, + object.size, object.tilt_x, object.tilt_y, id); safe_delete_array(object_name); auto results = QueryDatabase(query); if (!results.Success()) { @@ -750,6 +755,16 @@ float Object::GetHeadingData() return this->m_data.heading; } +float Object::GetTiltX() +{ + return this->m_data.tilt_x; +} + +float Object::GetTiltY() +{ + return this->m_data.tilt_y; +} + void Object::SetX(float pos) { this->m_data.x = pos; @@ -778,6 +793,34 @@ void Object::SetY(float pos) safe_delete(app2); } +void Object::SetTiltX(float pos) +{ + this->m_data.tilt_x = pos; + + auto app = new EQApplicationPacket(); + auto app2 = new EQApplicationPacket(); + this->CreateDeSpawnPacket(app); + this->CreateSpawnPacket(app2); + entity_list.QueueClients(0, app); + entity_list.QueueClients(0, app2); + safe_delete(app); + safe_delete(app2); +} + +void Object::SetTiltY(float pos) +{ + this->m_data.tilt_y = pos; + + auto app = new EQApplicationPacket(); + auto app2 = new EQApplicationPacket(); + this->CreateDeSpawnPacket(app); + this->CreateSpawnPacket(app2); + entity_list.QueueClients(0, app); + entity_list.QueueClients(0, app2); + safe_delete(app); + safe_delete(app2); +} + void Object::Depop() { auto app = new EQApplicationPacket(); @@ -828,7 +871,7 @@ void Object::SetModelName(const char* modelname) safe_delete(app2); } -void Object::SetSize(uint16 size) +void Object::SetSize(float size) { m_data.size = size; auto app = new EQApplicationPacket(); @@ -854,7 +897,7 @@ void Object::SetSolidType(uint16 solidtype) safe_delete(app2); } -uint16 Object::GetSize() +float Object::GetSize() { return m_data.size; } diff --git a/zone/object.h b/zone/object.h index c7ebdd677..896fc4276 100644 --- a/zone/object.h +++ b/zone/object.h @@ -154,10 +154,14 @@ public: void SetX(float pos); void SetY(float pos); void SetZ(float pos); + void SetTiltX(float pos); + void SetTiltY(float pos); + float GetTiltX(); + float GetTiltY(); void SetModelName(const char* modelname); const char* GetModelName(); - uint16 GetSize(); - void SetSize(uint16 size); + float GetSize(); + void SetSize(float size); uint16 GetSolidType(); void SetSolidType(uint16 size); diff --git a/zone/perl_object.cpp b/zone/perl_object.cpp index be52fef1d..f8fc9a4ee 100644 --- a/zone/perl_object.cpp +++ b/zone/perl_object.cpp @@ -968,7 +968,7 @@ XS(XS_Object_GetSize) Perl_croak(aTHX_ "Usage: Object::GetSize(THIS)"); { Object * THIS; - uint16 RETVAL; + float RETVAL; dXSTARG; if (sv_derived_from(ST(0), "Object")) { @@ -981,7 +981,7 @@ XS(XS_Object_GetSize) Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); RETVAL = THIS->GetSize(); - XSprePUSH; PUSHu((UV)RETVAL); + XSprePUSH; PUSHn((double)RETVAL); } XSRETURN(1); } @@ -995,7 +995,7 @@ XS(XS_Object_SetSize) Perl_croak(aTHX_ "Usage: Object::SetSize(THIS, type)"); { Object * THIS; - uint16 size = (uint16)SvUV(ST(1)); + float size = (float)SvNV(ST(1)); if (sv_derived_from(ST(0), "Object")) { IV tmp = SvIV((SV*)SvRV(ST(0))); @@ -1011,6 +1011,106 @@ XS(XS_Object_SetSize) XSRETURN_EMPTY; } +XS(XS_Object_SetTiltX); /* prototype to pass -Wmissing-prototypes */ +XS(XS_Object_SetTiltX) +{ + dXSARGS; + if (items != 2) + Perl_croak(aTHX_ "Usage: Object::SetTiltX(THIS, pos)"); + { + Object * THIS; + float pos = (float)SvNV(ST(1)); + + if (sv_derived_from(ST(0), "Object")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(Object *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type Object"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + THIS->SetTiltX(pos); + } + XSRETURN_EMPTY; +} + +XS(XS_Object_SetTiltY); /* prototype to pass -Wmissing-prototypes */ +XS(XS_Object_SetTiltY) +{ + dXSARGS; + if (items != 2) + Perl_croak(aTHX_ "Usage: Object::SetTiltY(THIS, pos)"); + { + Object * THIS; + float pos = (float)SvNV(ST(1)); + + if (sv_derived_from(ST(0), "Object")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(Object *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type Object"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + THIS->SetTiltY(pos); + } + XSRETURN_EMPTY; +} + +XS(XS_Object_GetTiltX); /* prototype to pass -Wmissing-prototypes */ +XS(XS_Object_GetTiltX) +{ + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: Object::GetSize(THIS)"); + { + Object * THIS; + float RETVAL; + dXSTARG; + + if (sv_derived_from(ST(0), "Object")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(Object *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type Object"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + RETVAL = THIS->GetTiltX(); + XSprePUSH; PUSHn((double)RETVAL); + } + XSRETURN(1); +} + +XS(XS_Object_GetTiltY); /* prototype to pass -Wmissing-prototypes */ +XS(XS_Object_GetTiltY) +{ + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: Object::GetSize(THIS)"); + { + Object * THIS; + float RETVAL; + dXSTARG; + + if (sv_derived_from(ST(0), "Object")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(Object *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type Object"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + RETVAL = THIS->GetTiltY(); + XSprePUSH; PUSHn((double)RETVAL); + } + XSRETURN(1); +} + #ifdef __cplusplus extern "C" #endif @@ -1066,6 +1166,10 @@ XS(boot_Object) newXSproto(strcpy(buf, "GetSolidType"),XS_Object_GetSolidType, file, "$"); newXSproto(strcpy(buf, "SetSize"),XS_Object_SetSize, file, "$$"); newXSproto(strcpy(buf, "GetSize"),XS_Object_GetSize, file, "$"); + newXSproto(strcpy(buf, "SetTiltX"),XS_Object_SetTiltX, file, "$$"); + newXSproto(strcpy(buf, "SetTiltY"),XS_Object_SetTiltY, file, "$"); + newXSproto(strcpy(buf, "GetTiltX"),XS_Object_GetTiltX, file, "$$"); + newXSproto(strcpy(buf, "GetTiltY"),XS_Object_GetTiltY, file, "$"); XSRETURN_YES; } #endif //EMBPERL_XS_CLASSES diff --git a/zone/zone.cpp b/zone/zone.cpp index 1165d7e9b..3dd8e55d8 100644 --- a/zone/zone.cpp +++ b/zone/zone.cpp @@ -161,7 +161,8 @@ bool Zone::LoadZoneObjects() { std::string query = StringFormat("SELECT id, zoneid, xpos, ypos, zpos, heading, " "itemid, charges, objectname, type, icon, unknown08, " - "unknown10, unknown20, unknown24, unknown76 fROM object " + "unknown10, unknown20, unknown24, unknown76, size, tilt_x, " + "tilt_y FROM object " "WHERE zoneid = %i AND (version = %u OR version = -1)", zoneid, instanceversion); auto results = database.QueryDatabase(query); @@ -241,11 +242,14 @@ bool Zone::LoadZoneObjects() { data.object_type = type; data.linked_list_addr[0] = 0; data.linked_list_addr[1] = 0; - data.size = (uint32)atoi(row[11]); + data.solidtype = (uint32)atoi(row[12]); data.unknown020 = (uint32)atoi(row[13]); data.unknown024 = (uint32)atoi(row[14]); data.unknown076 = (uint32)atoi(row[15]); + data.size = atof(row[16]); + data.tilt_x = atof(row[17]); + data.tilt_y = atof(row[18]); data.unknown084 = 0; ItemInst* inst = nullptr;