{sec})'); Aseco::addChatCommand('y', 'Votes Yes for a TMX track or chat-based vote'); Aseco::addChatCommand('history', 'Shows the 10 most recently played tracks'); Aseco::addChatCommand('xlist', 'Lists tracks on TMX (see: /xlist help)'); // called @ onEndRace function rasp_endrace($aseco, $data) { global $rasp, $tmxadd, $jukebox, $jukebox_check, $jukebox_skipleft, $jukebox_adminnoskip, $jukebox_in_window, $tmxplaying, $autosave_matchsettings, $replays_counter, $replays_total; // check for relay server if ($aseco->server->isrelay) return; // check for & cancel ongoing TMX vote if (!empty($tmxadd)) { $aseco->console('Vote by {1} to add {2} reset!', $tmxadd['login'], stripColors($tmxadd['name'], false)); $message = $rasp->messages['JUKEBOX_CANCEL'][0]; if ($jukebox_in_window && function_exists('send_window_message')) send_window_message($aseco, $message, true); else $aseco->client->query('ChatSendServerMessage', $aseco->formatColors($message)); $tmxadd = array(); // disable all vote panels if ($aseco->server->getGame() == 'TMF') allvotepanels_off($aseco); } // reset UID check $jukebox_check = ''; // check for jukeboxed track(s) if (!empty($jukebox)) { if ($aseco->debug) { $aseco->console_text('rasp_endrace step1 - $jukebox:' . CRLF . print_r($jukebox, true)); } // skip jukeboxed track(s) if their requesters left if ($jukebox_skipleft) { // go over jukeboxed tracks while ($next = array_shift($jukebox)) { // check if requester is still online, or was admin foreach ($aseco->server->players->player_list as $pl) { if ($pl->login == $next['Login'] || ($jukebox_adminnoskip && $aseco->isAnyAdminL($next['Login']))) { // found player, so proceed to play this track // put it back for rasp_newtrack to remove $uid = $next['uid']; $jukebox = array_merge(array($uid => $next), $jukebox); break 2; // exit foreach & while } } // player offline, so report skip $message = '{RASP Jukebox} Skipping Next Challenge ' . stripColors($next['Name'], false) . ' because requester ' . stripColors($next['Nick'], false) . ' left'; $aseco->console_text($message); $message = formatText($rasp->messages['JUKEBOX_SKIPLEFT'][0], stripColors($next['Name']), stripColors($next['Nick'])); if ($jukebox_in_window && function_exists('send_window_message')) send_window_message($aseco, $message, true); else $aseco->client->query('ChatSendServerMessage', $aseco->formatColors($message)); // throw 'jukebox changed' event $aseco->releaseEvent('onJukeboxChanged', array('skip', $next)); } // if jukebox went empty, bail out if (!isset($next)) return; } else { // just play the next track $next = array_shift($jukebox); // put it back for rasp_newtrack to remove $uid = $next['uid']; $jukebox = array_merge(array($uid => $next), $jukebox); } // remember UID of next track to check whether it really plays $jukebox_check = $uid; if ($aseco->debug) { $aseco->console_text('rasp_endrace step2 - $jukebox_check: ' . $jukebox_check); $aseco->console_text('rasp_endrace step2 - $jukebox:' . CRLF . print_r($jukebox, true)); } // if a TMX track, add it to server if ($next['tmx']) { if ($aseco->debug) { $aseco->console_text('{RASP Jukebox} ' . $next['source'] . ' challenge filename is ' . $next['FileName']); } $rtn = $aseco->client->query('AddChallenge', $next['FileName']); if (!$rtn) { trigger_error('[' . $aseco->client->getErrorCode() . '] AddChallenge - ' . $aseco->client->getErrorMessage(), E_USER_WARNING); return; } else { // throw 'tracklist changed' event $aseco->releaseEvent('onTracklistChanged', array('juke', $next['FileName'])); } } // select jukebox/TMX track as next challenge $rtn = $aseco->client->query('ChooseNextChallenge', $next['FileName']); if (!$rtn) { trigger_error('[' . $aseco->client->getErrorCode() . '] ChooseNextChallenge - ' . $aseco->client->getErrorMessage(), E_USER_WARNING); } else { // check for TMF United if ($aseco->server->getGame() == 'TMF' && $aseco->server->packmask != 'Stadium') { // report track change from TMX or jukebox if ($next['tmx']) { $logmsg = '{RASP Jukebox} Setting Next Challenge to [' . $next['Env'] . '] ' . stripColors($next['Name'], false) . ', file downloaded from ' . $next['source']; // remember it for later removal $tmxplaying = $next['FileName']; } else { $logmsg = '{RASP Jukebox} Setting Next Challenge to [' . $next['Env'] . '] ' . stripColors($next['Name'], false) . ', requested by ' . stripColors($next['Nick'], false); } $message = formatText($rasp->messages['JUKEBOX_NEXTENV'][0], $next['Env'], stripColors($next['Name']), stripColors($next['Nick'])); } else { // TMN(F) // report track change from TMX or jukebox if ($next['tmx']) { $logmsg = '{RASP Jukebox} Setting Next Challenge to ' . stripColors($next['Name'], false) . ', file downloaded from ' . $next['source']; // remember it for later removal $tmxplaying = $next['FileName']; } else { $logmsg = '{RASP Jukebox} Setting Next Challenge to ' . stripColors($next['Name'], false) . ', requested by ' . stripColors($next['Nick'], false); } $message = formatText($rasp->messages['JUKEBOX_NEXT'][0], stripColors($next['Name']), stripColors($next['Nick'])); } $aseco->console_text($logmsg); if ($jukebox_in_window && function_exists('send_window_message')) send_window_message($aseco, $message, true); else $aseco->client->query('ChatSendServerMessage', $aseco->formatColors($message)); } } else { // reset just in case current track was replayed $replays_counter = 0; $replays_total = 0; } // check for autosaving tracklist if ($autosave_matchsettings != '') { $rtn = $aseco->client->query('SaveMatchSettings', 'MatchSettings/' . $autosave_matchsettings); if (!$rtn) { trigger_error('[' . $aseco->client->getErrorCode() . '] SaveMatchSettings - ' . $aseco->client->getErrorMessage(), E_USER_WARNING); } else { // should a random filter be added? if ($aseco->settings['writetracklist_random']) { $tracksfile = $aseco->server->trackdir . 'MatchSettings/' . $autosave_matchsettings; // read the match settings file if (!$list = @file_get_contents($tracksfile)) { trigger_error('Could not read match settings file ' . $tracksfile . ' !', E_USER_WARNING); } else { // insert random filter after section $list = preg_replace('/<\/gameinfos>/', '$0' . CRLF . CRLF . "\t" . CRLF . "\t\t1" . CRLF . "\t", $list); // write out the match settings file if (!@file_put_contents($tracksfile, $list)) { trigger_error('Could not write match settings file ' . $tracksfile . ' !', E_USER_WARNING); } } } } } } // rasp_endrace // called @ onNewChallenge function rasp_newtrack($aseco, $data) { global $rasp, $buffersize, $jukebox, $jb_buffer, $tmxplaying, $tmxplayed, $jukebox_check, $jukebox_failed, $jukebox_permadd, $replays_counter, $replays_total; // check for relay server if ($aseco->server->isrelay) return; // don't duplicate replayed track in history if (!empty($jb_buffer)) { $previous = array_pop($jb_buffer); // put back previous track if different if ($previous != $data->uid) $jb_buffer[] = $previous; } // remember current track in history if (count($jb_buffer) >= $buffersize) { // drop oldest track if buffer full array_shift($jb_buffer); } // append current track to history $jb_buffer[] = $data->uid; // write track history to file in case of XASECO restart if ($fp = @fopen($aseco->server->trackdir . $aseco->settings['trackhist_file'], 'wb')) { foreach ($jb_buffer as $uid) fwrite($fp, $uid . CRLF); fclose($fp); } else { trigger_error('Could not write track history file ' . $aseco->server->trackdir . $aseco->settings['trackhist_file'] . ' !', E_USER_WARNING); } // process jukebox if (!empty($jukebox)) { if ($aseco->debug) { $aseco->console_text('rasp_newtrack step1 - $data->uid: ' . $data->uid); $aseco->console_text('rasp_newtrack step1 - $jukebox_check: ' . $jukebox_check); $aseco->console_text('rasp_newtrack step1 - $jukebox:' . CRLF . print_r($jukebox, true)); } // look for current track in jukebox if (array_key_exists($data->uid, $jukebox)) { if ($aseco->debug) { $message = '{RASP Jukebox} Current Challenge ' . stripColors($jukebox[$data->uid]['Name'], false) . ' loaded - index: ' . array_search($data->uid, array_keys($jukebox)); $aseco->console_text($message); } // check for /replay-ed track if ($jukebox[$data->uid]['source'] == 'Replay') $replays_counter++; else $replays_counter = 0; if (substr($jukebox[$data->uid]['source'], -6) == 'Replay') // AdminReplay $replays_total++; else $replays_total = 0; // remove loaded track $play = $jukebox[$data->uid]; unset($jukebox[$data->uid]); if ($aseco->debug) { $aseco->console_text('rasp_newtrack step2a - $jukebox:' . CRLF . print_r($jukebox, true)); } // throw 'jukebox changed' event $aseco->releaseEvent('onJukeboxChanged', array('play', $play)); } else { // look for intended track in jukebox if ($jukebox_check != '') { if (array_key_exists($jukebox_check, $jukebox)) { if ($aseco->debug) { $message = '{RASP Jukebox} Intended Challenge ' . stripColors($jukebox[$jukebox_check]['Name'], false) . ' dropped - index: ' . array_search($jukebox_check, array_keys($jukebox)); $aseco->console_text($message); } // drop stuck track $stuck = $jukebox[$jukebox_check]; unset($jukebox[$jukebox_check]); if ($aseco->debug) { $aseco->console_text('rasp_newtrack step2b - $jukebox:' . CRLF . print_r($jukebox, true)); } // throw 'jukebox changed' event $aseco->releaseEvent('onJukeboxChanged', array('drop', $stuck)); } else { if ($aseco->debug) { $message = '{RASP Jukebox} Intended Challenge ' . $jukebox_check . ' not found!'; $aseco->console_text($message); } } } } } // remove previous TMX track from server if ($tmxplayed) { // unless it is permanent if (!$jukebox_permadd) { if ($aseco->debug) { $aseco->console_text('rasp_newtrack step3 - remove: ' . $tmxplayed); } $rtn = $aseco->client->query('RemoveChallenge', $tmxplayed); if (!$rtn) { trigger_error('[' . $aseco->client->getErrorCode() . '] RemoveChallenge - ' . $aseco->client->getErrorMessage(), E_USER_WARNING); } else { // throw 'tracklist changed' event $aseco->releaseEvent('onTracklistChanged', array('unjuke', $tmxplayed)); } } $tmxplayed = false; } // check whether current track was from TMX if ($tmxplaying) { // remember it for removal afterwards $tmxplayed = $tmxplaying; $tmxplaying = false; } } // rasp_newtrack // calls function disp_recs() from chat.records2.php function chat_list($aseco, $command) { global $feature_karma; // from rasp.settings.php $player = $command['author']; $login = $player->login; // check for relay server if ($aseco->server->isrelay) { $message = formatText($aseco->getChatMessage('NOTONRELAY')); $aseco->client->query('ChatSendServerMessageToLogin', $aseco->formatColors($message), $login); return; } // split params into array $arglist = preg_replace('/ +/', ' ', $command['params']); $command['params'] = explode(' ', $arglist); $cmdcount = count($command['params']); if ($cmdcount == 1 && $command['params'][0] == 'help') { if ($aseco->server->getGame() == 'TMN') { $help = '{#black}/list$g will show tracks in rotation on the server:' . LF; $help .= ' - {#black}help$g, displays this help information' . LF; $help .= ' - {#black}nofinish$g, tracks you haven\'t completed' . LF; $help .= ' - {#black}norank$g, tracks you don\'t have a rank on' . LF; $help .= ' - {#black}nogold$g, tracks you didn\'t beat gold time on' . LF; $help .= ' - {#black}noauthor$g, tracks you didn\'t beat author time on' . LF; $help .= ' - {#black}norecent$g, tracks you didn\'t play recently' . LF; $help .= ' - {#black}best$g/{#black}worst$g, tracks with your best/worst records' . LF; $help .= ' - {#black}longest$g/{#black}shortest$g, the longest/shortest tracks' . LF; $help .= ' - {#black}newest$g/{#black}oldest #$g, newest/oldest # tracks (def: 50)' . LF; $help .= ' - {#black}xxx$g, where xxx is part of a track or author name' . LF; if ($feature_karma) { $help .= ' - {#black}novote$g, tracks you didn\'t karma vote for' . LF; $help .= ' - {#black}karma +/-#$g, display all tracks with karma >= or <=' . LF . ' given value (example: {#black}/list karma -3$g shows all' . LF . ' tracks with karma equal or worse than -3)' . LF; } $help .= LF . 'Pick an Id number from the list, and use {#black}/jukebox #'; // display popup message $aseco->client->query('SendDisplayServerMessageToLogin', $login, $aseco->formatColors($help), 'OK', '', 0); } elseif ($aseco->server->getGame() == 'TMF') { $header = '{#black}/list$g will show tracks in rotation on the server:'; $help = array(); $help[] = array('...', '{#black}help', 'Displays this help information'); $help[] = array('...', '{#black}nofinish', 'Shows tracks you haven\'t completed'); $help[] = array('...', '{#black}norank', 'Shows tracks you don\'t have a rank on'); $help[] = array('...', '{#black}nogold', 'Shows tracks you didn\'t beat gold ' . ($aseco->server->gameinfo->mode == Gameinfo::STNT ? 'score on' : 'time on')); $help[] = array('...', '{#black}noauthor', 'Shows tracks you didn\'t beat author '. ($aseco->server->gameinfo->mode == Gameinfo::STNT ? 'score on' : 'time on')); $help[] = array('...', '{#black}norecent', 'Shows tracks you didn\'t play recently'); $help[] = array('...', '{#black}best$g/{#black}worst', 'Shows tracks with your best/worst records'); if ($aseco->server->gameinfo->mode != Gameinfo::STNT) { $help[] = array('...', '{#black}longest$g/{#black}shortest', 'Shows the longest/shortest tracks'); } $help[] = array('...', '{#black}newest$g/{#black}oldest #', 'Shows newest/oldest # tracks (def: 50)'); $help[] = array('...', '{#black}xxx', 'Where xxx is part of a track or author name'); if ($aseco->server->packmask != 'Stadium') { $help[] = array('...', '{#black}env:zzz', 'Where zzz is an environment from: stadium,'); $help[] = array('', '', 'bay,coast,island,alpine/snow,desert/speed,rally'); $help[] = array('...', '{#black}xxx env:zzz', 'Combines the name and environment searches'); } if ($feature_karma) { $help[] = array('...', '{#black}novote', 'Shows tracks you didn\'t karma vote for'); $help[] = array('...', '{#black}karma +/-#', 'Shows all tracks with karma >= or <='); $help[] = array('', '', 'given value (example: {#black}/list karma -3$g shows all'); $help[] = array('', '', 'tracks with karma equal or worse than -3)'); } $help[] = array(); $help[] = array('Pick an Id number from the list, and use {#black}/jukebox #'); // display ManiaLink message display_manialink($login, $header, array('Icons64x64_1', 'TrackInfo', -0.01), $help, array(1.1, 0.05, 0.3, 0.75), 'OK'); } return; } elseif ($cmdcount == 1 && $command['params'][0] == 'nofinish') { getChallengesNoFinish($player); } elseif ($cmdcount == 1 && $command['params'][0] == 'norank') { getChallengesNoRank($player); } elseif ($cmdcount == 1 && $command['params'][0] == 'nogold') { getChallengesNoGold($player); } elseif ($cmdcount == 1 && $command['params'][0] == 'noauthor') { getChallengesNoAuthor($player); } elseif ($cmdcount == 1 && $command['params'][0] == 'norecent') { getChallengesNoRecent($player); } elseif ($cmdcount == 1 && $command['params'][0] == 'best') { // avoid interference from possible parameters $command['params'] = ''; // display player records, best first disp_recs($aseco, $command, true); // from chat.records2.php return; } elseif ($cmdcount == 1 && $command['params'][0] == 'worst') { // avoid interference from possible parameters $command['params'] = ''; // display player records, worst first disp_recs($aseco, $command, false); // from chat.records2.php return; } elseif ($cmdcount == 1 && $command['params'][0] == 'longest') { getChallengesByLength($player, false); } elseif ($cmdcount == 1 && $command['params'][0] == 'shortest') { getChallengesByLength($player, true); } elseif ($cmdcount >= 1 && $command['params'][0] == 'newest') { $count = 50; // default if ($cmdcount == 2 && is_numeric($command['params'][1]) && $command['params'][1] > 0) $count = intval($command['params'][1]); getChallengesByAdd($player, true, $count); } elseif ($cmdcount >= 1 && $command['params'][0] == 'oldest') { $count = 50; // default if ($cmdcount == 2 && is_numeric($command['params'][1]) && $command['params'][1] > 0) $count = intval($command['params'][1]); getChallengesByAdd($player, false, $count); } elseif ($cmdcount == 1 && $command['params'][0] == 'novote' && $feature_karma) { getChallengesNoVote($player); } elseif ($cmdcount == 2 && $command['params'][0] == 'karma' && $feature_karma) { $karmaval = intval($command['params'][1]); getChallengesByKarma($player, $karmaval); } elseif ($cmdcount >= 1 && strlen($command['params'][0]) > 0) { // check for TMUF if ($aseco->server->getGame() == 'TMF' && $aseco->server->packmask != 'Stadium') { $env = '*'; // wildcard // find and delete optional env: parameter foreach ($command['params'] as &$param) { if (strtolower(substr($param, 0, 4)) == 'env:') { $env = substr($param, 4); // map external to internal envs, allowing abbreviations if (stripos('desert', $env) === 0) $env = 'speed'; elseif (stripos('snow', $env) === 0) $env = 'alpine'; $param = ''; // drop env:zzz from arglist } } // rebuild parameter list $arglist = trim(implode(' ', $command['params'])); // set wildcard name if searching for env if ($arglist == '') $arglist = '*'; getAllChallenges($player, $arglist, $env); } else { // TMN(F)/TMS/TMO getAllChallenges($player, $arglist, '*'); // wildcard } } else { getAllChallenges($player, '*', '*'); // wildcards } if (empty($player->tracklist)) { $message = '{#server}> {#error}No tracks found, try again!'; $aseco->client->query('ChatSendServerMessageToLogin', $aseco->formatColors($message), $login); return; } if ($aseco->server->getGame() == 'TMN') { // display popup message if (count($player->msgs) == 2) { $aseco->client->query('SendDisplayServerMessageToLogin', $login, $player->msgs[1], 'OK', '', 0); } else { // > 2 $aseco->client->query('SendDisplayServerMessageToLogin', $login, $player->msgs[1], 'Close', 'Next', 0); } } elseif ($aseco->server->getGame() == 'TMF') { // display ManiaLink message display_manialink_multi($player); } } // chat_list function chat_jukebox($aseco, $command) { global $rasp, $feature_jukebox, $jukebox_in_window, $jukebox, $jb_buffer; $player = $command['author']; $login = $player->login; // check for relay server if ($aseco->server->isrelay) { $message = formatText($aseco->getChatMessage('NOTONRELAY')); $aseco->client->query('ChatSendServerMessageToLogin', $aseco->formatColors($message), $login); return; } if ($feature_jukebox || $aseco->allowAbility($player, 'chat_jukebox')) { // check parameter $param = $command['params']; if (is_numeric($param) && $param >= 0) { if (empty($player->tracklist)) { $message = $rasp->messages['LIST_HELP'][0]; $aseco->client->query('ChatSendServerMessageToLogin', $aseco->formatColors($message), $login); return; } // check for track by this player in jukebox if (!$aseco->allowAbility($player, 'chat_jb_multi')) { foreach ($jukebox as $key) { if ($login == $key['Login']) { $message = $rasp->messages['JUKEBOX_ALREADY'][0]; $aseco->client->query('ChatSendServerMessageToLogin', $aseco->formatColors($message), $login); return; } } } // find track by given # $jid = ltrim($param, '0'); $jid--; if (array_key_exists($jid, $player->tracklist)) { $uid = $player->tracklist[$jid]['uid']; // check if track is already queued in jukebox if (array_key_exists($uid, $jukebox)) { // find by uid in jukebox $message = $rasp->messages['JUKEBOX_DUPL'][0]; $aseco->client->query('ChatSendServerMessageToLogin', $aseco->formatColors($message), $login); return; } // check if track was recently played elseif (in_array($uid, $jb_buffer)) { $message = $rasp->messages['JUKEBOX_REPEAT'][0]; $aseco->client->query('ChatSendServerMessageToLogin', $aseco->formatColors($message), $login); // if not an admin with this ability, bail out if (!$aseco->allowAbility($player, 'chat_jb_recent')) return; } // check track vs. server settings if ($aseco->server->getGame() == 'TMF') $rtn = $aseco->client->query('CheckChallengeForCurrentServerParams', $player->tracklist[$jid]['filename']); else $rtn = true; if (!$rtn) { trigger_error('[' . $aseco->client->getErrorCode() . '] CheckChallengeForCurrentServerParams - ' . $aseco->client->getErrorMessage(), E_USER_WARNING); $message = formatText($rasp->messages['JUKEBOX_IGNORED'][0], stripColors($player->tracklist[$jid]['name']), $aseco->client->getErrorMessage()); $aseco->client->query('ChatSendServerMessageToLogin', $aseco->formatColors($message), $login); } else { // add track to jukebox $jukebox[$uid]['FileName'] = $player->tracklist[$jid]['filename']; $jukebox[$uid]['Name'] = $player->tracklist[$jid]['name']; $jukebox[$uid]['Env'] = $player->tracklist[$jid]['environment']; $jukebox[$uid]['Login'] = $player->login; $jukebox[$uid]['Nick'] = $player->nickname; $jukebox[$uid]['source'] = 'Jukebox'; $jukebox[$uid]['tmx'] = false; $jukebox[$uid]['uid'] = $uid; $message = formatText($rasp->messages['JUKEBOX'][0], stripColors($player->tracklist[$jid]['name']), stripColors($player->nickname)); if ($jukebox_in_window && function_exists('send_window_message')) send_window_message($aseco, $message, false); else $aseco->client->query('ChatSendServerMessage', $aseco->formatColors($message)); // throw 'jukebox changed' event $aseco->releaseEvent('onJukeboxChanged', array('add', $jukebox[$uid])); } } else { $message = $rasp->messages['JUKEBOX_NOTFOUND'][0]; $aseco->client->query('ChatSendServerMessageToLogin', $aseco->formatColors($message), $login); } } elseif ($param == 'list') { if (!empty($jukebox)) { $message = $rasp->messages['JUKEBOX_LIST'][0]; $i = 1; foreach ($jukebox as $item) { $message .= '{#highlite}' . $i . '{#emotic}.[{#highlite}' . stripColors($item['Name']) . '{#emotic}], '; $i++; } $message = substr($message, 0, strlen($message)-2); // strip trailing ", " $aseco->client->query('ChatSendServerMessageToLogin', $aseco->formatColors($message), $login); } else { $message = $rasp->messages['JUKEBOX_EMPTY'][0]; $aseco->client->query('ChatSendServerMessageToLogin', $aseco->formatColors($message), $login); } } elseif ($param == 'display') { if (!empty($jukebox)) { if ($aseco->server->getGame() == 'TMN') { $head = 'Upcoming tracks in the jukebox:' . LF . 'Id Name / Requester' . LF; $msg = ''; $tid = 1; $lines = 0; $player->msgs = array(); $player->msgs[0] = 1; foreach ($jukebox as $item) { $trackname = $item['Name']; if (!$aseco->settings['lists_colortracks']) $trackname = stripColors($trackname); $msg .= '$g' . str_pad($tid, 2, '0', STR_PAD_LEFT) . '. {#black}' . $trackname . '$z / {#black}' . stripColors($item['Nick']) . LF; $tid++; if (++$lines > 9) { $player->msgs[] = $aseco->formatColors($head . $msg); $lines = 0; $msg = ''; } } // add if last batch exists if ($msg != '') $player->msgs[] = $aseco->formatColors($head . $msg); // display popup message if (count($player->msgs) == 2) { $aseco->client->query('SendDisplayServerMessageToLogin', $login, $player->msgs[1], 'OK', '', 0); } else { // > 2 $aseco->client->query('SendDisplayServerMessageToLogin', $login, $player->msgs[1], 'Close', 'Next', 0); } } elseif ($aseco->server->getGame() == 'TMF') { // determine admin ability to drop all jukeboxed tracks $dropall = $aseco->allowAbility($player, 'dropjukebox'); $head = 'Upcoming tracks in the jukebox:'; $page = array(); if ($aseco->server->packmask != 'Stadium') if ($aseco->settings['clickable_lists']) $page[] = array('Id', 'Name (click to drop)', 'Env', 'Requester'); else $page[] = array('Id', 'Name', 'Env', 'Requester'); else if ($aseco->settings['clickable_lists']) $page[] = array('Id', 'Name (click to drop)', 'Requester'); else $page[] = array('Id', 'Name', 'Requester'); $tid = 1; $lines = 0; $player->msgs = array(); // reserve extra width for $w tags $extra = ($aseco->settings['lists_colortracks'] ? 0.2 : 0); if ($aseco->server->packmask != 'Stadium') $player->msgs[0] = array(1, $head, array(1.25+$extra, 0.1, 0.6+$extra, 0.15, 0.4), array('Icons128x128_1', 'LoadTrack', 0.02)); else $player->msgs[0] = array(1, $head, array(1.10+$extra, 0.1, 0.6+$extra, 0.4), array('Icons128x128_1', 'LoadTrack', 0.02)); foreach ($jukebox as $item) { $trackname = $item['Name']; if (!$aseco->settings['lists_colortracks']) $trackname = stripColors($trackname); // add clickable button if admin with 'dropjukebox' ability or track by this player if ($aseco->settings['clickable_lists'] && $tid <= 100 && ($dropall || $item['Login'] == $login)) $trackname = array('{#black}' . $trackname, -2000-$tid); // action id else $trackname = '{#black}' . $trackname; if ($aseco->server->packmask != 'Stadium') $page[] = array(str_pad($tid, 2, '0', STR_PAD_LEFT) . '.', $trackname, $item['Env'], '{#black}' . stripColors($item['Nick'])); else $page[] = array(str_pad($tid, 2, '0', STR_PAD_LEFT) . '.', $trackname, '{#black}' . stripColors($item['Nick'])); $tid++; if (++$lines > 14) { if ($aseco->allowAbility($player, 'clearjukebox')) { $page[] = array(); if ($aseco->server->packmask != 'Stadium') $page[] = array('', array('{#emotic} Clear Entire Jukebox', 20), '', ''); // action id else $page[] = array('', array('{#emotic} Clear Entire Jukebox', 20), ''); // action id } $player->msgs[] = $page; $lines = 0; $page = array(); if ($aseco->server->packmask != 'Stadium') if ($aseco->settings['clickable_lists']) $page[] = array('Id', 'Name (click to drop)', 'Env', 'Requester'); else $page[] = array('Id', 'Name', 'Env', 'Requester'); else if ($aseco->settings['clickable_lists']) $page[] = array('Id', 'Name (click to drop)', 'Requester'); else $page[] = array('Id', 'Name', 'Requester'); } } // add if last batch exists if (count($page) > 1) { if ($aseco->allowAbility($player, 'clearjukebox')) { $page[] = array(); if ($aseco->server->packmask != 'Stadium') $page[] = array('', array('{#emotic} Clear Entire Jukebox', 20), '', ''); // action id else $page[] = array('', array('{#emotic} Clear Entire Jukebox', 20), ''); // action id } $player->msgs[] = $page; } // display ManiaLink message display_manialink_multi($player); } } else { $message = $rasp->messages['JUKEBOX_EMPTY'][0]; $aseco->client->query('ChatSendServerMessageToLogin', $aseco->formatColors($message), $login); } } elseif ($param == 'drop') { // find track by current player $uid = ''; foreach ($jukebox as $item) { if ($item['Login'] == $login) { $name = $item['Name']; $uid = $item['uid']; break; } } if ($uid) { // drop it from the jukebox $drop = $jukebox[$uid]; unset($jukebox[$uid]); $message = formatText($rasp->messages['JUKEBOX_DROP'][0], stripColors($player->nickname), stripColors($name)); if ($jukebox_in_window && function_exists('send_window_message')) send_window_message($aseco, $message, false); else $aseco->client->query('ChatSendServerMessage', $aseco->formatColors($message)); // throw 'jukebox changed' event $aseco->releaseEvent('onJukeboxChanged', array('drop', $drop)); } else { $message = $rasp->messages['JUKEBOX_NODROP'][0]; $aseco->client->query('ChatSendServerMessageToLogin', $aseco->formatColors($message), $login); } } elseif ($param == 'help') { if ($aseco->server->getGame() == 'TMN') { $help = '{#black}/jukebox$g will add a track to the jukebox' . LF; $help .= ' - {#black}help$g, displays this help information' . LF; $help .= ' - {#black}list$g, shows upcoming tracks' . LF; $help .= ' - {#black}display$g, displays upcoming tracks' . LF . ' and requesters' . LF; $help .= ' - {#black}drop$g, drops your currently added track' . LF . ' so you can jukebox another' . LF; $help .= ' - {#black}##$g, adds a track where ## is the track Id' . LF . ' from your most recent {#black}/list$g command'; // display popup message $aseco->client->query('SendDisplayServerMessageToLogin', $login, $aseco->formatColors($help), 'OK', '', 0); } elseif ($aseco->server->getGame() == 'TMF') { $header = '{#black}/jukebox$g will add a track to the jukebox:'; $help = array(); $help[] = array('...', '{#black}help', 'Displays this help information'); $help[] = array('...', '{#black}list', 'Shows upcoming tracks'); $help[] = array('...', '{#black}display', 'Displays upcoming tracks and requesters'); $help[] = array('...', '{#black}drop', 'Drops your currently added track'); $help[] = array('...', '{#black}##', 'Adds a track where ## is the track Id'); $help[] = array('', '', 'from your most recent {#black}/list$g command'); // display ManiaLink message display_manialink($login, $header, array('Icons64x64_1', 'TrackInfo', -0.01), $help, array(0.9, 0.05, 0.15, 0.7), 'OK'); } } else { $message = $rasp->messages['JUKEBOX_HELP'][0]; $aseco->client->query('ChatSendServerMessageToLogin', $aseco->formatColors($message), $login); } } else { $message = $rasp->messages['NO_JUKEBOX'][0]; $aseco->client->query('ChatSendServerMessageToLogin', $aseco->formatColors($message), $login); } } // chat_jukebox function chat_autojuke($aseco, $command) { global $feature_karma, $buffersize, $jukebox, $jb_buffer; // from rasp.settings.php $player = $command['author']; $login = $player->login; // check for relay server if ($aseco->server->isrelay) { $message = formatText($aseco->getChatMessage('NOTONRELAY')); $aseco->client->query('ChatSendServerMessageToLogin', $aseco->formatColors($message), $login); return; } // split params into array $command['params'] = explode(' ', preg_replace('/ +/', ' ', $command['params'])); $cmdcount = count($command['params']); if ($cmdcount == 1 && $command['params'][0] == 'help') { if ($aseco->server->getGame() == 'TMN') { $help = '{#black}/autojuke$g will jukebox a track from /list selection:' . LF; $help .= ' - {#black}help$g, displays this help information' . LF; $help .= ' - {#black}nofinish$g, tracks you haven\'t completed' . LF; $help .= ' - {#black}norank$g, tracks you don\'t have a rank on' . LF; $help .= ' - {#black}nogold$g, tracks you didn\'t beat gold time on' . LF; $help .= ' - {#black}noauthor$g, tracks you didn\'t beat author time on' . LF; $help .= ' - {#black}norecent$g, tracks you didn\'t play recently' . LF; $help .= ' - {#black}longest$g/{#black}shortest$g, the longest/shortest tracks' . LF; $help .= ' - {#black}newest$g/{#black}oldest$g, the newest/oldest tracks' . LF; if ($feature_karma) { $help .= ' - {#black}novote$g, tracks you didn\'t karma vote for' . LF; } $help .= LF . 'The jukeboxed track is the first one from the' . LF . 'chosen selection that is not in the track history.'; // display popup message $aseco->client->query('SendDisplayServerMessageToLogin', $login, $aseco->formatColors($help), 'OK', '', 0); } elseif ($aseco->server->getGame() == 'TMF') { $header = '{#black}/autojuke$g will jukebox a track from /list selection:'; $help = array(); $help[] = array('...', '{#black}help', 'Displays this help information'); $help[] = array('...', '{#black}nofinish', 'Selects tracks you haven\'t completed'); $help[] = array('...', '{#black}norank', 'Selects tracks you don\'t have a rank on'); $help[] = array('...', '{#black}nogold', 'Selects tracks you didn\'t beat gold ' . ($aseco->server->gameinfo->mode == Gameinfo::STNT ? 'score on' : 'time on')); $help[] = array('...', '{#black}noauthor', 'Selects tracks you didn\'t beat author '. ($aseco->server->gameinfo->mode == Gameinfo::STNT ? 'score on' : 'time on')); $help[] = array('...', '{#black}norecent', 'Selects tracks you didn\'t play recently'); if ($aseco->server->gameinfo->mode != Gameinfo::STNT) { $help[] = array('...', '{#black}longest$g/{#black}shortest', 'Selects the longest/shortest tracks'); } $help[] = array('...', '{#black}newest$g/{#black}oldest', 'Selects the newest/oldest tracks'); if ($feature_karma) { $help[] = array('...', '{#black}novote', 'Selects tracks you didn\'t karma vote for'); } $help[] = array(); $help[] = array('The jukeboxed track is the first one from the chosen selection'); $help[] = array('that is not in the track history.'); // display ManiaLink message display_manialink($login, $header, array('Icons64x64_1', 'TrackInfo', -0.01), $help, array(1.1, 0.05, 0.3, 0.75), 'OK'); } return; } elseif ($cmdcount == 1 && $command['params'][0] == 'nofinish') { getChallengesNoFinish($player); } elseif ($cmdcount == 1 && $command['params'][0] == 'norank') { getChallengesNoRank($player); } elseif ($cmdcount == 1 && $command['params'][0] == 'nogold') { getChallengesNoGold($player); } elseif ($cmdcount == 1 && $command['params'][0] == 'noauthor') { getChallengesNoAuthor($player); } elseif ($cmdcount == 1 && $command['params'][0] == 'norecent') { getChallengesNoRecent($player); } elseif ($cmdcount == 1 && $command['params'][0] == 'longest') { getChallengesByLength($player, false); } elseif ($cmdcount == 1 && $command['params'][0] == 'shortest') { getChallengesByLength($player, true); } elseif ($cmdcount == 1 && $command['params'][0] == 'newest') { getChallengesByAdd($player, true, $buffersize+1); } elseif ($cmdcount == 1 && $command['params'][0] == 'oldest') { getChallengesByAdd($player, false, $buffersize+1); } elseif ($cmdcount == 1 && $command['params'][0] == 'novote' && $feature_karma) { getChallengesNoVote($player); } else { $message = '{#server}> {#error}Invalid selection, try again!'; $aseco->client->query('ChatSendServerMessageToLogin', $aseco->formatColors($message), $login); return; } if (empty($player->tracklist)) { $message = '{#server}> {#error}No tracks found, try again!'; $aseco->client->query('ChatSendServerMessageToLogin', $aseco->formatColors($message), $login); return; } // find first available track $ctr = 1; $found = false; foreach ($player->tracklist as $key) { if (!array_key_exists($key['uid'], $jukebox) && !in_array($key['uid'], $jb_buffer)) { $found = true; break; } $ctr++; } if ($found) { // jukebox it $command['params'] = $ctr; chat_jukebox($aseco, $command); } else { $message = '{#server}> {#highlite}' . $command['params'][0] . '{#error} tracks currently unavailable, try again later!'; $aseco->client->query('ChatSendServerMessageToLogin', $aseco->formatColors($message), $login); } } // chat_autojuke function chat_add($aseco, $command) { global $rasp, $feature_jukebox, $feature_tmxadd, $jukebox_in_window, $jukebox, $tmxadd, $tmxtmpdir, $chatvote, $plrvotes, $allow_spec_startvote, $r_expire_num, $ta_show_num, $ta_expire_start, $auto_vote_starter; $player = $command['author']; $login = $player->login; // check for relay server if ($aseco->server->isrelay) { $message = formatText($aseco->getChatMessage('NOTONRELAY')); $aseco->client->query('ChatSendServerMessageToLogin', $aseco->formatColors($message), $player->login); return; } $sections = array('TMO' => 'original', 'TMS' => 'sunrise', 'TMN' => 'nations', 'TMU' => 'united', 'TMNF' => 'tmnforever'); // check whether jukebox & /add are enabled if ($feature_jukebox && $feature_tmxadd) { // check whether this player is spectator if (!$allow_spec_startvote && $aseco->isSpectator($player)) { $message = $rasp->messages['NO_SPECTATORS'][0]; $aseco->client->query('ChatSendServerMessageToLogin', $aseco->formatColors($message), $login); return; } // check for ongoing TMX or chat vote if (!empty($tmxadd) || !empty($chatvote)) { $message = $rasp->messages['VOTE_ALREADY'][0]; $aseco->client->query('ChatSendServerMessageToLogin', $aseco->formatColors($message), $login); return; } // check for special 'trackref' parameter & write file if ($command['params'] == 'trackref' && $aseco->allowAbility($player, 'chat_add_tref')) { build_tmx_trackref($aseco); $message = '{#server}> {#emotic}Wrote trackref.txt files'; $aseco->client->query('ChatSendServerMessageToLogin', $aseco->formatColors($message), $login); return; } // split params into array $command['params'] = explode(' ', preg_replace('/ +/', ' ', $command['params'])); // check for valid TMX ID if (is_numeric($command['params'][0]) && $command['params'][0] >= 0) { $trkid = ltrim($command['params'][0], '0'); $source = 'TMX'; $section = $aseco->server->getGame(); if ($section == 'TMF' && isset($command['params'][1])) { $section = strtoupper($command['params'][1]); if (!array_key_exists($section, $sections)) { $message = '{#server}> {#error}No such section on TMX!'; $aseco->client->query('ChatSendServerMessageToLogin', $aseco->formatColors($message), $login); return; } } else { // TMN/TMS/TMO or no section if ($section == 'TMF') { if ($aseco->server->packmask == 'Stadium') $section = 'TMNF'; else $section = 'TMU'; } } // try to load the track from TMX $remotefile = 'http://' . $sections[$section] . '.tm-exchange.com/get.aspx?action=trackgbx&id=' . $trkid; $file = http_get_file($remotefile); if ($file === false || $file == -1) { $message = '{#server}> {#error}Error downloading, or wrong TMX section, or TMX is down!'; $aseco->client->query('ChatSendServerMessageToLogin', $aseco->formatColors($message), $login); } else { // check for maximum online track size (256 KB) if (strlen($file) >= 256 * 1024) { $message = formatText($rasp->messages['TRACK_TOO_LARGE'][0], round(strlen($file) / 1024)); $aseco->client->query('ChatSendServerMessageToLogin', $aseco->formatColors($message), $login); return; } $sepchar = substr($aseco->server->trackdir, -1, 1); $partialdir = $tmxtmpdir . $sepchar . $trkid . '.Challenge.gbx'; $localfile = $aseco->server->trackdir . $partialdir; if ($aseco->debug) { $aseco->console_text('/add - tmxtmpdir=' . $tmxtmpdir); $aseco->console_text('/add - path + filename=' . $partialdir); $aseco->console_text('/add - aseco->server->trackdir = ' . $aseco->server->trackdir); } if ($nocasepath = file_exists_nocase($localfile)) { if (!unlink($nocasepath)) { $message = '{#server}> {#error}Error erasing old file. Please contact admin.'; $aseco->client->query('ChatSendServerMessageToLogin', $aseco->formatColors($message), $login); return; } } if (!$lfile = @fopen($localfile, 'wb')) { $message = '{#server}> {#error}Error creating file. Please contact admin.'; $aseco->client->query('ChatSendServerMessageToLogin', $aseco->formatColors($message), $login); return; } if (!fwrite($lfile, $file)) { $message = '{#server}> {#error}Error saving file - unable to write data. Please contact admin.'; $aseco->client->query('ChatSendServerMessageToLogin', $aseco->formatColors($message), $login); fclose($lfile); return; } fclose($lfile); $newtrk = getChallengeData($localfile, true); // 2nd parm is whether or not to get players & votes required if ($newtrk['votes'] == 500 && $newtrk['name'] == 'Not a GBX file') { $message = '{#server}> {#error}No such track on ' . $source; if ($source == 'TMX' && $aseco->server->getGame() == 'TMF') $message .= ' section ' . $section; $message .= '!'; $aseco->client->query('ChatSendServerMessageToLogin', $aseco->formatColors($message), $login); unlink($localfile); return; } // dummy player to easily obtain entire track list $list = new Player(); getAllChallenges($list, '*', '*'); // check for track presence on server $ctr = 1; foreach ($list->tracklist as $key) { if ($key['uid'] == $newtrk['uid']) { $message = $rasp->messages['ADD_PRESENTJB'][0]; $aseco->client->query('ChatSendServerMessageToLogin', $aseco->formatColors($message), $login); unlink($localfile); // jukebox already available track $player->tracklist = $list->tracklist; $command['params'] = $ctr; chat_jukebox($aseco, $command); unset($list); return; } $ctr++; } unset($list); // check for track presence in jukebox via previous /add if (isset($jukebox[$newtrk['uid']])) { $message = $rasp->messages['ADD_DUPL'][0]; $aseco->client->query('ChatSendServerMessageToLogin', $aseco->formatColors($message), $login); unlink($localfile); return; } // rename ID filename to track's name $md5new = md5_file($localfile); $filename = trim(utf8_decode(stripColors($newtrk['name']))); $filename = preg_replace('/[^A-Za-z0-9 \'#=+~_,.-]/', '_', $filename); $filename = preg_replace('/ +/', ' ', preg_replace('/_+/', '_', $filename)); $partialdir = $tmxtmpdir . $sepchar . $filename . '_' . $trkid . '.Challenge.gbx'; // insure unique filename by incrementing sequence number, // if not a duplicate track $i = 1; $dupl = false; while ($nocasepath = file_exists_nocase($aseco->server->trackdir . $partialdir)) { $md5old = md5_file($nocasepath); if ($md5old == $md5new) { $dupl = true; $partialdir = str_replace($aseco->server->trackdir, '', $nocasepath); break; } else { $partialdir = $tmxtmpdir . $sepchar . $filename . '_' . $trkid . '-' . $i++ . '.Challenge.gbx'; } } if ($dupl) { unlink($localfile); } else { rename($localfile, $aseco->server->trackdir . $partialdir); } // check track vs. server settings if ($aseco->server->getGame() == 'TMF') $rtn = $aseco->client->query('CheckChallengeForCurrentServerParams', $partialdir); else $rtn = true; if (!$rtn) { trigger_error('[' . $aseco->client->getErrorCode() . '] CheckChallengeForCurrentServerParams - ' . $aseco->client->getErrorMessage(), E_USER_WARNING); $message = formatText($rasp->messages['JUKEBOX_IGNORED'][0], stripColors($newtrk['name']), $aseco->client->getErrorMessage()); $aseco->client->query('ChatSendServerMessageToLogin', $aseco->formatColors($message), $login); } else { // start /add vote $tmxadd['filename'] = $partialdir; $tmxadd['votes'] = $newtrk['votes']; $tmxadd['name'] = $newtrk['name']; $tmxadd['environment'] = $newtrk['environment']; $tmxadd['login'] = $player->login; $tmxadd['nick'] = $player->nickname; $tmxadd['source'] = $source; $tmxadd['uid'] = $newtrk['uid']; // reset votes, rounds counter, TA interval counter & start time $plrvotes = array(); $r_expire_num = 0; $ta_show_num = 0; $ta_expire_start = time_playing($aseco); // from plugin.track.php // compile & show chat message $message = formatText($rasp->messages['JUKEBOX_ADD'][0], stripColors($tmxadd['nick']), stripColors($tmxadd['name']), $tmxadd['source'], $tmxadd['votes']); $message = str_replace('{br}', LF, $message); // split long message if ($jukebox_in_window && function_exists('send_window_message')) send_window_message($aseco, $message, true); else $aseco->client->query('ChatSendServerMessage', $aseco->formatColors($message)); // enable all vote panels if ($aseco->server->getGame() == 'TMF' && function_exists('allvotepanels_on')) allvotepanels_on($aseco, $login, $aseco->formatColors('{#emotic}')); // vote automatically by vote starter? if ($auto_vote_starter) chat_y($aseco, $command); } } } else { $message = '{#server}> {#error}You must include a TMX Track_ID!'; $aseco->client->query('ChatSendServerMessageToLogin', $aseco->formatColors($message), $login); } } else { $message = $rasp->messages['NO_ADD'][0]; $aseco->client->query('ChatSendServerMessageToLogin', $aseco->formatColors($message), $login); } } // chat_add function build_tmx_trackref($aseco) { global $tmxdir, $tmxtmpdir; $td = $aseco->server->trackdir . $tmxdir; if (is_dir($td)) { $dir = opendir($td); $fp = fopen($td . '/trackref.txt', 'w'); while (($file = readdir($dir)) !== false) { if (strtolower(substr($file, -4)) == '.gbx') { $ci = getChallengeData($td . '/' . $file, false); $file = str_ireplace('.challenge.gbx', '', $file); fwrite($fp, $file . "\t" . $ci['environment'] . "\t" . $ci['author'] . "\t" . stripColors($ci['name']) . "\t" . $ci['coppers'] . CRLF); } } fclose($fp); closedir($dir); } $td = $aseco->server->trackdir . $tmxtmpdir; if (is_dir($td)) { $dir = opendir($td); $fp = fopen($td . '/trackref.txt', 'w'); while (($file = readdir($dir)) !== false) { if (strtolower(substr($file, -4)) == '.gbx') { $ci = getChallengeData($td . '/' . $file, false); $file = str_ireplace('.challenge.gbx', '', $file); fwrite($fp, $file . "\t" . $ci['environment'] . "\t" . $ci['author'] . "\t" . stripColors($ci['name']) . "\t" . $ci['coppers'] . CRLF); } } fclose($fp); closedir($dir); } } // build_tmx_trackref function chat_y($aseco, $command) { global $rasp, $tmxadd, $plrvotes, $chatvote, $jukebox, $allow_spec_voting, $jukebox_in_window, $vote_in_window, $feature_tmxadd, $feature_votes, $ladder_fast_restart; $player = $command['author']; $login = $player->login; // check for relay server if ($aseco->server->isrelay) { $message = formatText($aseco->getChatMessage('NOTONRELAY')); $aseco->client->query('ChatSendServerMessageToLogin', $aseco->formatColors($message), $player->login); return; } // check whether this player is spectator but not any admin if (!$allow_spec_voting && $aseco->isSpectator($player) && !$aseco->isAnyAdmin($player)) { $message = $rasp->messages['NO_SPECTATORS'][0]; $aseco->client->query('ChatSendServerMessageToLogin', $aseco->formatColors($message), $login); return; } // check whether this player already voted if (in_array($login, $plrvotes)) { $message = '{#server}> {#error}You have already voted!'; $aseco->client->query('ChatSendServerMessageToLogin', $aseco->formatColors($message), $login); return; } // check for ongoing TMX vote if (!empty($tmxadd) && $tmxadd['votes'] >= 0) { $votereq = $tmxadd['votes']; $votereq--; // check for sufficient votes if ($votereq > 0) { // remind all players to vote $tmxadd['votes'] = $votereq; $message = formatText($rasp->messages['JUKEBOX_Y'][0], $votereq, ($votereq == 1 ? '' : 's'), stripColors($tmxadd['name'])); if ($jukebox_in_window && function_exists('send_window_message')) send_window_message($aseco, $message, false); else $aseco->client->query('ChatSendServerMessage', $aseco->formatColors($message)); // register this player's vote $plrvotes[] = $login; // disable panel in case /y was used to vote if ($aseco->server->getGame() == 'TMF') votepanel_off($aseco, $login); } else { // pass, so add it to jukebox $uid = $tmxadd['uid']; $jukebox[$uid]['FileName'] = $tmxadd['filename']; $jukebox[$uid]['Name'] = $tmxadd['name']; $jukebox[$uid]['Env'] = $tmxadd['environment']; $jukebox[$uid]['Login'] = $tmxadd['login']; $jukebox[$uid]['Nick'] = $tmxadd['nick']; $jukebox[$uid]['source'] = $tmxadd['source']; $jukebox[$uid]['tmx'] = true; $jukebox[$uid]['uid'] = $uid; // show chat message $message = formatText($rasp->messages['JUKEBOX_PASS'][0], stripColors($tmxadd['name'])); if ($jukebox_in_window && function_exists('send_window_message')) send_window_message($aseco, $message, false); else $aseco->client->query('ChatSendServerMessage', $aseco->formatColors($message)); // clear for next vote $tmxadd = array(); // disable all vote panels if ($aseco->server->getGame() == 'TMF') allvotepanels_off($aseco); // throw 'jukebox changed' event $aseco->releaseEvent('onJukeboxChanged', array('add', $jukebox[$uid])); } } // check for ongoing chat vote elseif (!empty($chatvote) && $chatvote['votes'] >= 0) { $votereq = $chatvote['votes']; $votereq--; // check for sufficient votes if ($votereq > 0) { // remind players to vote $chatvote['votes'] = $votereq; $message = formatText($rasp->messages['VOTE_Y'][0], $votereq, ($votereq == 1 ? '' : 's'), $chatvote['desc']); if ($vote_in_window && function_exists('send_window_message')) send_window_message($aseco, $message, false); else $aseco->client->query('ChatSendServerMessage', $aseco->formatColors($message)); // register this player's vote $plrvotes[] = $login; // disable panel in case /y was used to vote if ($aseco->server->getGame() == 'TMF') votepanel_off($aseco, $login); } else { // show chat message $message = formatText($rasp->messages['VOTE_PASS'][0], $chatvote['desc']); if ($vote_in_window && function_exists('send_window_message')) send_window_message($aseco, $message, false); else $aseco->client->query('ChatSendServerMessage', $aseco->formatColors($message)); // pass, so perform action switch ($chatvote['type']) { case 0: // endround $aseco->client->query('ForceEndRound'); $aseco->console('Vote by {1} forced round end!', $chatvote['login']); break; case 1: // ladder if ($ladder_fast_restart) { global $atl_restart; // from plugin.autotime.php // perform quick restart if (isset($atl_restart)) $atl_restart = true; if ($aseco->server->gameinfo->mode == Gameinfo::CUP) // don't clear scores if in TMF Cup mode $aseco->client->query('ChallengeRestart', true); else $aseco->client->query('ChallengeRestart'); } else { // prepend current track to start of jukebox $uid = $aseco->server->challenge->uid; $jukebox = array_reverse($jukebox, true); $jukebox[$uid]['FileName'] = $aseco->server->challenge->filename; $jukebox[$uid]['Name'] = $aseco->server->challenge->name; $jukebox[$uid]['Env'] = $aseco->server->challenge->environment; $jukebox[$uid]['Login'] = $chatvote['login']; $jukebox[$uid]['Nick'] = $chatvote['nick']; $jukebox[$uid]['source'] = 'Ladder'; $jukebox[$uid]['tmx'] = false; $jukebox[$uid]['uid'] = $uid; $jukebox = array_reverse($jukebox, true); if ($aseco->debug) { $aseco->console_text('/ladder pass - $jukebox:' . CRLF . print_r($jukebox, true)); } // throw 'jukebox changed' event $aseco->releaseEvent('onJukeboxChanged', array('restart', $jukebox[$uid])); // ...and skip to it if ($aseco->server->gameinfo->mode == Gameinfo::CUP) // don't clear scores if in TMF Cup mode $aseco->client->query('NextChallenge', true); else $aseco->client->query('NextChallenge'); } $aseco->console('Vote by {1} restarted track for ladder!', $chatvote['login']); break; case 2: // replay // prepend current track to start of jukebox $uid = $aseco->server->challenge->uid; $jukebox = array_reverse($jukebox, true); $jukebox[$uid]['FileName'] = $aseco->server->challenge->filename; $jukebox[$uid]['Name'] = $aseco->server->challenge->name; $jukebox[$uid]['Env'] = $aseco->server->challenge->environment; $jukebox[$uid]['Login'] = $chatvote['login']; $jukebox[$uid]['Nick'] = $chatvote['nick']; $jukebox[$uid]['source'] = 'Replay'; $jukebox[$uid]['tmx'] = false; $jukebox[$uid]['uid'] = $uid; $jukebox = array_reverse($jukebox, true); if ($aseco->debug) { $aseco->console_text('/replay pass - $jukebox:' . CRLF . print_r($jukebox, true)); } $aseco->console('Vote by {1} replays track after finish!', $chatvote['login']); // throw 'jukebox changed' event $aseco->releaseEvent('onJukeboxChanged', array('replay', $jukebox[$uid])); break; case 3: // skip // skip immediately to next track if ($aseco->server->gameinfo->mode == Gameinfo::CUP) // don't clear scores if in TMF Cup mode $aseco->client->query('NextChallenge', true); else $aseco->client->query('NextChallenge'); $aseco->console('Vote by {1} skips this track!', $chatvote['login']); break; case 4: // kick $rtn = $aseco->client->query('Kick', $chatvote['target']); if (!$rtn) { trigger_error('[' . $aseco->client->getErrorCode() . '] Kick - ' . $aseco->client->getErrorMessage(), E_USER_WARNING); } else { $aseco->console('Vote by {1} kicked player {2}!', $chatvote['login'], $chatvote['target']); } break; case 6: // ignore $rtn = $aseco->client->query('Ignore', $chatvote['target']); if (!$rtn) { trigger_error('[' . $aseco->client->getErrorCode() . '] Ignore - ' . $aseco->client->getErrorMessage(), E_USER_WARNING); } else { // check if in global mute/ignore list if (!in_array($chatvote['target'], $aseco->server->mutelist)) { // add player to list $aseco->server->mutelist[] = $chatvote['target']; } $aseco->console('Vote by {1} ignored player {2}!', $chatvote['login'], $chatvote['target']); } break; case 5: // add - can't occur here break; } // clear for next vote $chatvote = array(); // disable all vote panels if ($aseco->server->getGame() == 'TMF') allvotepanels_off($aseco); } // all quiet on the voting front :) } else { $message = '{#server}> {#error}There is no vote right now!'; if ($feature_tmxadd) { if ($feature_votes) { $message .= ' Use {#highlite}$i/add {#error} or see {#highlite}$i/helpvote{#error} to start one.'; } else { $message .= ' Use {#highlite}$i/add {#error} to start one.'; } } else { if ($feature_votes) { $message .= ' See {#highlite}$i/helpvote{#error} to start one.'; } else { $message .= ''; } } $aseco->client->query('ChatSendServerMessageToLogin', $aseco->formatColors($message), $login); } } // chat_y // called @ onSync function init_jbhistory($aseco, $data) { global $buffersize, $jb_buffer; // read track history from file in case of XASECO restart $jb_buffer = array(); if ($fp = @fopen($aseco->server->trackdir . $aseco->settings['trackhist_file'], 'rb')) { while (!feof($fp)) { $uid = rtrim(fgets($fp)); if ($uid != '') $jb_buffer[] = $uid; } fclose($fp); // keep only most recent $buffersize entries $jb_buffer = array_slice($jb_buffer, -$buffersize); // drop current (last) track as rasp_newtrack() will add it back array_pop($jb_buffer); } } // init_jbhistory function chat_history($aseco, $command) { global $rasp, $jb_buffer; $player = $command['author']; // check for relay server if ($aseco->server->isrelay) { $message = formatText($aseco->getChatMessage('NOTONRELAY')); $aseco->client->query('ChatSendServerMessageToLogin', $aseco->formatColors($message), $player->login); return; } if (!empty($jb_buffer)) { $message = $rasp->messages['HISTORY'][0]; // loop over last 10 (max) entries in buffer for ($i = 1, $j = count($jb_buffer)-1; $i <= 10 && $j >= 0; $i++, $j--) { // get track name from UID $query = 'SELECT Name FROM challenges WHERE Uid=' . quotedString($jb_buffer[$j]); $res = mysql_query($query); $row = mysql_fetch_object($res); mysql_free_result($res); $message .= '{#highlite}' . $i . '{#emotic}.[{#highlite}' . stripColors($row->Name) . '{#emotic}], '; } $message = substr($message, 0, strlen($message)-2); // strip trailing ", " $aseco->client->query('ChatSendServerMessageToLogin', $aseco->formatColors($message), $player->login); return; } else { $message = '{#server}> {#error}No track history available!'; $aseco->client->query('ChatSendServerMessageToLogin', $aseco->formatColors($message), $player->login); return; } } // chat_history function chat_xlist($aseco, $command) { $player = $command['author']; $login = $player->login; // split params into array $command['params'] = explode(' ', preg_replace('/ +/', ' ', $command['params'])); $cmdcount = count($command['params']); $section = $aseco->server->getGame(); if ($section == 'TMF') { if ($aseco->server->packmask == 'Stadium') $section = 'TMNF'; else $section = 'TMU'; } if ($cmdcount == 1 && $command['params'][0] == 'help') { if ($aseco->server->getGame() == 'TMN') { $help = '{#black}/xlist$g will show tracks on TMX:' . LF; $help .= ' - {#black}help$g, displays this help information' . LF; $help .= ' - {#black}recent$g, the 10 most recent tracks' . LF; $help .= ' - {#black}xxx$g, tracks matching (partial) name' . LF; $help .= ' - {#black}auth:yyy$g, tracks matching (partial) author' . LF; $help .= ' - {#black}env:zzz$g, where zzz is an environment from:' . LF; $help .= ' stadium,bay,coast,island,snow,desert,rally' . LF; $help .= ' - {#black}xxx auth:yyy env:zzz$g, combines any searches' . LF; $help .= ' - {#black}tmx$g, selects a TMX section from:' . LF; $help .= ' TMO,TMS,TMN,TMNF$n $m,TMU' . LF; $help .= LF . 'Pick a TMX Id number from the list, and use {#black}/add #$g'; // display popup message $aseco->client->query('SendDisplayServerMessageToLogin', $login, $aseco->formatColors($help), 'OK', '', 0); } elseif ($aseco->server->getGame() == 'TMF') { $header = '{#black}/xlist$g will show tracks on TMX:'; $help = array(); $help[] = array('...', '{#black}help', 'Displays this help information'); $help[] = array('...', '{#black}recent', 'Lists the 10 most recent tracks'); $help[] = array('...', '{#black}xxx', 'Lists tracks matching (partial) name'); $help[] = array('...', '{#black}auth:yyy', 'Lists tracks matching (partial) author'); $help[] = array('...', '{#black}env:zzz', 'Where zzz is an environment from: stadium,'); $help[] = array('', '', 'bay,coast,island,snow/alpine,desert/speed,rally'); $help[] = array('...', '{#black}xxx auth:yyy env:zzz', 'Combines the name, author and/or env searches'); $help[] = array('...', '{#black}tmx', 'Selects a TMX section from:'); $help[] = array('', '', 'TMO,TMS,TMN,TMNF,TMU'); $help[] = array(); $help[] = array('Pick a TMX Id number from the list, and use {#black}/add # {sec}'); // display ManiaLink message display_manialink($login, $header, array('Icons64x64_1', 'TrackInfo', -0.01), $help, array(1.2, 0.05, 0.35, 0.8), 'OK'); } return; } elseif ($command['params'][0] == 'recent') { // check for optional parameter if (isset($command['params'][1]) && strtolower(substr($command['params'][1], 0, 2)) == 'tm') $section = strtoupper($command['params'][1]); // get 10 most recent tracks $tracks = new TMXInfoSearcher($section, '', '', '', true); } else { $name = ''; $auth = ''; $env = ''; // collect search parameters foreach ($command['params'] as $param) { if (strtolower(substr($param, 0, 5)) == 'auth:') { $auth = substr($param, 5); } elseif (strtolower(substr($param, 0, 4)) == 'env:') { $env = substr($param, 4); // map internal to external envs if (strtolower($env) == 'speed') $env = 'desert'; elseif (strtolower($env) == 'alpine') $env = 'snow'; } elseif (strtolower(substr($param, 0, 2)) == 'tm' && // only if last parameter $param == end($command['params'])) { $section = strtoupper($param); } else { if ($name == '') $name = $param; else // concatenate words in name $name .= '%20' . $param; } } // search for matching tracks $tracks = new TMXInfoSearcher($section, $name, $auth, $env, false); } // check for any results if (!$tracks->valid()) { $message = '{#server}> {#error}No tracks found, or TMX is down!'; $aseco->client->query('ChatSendServerMessageToLogin', $aseco->formatColors($message), $login); return; } $player->tracklist = array(); if ($aseco->server->getGame() == 'TMN') { $head = 'Tracks On TMX Section {#black}' . $section . '$g:' . LF . 'Id TMX Name Author' . LF; $msg = ''; $tid = 1; $lines = 0; $player->msgs = array(); $player->msgs[0] = 1; // list all found tracks foreach ($tracks as $row) { $msg .= '$z' . str_pad($tid, 3, '0', STR_PAD_LEFT) . '. {#black}' . str_pad($row->id, 7) . ' ' . str_pad($row->name, 20) . '$z ' . $row->author . LF; $tid++; if (++$lines > 9) { $player->msgs[] = $aseco->formatColors($head . $msg); $lines = 0; $msg = ''; } } // add if last batch exists if ($msg != '') $player->msgs[] = $aseco->formatColors($head . $msg); // display popup message if (count($player->msgs) == 2) { $aseco->client->query('SendDisplayServerMessageToLogin', $login, $player->msgs[1], 'OK', '', 0); } else { // > 2 $aseco->client->query('SendDisplayServerMessageToLogin', $login, $player->msgs[1], 'Close', 'Next', 0); } } elseif ($aseco->server->getGame() == 'TMF') { $adminadd = $aseco->allowAbility($player, 'add'); $head = 'Tracks On TMX Section {#black}' . $section . '$g:'; $msg = array(); if ($aseco->settings['clickable_lists']) if ($adminadd) $msg[] = array('Id', 'TMX', 'Name (click to /add)', '$nAdmin', 'Author', 'Env'); else $msg[] = array('Id', 'TMX', 'Name (click to /add)', 'Author', 'Env'); else $msg[] = array('Id', 'TMX', 'Name', 'Author', 'Env'); $tid = 1; $lines = 0; $player->msgs = array(); if ($adminadd && $aseco->settings['clickable_lists']) $player->msgs[0] = array(1, $head, array(1.55, 0.12, 0.16, 0.6, 0.1, 0.4, 0.17), array('Icons128x128_1', 'LoadTrack', 0.02)); else $player->msgs[0] = array(1, $head, array(1.45, 0.12, 0.16, 0.6, 0.4, 0.17), array('Icons128x128_1', 'LoadTrack', 0.02)); // list all found tracks foreach ($tracks as $row) { $tmxid = '{#black}' . $row->id; $name = '{#black}' . $row->name; $author = $row->author; // add clickable buttons if ($aseco->settings['clickable_lists'] && $tid <= 500) { $tmxid = array($tmxid, $tid+5200); // action ids $name = array($name, $tid+5700); $author = array($author, $tid+6700); // store track in player object for action buttons $trkarr = array(); $trkarr['id'] = $row->id; $trkarr['section'] = $row->section; $trkarr['author'] = $row->author; $player->tracklist[] = $trkarr; } if ($adminadd) if ($aseco->settings['clickable_lists'] && $tid <= 500) $msg[] = array(str_pad($tid, 3, '0', STR_PAD_LEFT) . '.', $tmxid, $name, array('Add', $tid+6200), $author, $row->envir); else $msg[] = array(str_pad($tid, 3, '0', STR_PAD_LEFT) . '.', $tmxid, $name, 'Add', $author, $row->envir); else $msg[] = array(str_pad($tid, 3, '0', STR_PAD_LEFT) . '.', $tmxid, $name, $author, $row->envir); $tid++; if (++$lines > 14) { $player->msgs[] = $msg; $lines = 0; $msg = array(); if ($aseco->settings['clickable_lists']) if ($adminadd) $msg[] = array('Id', 'TMX', 'Name (click to /add)', '$nAdmin', 'Author', 'Env'); else $msg[] = array('Id', 'TMX', 'Name (click to /add)', 'Author', 'Env'); else $msg[] = array('Id', 'TMX', 'Name', 'Author', 'Env'); } } // add if last batch exists if (count($msg) > 1) $player->msgs[] = $msg; // display ManiaLink message display_manialink_multi($player); } } // chat_xlist // called @ onPlayerManialinkPageAnswer // Handles ManiaLink jukebox responses // [0]=PlayerUid, [1]=Login, [2]=Answer function event_jukebox($aseco, $answer) { global $jukebox; // leave actions outside 101 - 2000, -2000 - -101, -2100 - -2001, // -6001 - -7900 & 5201 - 7200 to other handlers if ($answer[2] >= 101 && $answer[2] <= 2000) { // get player $player = $aseco->server->players->getPlayer($answer[1]); // log clicked command $aseco->console('player {1} clicked command "/jukebox {2}"', $player->login, $answer[2]-100); // jukebox selected track $command = array(); $command['author'] = $player; $command['params'] = $answer[2]-100; chat_jukebox($aseco, $command); } elseif ($answer[2] >= -7900 && $answer[2] <= -6001) { // get player $player = $aseco->server->players->getPlayer($answer[1]); // log clicked command $aseco->console('player {1} clicked command "/karma {2}"', $player->login, abs($answer[2])-6000); // karma selected track $command = array(); $command['author'] = $player; $command['params'] = abs($answer[2])-6000; chat_karma($aseco, $command); } elseif ($answer[2] >= -2000 && $answer[2] <= -101) { // get player $player = $aseco->server->players->getPlayer($answer[1]); $author = $player->tracklist[abs($answer[2])-101]['author']; // close main window because /list can take a while mainwindow_off($aseco, $player->login); // log clicked command $aseco->console('player {1} clicked command "/list {2}"', $player->login, $author); // search for tracks by author $command = array(); $command['author'] = $player; $command['params'] = $author; chat_list($aseco, $command); } elseif ($answer[2] >= -2100 && $answer[2] <= -2001) { // get player $player = $aseco->server->players->getPlayer($answer[1]); $login = $player->login; // determine admin ability to drop all jukeboxed tracks if ($aseco->allowAbility($player, 'dropjukebox')) { // log clicked command $aseco->console('player {1} clicked command "/admin dropjukebox {2}"', $login, abs($answer[2])-2000); // drop any jukeboxed track by admin $command = array(); $command['author'] = $player; $command['params'] = 'dropjukebox ' . (abs($answer[2])-2000); chat_admin($aseco, $command); // check whether last track was dropped if (empty($jukebox)) { // close main window mainwindow_off($aseco, $login); } else { // log clicked command $aseco->console('player {1} clicked command "/jukebox display"', $login); // display updated list $command['params'] = 'display'; chat_jukebox($aseco, $command); } } else { // log clicked command $aseco->console('player {1} clicked command "/jukebox drop"', $login); // drop user's jukeboxed track $command = array(); $command['author'] = $player; $command['params'] = 'drop'; chat_jukebox($aseco, $command); // check whether last track was dropped if (empty($jukebox)) { // close main window mainwindow_off($aseco, $login); } else { // log clicked command $aseco->console('player {1} clicked command "/jukebox display"', $login); // display updated list $command['params'] = 'display'; chat_jukebox($aseco, $command); } } } elseif ($answer[2] >= 5201 && $answer[2] <= 5700) { // get player & track ID $player = $aseco->server->players->getPlayer($answer[1]); $tmxid = $player->tracklist[$answer[2]-5201]['id']; $section = $player->tracklist[$answer[2]-5201]['section']; // log clicked command $aseco->console('player {1} clicked command "/tmxinfo {2} {3}"', $player->login, $tmxid, $section); // /tmxinfo selected track $command = array(); $command['author'] = $player; $command['params'] = $tmxid . ' ' . $section; chat_tmxinfo($aseco, $command); } elseif ($answer[2] >= 5701 && $answer[2] <= 6200) { // get player & track ID $player = $aseco->server->players->getPlayer($answer[1]); $tmxid = $player->tracklist[$answer[2]-5701]['id']; $section = $player->tracklist[$answer[2]-5701]['section']; // log clicked command $aseco->console('player {1} clicked command "/add {2} {3}"', $player->login, $tmxid, $section); // /add selected track $command = array(); $command['author'] = $player; $command['params'] = $tmxid . ' ' . $section; chat_add($aseco, $command); } elseif ($answer[2] >= 6201 && $answer[2] <= 6700) { // get player & track ID $player = $aseco->server->players->getPlayer($answer[1]); $tmxid = $player->tracklist[$answer[2]-6201]['id']; $section = $player->tracklist[$answer[2]-6201]['section']; // log clicked command $aseco->console('player {1} clicked command "/admin add {2} {3}"', $player->login, $tmxid, $section); // /admin add selected track $command = array(); $command['author'] = $player; $command['params'] = 'add ' . $tmxid . ' ' . $section; chat_admin($aseco, $command); } elseif ($answer[2] >= 6701 && $answer[2] <= 7200) { // get player & track author $player = $aseco->server->players->getPlayer($answer[1]); $author = $player->tracklist[$answer[2]-6701]['author']; $section = $player->tracklist[$answer[2]-6701]['section']; // insure multi-word author is single parameter $author = str_replace(' ', '%20', $author); // log clicked command $aseco->console('player {1} clicked command "/xlist auth:{2} {3}"', $player->login, $author, $section); // /xlist auth: selected author $command = array(); $command['author'] = $player; $command['params'] = 'auth:' . $author . ' ' . $section; chat_xlist($aseco, $command); } } // event_jukebox ?>