mirror of
https://github.com/smogon/pokemon-showdown-client.git
synced 2026-09-30 23:01:05 -05:00
Move replay file creation to battledata.js
This mainly allows a Download button to be available to the replay player.
This commit is contained in:
@@ -1412,5 +1412,73 @@ var Tools = {
|
||||
if (!type) return '';
|
||||
var sanitizedType = type.replace(/\?/g, '%3f');
|
||||
return '<img src="' + Tools.resourcePrefix + 'sprites/types/' + sanitizedType + '.png" alt="' + type + '" height="14" width="32"' + (b ? ' class="b"' : '') + ' />';
|
||||
},
|
||||
|
||||
/*********************************************************
|
||||
* Replay files
|
||||
*********************************************************/
|
||||
|
||||
// Replay files are .html files that display a replay for a battle.
|
||||
|
||||
// The .html files mainly contain replay log data; the actual replay
|
||||
// player is downloaded online. Also included is a textual log and
|
||||
// some minimal CSS to make it look pretty, for offline viewing.
|
||||
|
||||
// This strategy helps keep the replay file reasonably small; of
|
||||
// the 30 KB or so for a 50-turn battle, around 10 KB is the log
|
||||
// data, and around 20 KB is the textual log.
|
||||
|
||||
// The actual replay player is downloaded from replay-embed.js,
|
||||
// which handles loading all the necessary resources for turning the log
|
||||
// data into a playable replay.
|
||||
|
||||
// Battle log data is stored in and loaded from a
|
||||
// <script type="text/plain" class="battle-log-data"> tag.
|
||||
|
||||
// replay-embed.js is loaded through a cache-buster that rotates daily.
|
||||
// This allows pretty much anything about the replay viewer to be
|
||||
// updated as desired.
|
||||
|
||||
createReplayFile: function (room) {
|
||||
var battle = room.battle;
|
||||
var replayid = room.id;
|
||||
if (replayid) {
|
||||
// battle room
|
||||
replayid = replayid.slice(7);
|
||||
if (Config.server.id !== 'showdown') {
|
||||
if (!Config.server.registered) {
|
||||
replayid = 'unregisteredserver-' + replayid;
|
||||
} else {
|
||||
replayid = Config.server.id + '-' + replayid;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// replay panel
|
||||
replayid = room.fragment;
|
||||
}
|
||||
battle.fastForwardTo(-1);
|
||||
var buf = '<!DOCTYPE html>\n';
|
||||
buf += '<meta charset="utf-8" />\n';
|
||||
buf += '<!-- version 1 -->\n';
|
||||
buf += '<title>' + Tools.escapeHTML(battle.tier) + ' replay: ' + Tools.escapeHTML(battle.p1.name) + ' vs. ' + Tools.escapeHTML(battle.p2.name) + '</title>\n';
|
||||
buf += '<style>\n';
|
||||
buf += 'html,body {font-family:Verdana, sans-serif;font-size:10pt;margin:0;padding:0;}body{padding:12px 0;} .battle-log {font-family:Verdana, sans-serif;font-size:10pt;} .battle-log-inline {border:1px solid #AAAAAA;background:#EEF2F5;color:black;max-width:640px;margin:0 auto 80px;padding-bottom:5px;} .battle-log .inner {padding:4px 8px 0px 8px;} .battle-log .inner-preempt {padding:0 8px 4px 8px;} .battle-log .inner-after {margin-top:0.5em;} .battle-log h2 {margin:0.5em -8px;padding:4px 8px;border:1px solid #AAAAAA;background:#E0E7EA;border-left:0;border-right:0;font-family:Verdana, sans-serif;font-size:13pt;} .battle-log .chat {vertical-align:middle;padding:3px 0 3px 0;font-size:8pt;} .battle-log .chat strong {color:#40576A;} .battle-log .chat em {padding:1px 4px 1px 3px;color:#000000;font-style:normal;} .chat.mine {background:rgba(0,0,0,0.05);margin-left:-8px;margin-right:-8px;padding-left:8px;padding-right:8px;} .spoiler {color:#BBBBBB;background:#BBBBBB;padding:0px 3px;} .spoiler:hover, .spoiler:active, .spoiler-shown {color:#000000;background:#E2E2E2;padding:0px 3px;} .spoiler a {color:#BBBBBB;} .spoiler:hover a, .spoiler:active a, .spoiler-shown a {color:#2288CC;} .chat code, .chat .spoiler:hover code, .chat .spoiler:active code, .chat .spoiler-shown code {border:1px solid #C0C0C0;background:#EEEEEE;color:black;padding:0 2px;} .chat .spoiler code {border:1px solid #CCCCCC;background:#CCCCCC;color:#CCCCCC;} .battle-log .rated {padding:3px 4px;} .battle-log .rated strong {color:white;background:#89A;padding:1px 4px;border-radius:4px;} .spacer {margin-top:0.5em;} .message-announce {background:#6688AA;color:white;padding:1px 4px 2px;} .message-announce a, .broadcast-green a, .broadcast-blue a, .broadcast-red a {color:#DDEEFF;} .broadcast-green {background-color:#559955;color:white;padding:2px 4px;} .broadcast-blue {background-color:#6688AA;color:white;padding:2px 4px;} .infobox {border:1px solid #6688AA;padding:2px 4px;} .infobox-limited {max-height:200px;overflow:auto;overflow-x:hidden;} .broadcast-red {background-color:#AA5544;color:white;padding:2px 4px;} .message-learn-canlearn {font-weight:bold;color:#228822;text-decoration:underline;} .message-learn-cannotlearn {font-weight:bold;color:#CC2222;text-decoration:underline;} .message-effect-weak {font-weight:bold;color:#CC2222;} .message-effect-resist {font-weight:bold;color:#6688AA;} .message-effect-immune {font-weight:bold;color:#666666;} .message-learn-list {margin-top:0;margin-bottom:0;} .message-throttle-notice, .message-error {color:#992222;} .message-overflow, .chat small.message-overflow {font-size:0pt;} .message-overflow::before {font-size:9pt;content:\'...\';} .subtle {color:#3A4A66;}\n';
|
||||
buf += '</style>\n';
|
||||
buf += '<div class="wrapper replay-wrapper" style="max-width:1180px;margin:0 auto">\n';
|
||||
buf += '<input type="hidden" name="replayid" value="' + replayid + '" />\n';
|
||||
buf += '<div class="battle"></div><div class="battle-log"></div><div class="replay-controls"></div><div class="replay-controls-2"></div>\n';
|
||||
buf += '<h1 style="font-weight:normal;text-align:center"><strong>' + Tools.escapeHTML(battle.tier) + '</strong><br /><a href="http://pokemonshowdown.com/users/' + toId(battle.p1.name) + '" class="subtle" target="_blank">' + Tools.escapeHTML(battle.p1.name) + '</a> vs. <a href="http://pokemonshowdown.com/users/' + toId(battle.p2.name) + '" class="subtle" target="_blank">' + Tools.escapeHTML(battle.p2.name) + '</a></h1>\n';
|
||||
buf += '<script type="text/plain" class="battle-log-data">' + battle.activityQueue.join('\n').replace(/\//g, '\\/') + '</script>\n';
|
||||
buf += '</div>\n';
|
||||
buf += '<div class="battle-log battle-log-inline"><div class="inner">' + battle.logElem.html() + '</div></div>\n';
|
||||
buf += '</div>\n';
|
||||
buf += '<script>\n';
|
||||
buf += 'var daily = Math.floor(Date.now()/1000/60/60/24);document.write(\'<script src="https://play.pokemonshowdown.com/js/replay-embed.js?version\'+daily+\'"></\'+\'script>\');\n';
|
||||
buf += '</script>\n';
|
||||
return buf;
|
||||
},
|
||||
|
||||
createReplayFileHref: function (room) {
|
||||
return 'data:text/plain;base64,' + encodeURIComponent(window.btoa(unescape(encodeURIComponent(Tools.createReplayFile(room)))));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -710,7 +710,7 @@
|
||||
filename += '-' + toId(this.battle.p1.name);
|
||||
filename += '-' + toId(this.battle.p2.name);
|
||||
|
||||
e.currentTarget.href = Storage.createReplayFileHref(this);
|
||||
e.currentTarget.href = Tools.createReplayFileHref(this);
|
||||
e.currentTarget.download = filename + '.html';
|
||||
|
||||
e.stopPropagation();
|
||||
|
||||
@@ -1180,67 +1180,6 @@ Storage.exportTeam = function (team) {
|
||||
return text;
|
||||
};
|
||||
|
||||
/*********************************************************
|
||||
* Replay files
|
||||
*********************************************************/
|
||||
|
||||
// Replay files are .html files that display a replay for a battle.
|
||||
|
||||
// The .html files mainly contain replay log data; the actual replay
|
||||
// player is downloaded online. Also included is a textual log and
|
||||
// some minimal CSS to make it look pretty, for offline viewing.
|
||||
|
||||
// This strategy helps keep the replay file reasonably small; of
|
||||
// the 30 KB or so for a 50-turn battle, around 10 KB is the log
|
||||
// data, and around 20 KB is the textual log.
|
||||
|
||||
// The actual replay player is downloaded from replay-embed.js,
|
||||
// which handles loading all the necessary resources for turning the log
|
||||
// data into a playable replay.
|
||||
|
||||
// Battle log data is stored in and loaded from a
|
||||
// <script type="text/plain" class="battle-log-data"> tag.
|
||||
|
||||
// replay-embed.js is loaded through a cache-buster that rotates daily.
|
||||
// This allows pretty much anything about the replay viewer to be
|
||||
// updated as desired.
|
||||
|
||||
Storage.createReplayFile = function (room) {
|
||||
var battle = room.battle;
|
||||
var replayid = room.id.slice(7);
|
||||
if (Config.server.id !== 'showdown') {
|
||||
if (!Config.server.registered) {
|
||||
replayid = 'unregisteredserver-' + replayid;
|
||||
} else {
|
||||
replayid = Config.server.id + '-' + replayid;
|
||||
}
|
||||
}
|
||||
battle.fastForwardTo(-1);
|
||||
var buf = '<!DOCTYPE html>\n';
|
||||
buf += '<meta charset="utf-8" />\n';
|
||||
buf += '<!-- version 1 -->\n';
|
||||
buf += '<title>' + Tools.escapeHTML(battle.tier) + ' replay: ' + Tools.escapeHTML(battle.p1.name) + ' vs. ' + Tools.escapeHTML(battle.p2.name) + '</title>\n';
|
||||
buf += '<style>\n';
|
||||
buf += 'html,body {font-family:Verdana, sans-serif;font-size:10pt;margin:0;padding:0;}body{padding:12px 0;} .battle-log {font-family:Verdana, sans-serif;font-size:10pt;} .battle-log-inline {border:1px solid #AAAAAA;background:#EEF2F5;color:black;max-width:640px;margin:0 auto 80px;padding-bottom:5px;} .battle-log .inner {padding:4px 8px 0px 8px;} .battle-log .inner-preempt {padding:0 8px 4px 8px;} .battle-log .inner-after {margin-top:0.5em;} .battle-log h2 {margin:0.5em -8px;padding:4px 8px;border:1px solid #AAAAAA;background:#E0E7EA;border-left:0;border-right:0;font-family:Verdana, sans-serif;font-size:13pt;} .battle-log .chat {vertical-align:middle;padding:3px 0 3px 0;font-size:8pt;} .battle-log .chat strong {color:#40576A;} .battle-log .chat em {padding:1px 4px 1px 3px;color:#000000;font-style:normal;} .chat.mine {background:rgba(0,0,0,0.05);margin-left:-8px;margin-right:-8px;padding-left:8px;padding-right:8px;} .spoiler {color:#BBBBBB;background:#BBBBBB;padding:0px 3px;} .spoiler:hover, .spoiler:active, .spoiler-shown {color:#000000;background:#E2E2E2;padding:0px 3px;} .spoiler a {color:#BBBBBB;} .spoiler:hover a, .spoiler:active a, .spoiler-shown a {color:#2288CC;} .chat code, .chat .spoiler:hover code, .chat .spoiler:active code, .chat .spoiler-shown code {border:1px solid #C0C0C0;background:#EEEEEE;color:black;padding:0 2px;} .chat .spoiler code {border:1px solid #CCCCCC;background:#CCCCCC;color:#CCCCCC;} .battle-log .rated {padding:3px 4px;} .battle-log .rated strong {color:white;background:#89A;padding:1px 4px;border-radius:4px;} .spacer {margin-top:0.5em;} .message-announce {background:#6688AA;color:white;padding:1px 4px 2px;} .message-announce a, .broadcast-green a, .broadcast-blue a, .broadcast-red a {color:#DDEEFF;} .broadcast-green {background-color:#559955;color:white;padding:2px 4px;} .broadcast-blue {background-color:#6688AA;color:white;padding:2px 4px;} .infobox {border:1px solid #6688AA;padding:2px 4px;} .infobox-limited {max-height:200px;overflow:auto;overflow-x:hidden;} .broadcast-red {background-color:#AA5544;color:white;padding:2px 4px;} .message-learn-canlearn {font-weight:bold;color:#228822;text-decoration:underline;} .message-learn-cannotlearn {font-weight:bold;color:#CC2222;text-decoration:underline;} .message-effect-weak {font-weight:bold;color:#CC2222;} .message-effect-resist {font-weight:bold;color:#6688AA;} .message-effect-immune {font-weight:bold;color:#666666;} .message-learn-list {margin-top:0;margin-bottom:0;} .message-throttle-notice, .message-error {color:#992222;} .message-overflow, .chat small.message-overflow {font-size:0pt;} .message-overflow::before {font-size:9pt;content:\'...\';} .subtle {color:#3A4A66;}\n';
|
||||
buf += '</style>\n';
|
||||
buf += '<div class="wrapper replay-wrapper" style="max-width:1180px;margin:0 auto">\n';
|
||||
buf += '<input type="hidden" name="replayid" value="' + replayid + '" />\n';
|
||||
buf += '<div class="battle"></div><div class="battle-log"></div><div class="replay-controls"></div><div class="replay-controls-2"></div>\n';
|
||||
buf += '<h1 style="font-weight:normal;text-align:center"><strong>' + Tools.escapeHTML(battle.tier) + '</strong><br /><a href="http://pokemonshowdown.com/users/' + toId(battle.p1.name) + '" class="subtle" target="_blank">' + Tools.escapeHTML(battle.p1.name) + '</a> vs. <a href="http://pokemonshowdown.com/users/' + toId(battle.p2.name) + '" class="subtle" target="_blank">' + Tools.escapeHTML(battle.p2.name) + '</a></h1>\n';
|
||||
buf += '<script type="text/plain" class="battle-log-data">' + battle.activityQueue.join('\n').replace(/\//g, '\\/') + '</script>\n';
|
||||
buf += '</div>\n';
|
||||
buf += '<div class="battle-log battle-log-inline"><div class="inner">' + battle.logElem.html() + '</div></div>\n';
|
||||
buf += '</div>\n';
|
||||
buf += '<script>\n';
|
||||
buf += 'var daily = Math.floor(Date.now()/1000/60/60/24);document.write(\'<script src="https://play.pokemonshowdown.com/js/replay-embed.js?version\'+daily+\'"></\'+\'script>\');\n';
|
||||
buf += '</script>\n';
|
||||
return buf;
|
||||
};
|
||||
|
||||
Storage.createReplayFileHref = function (room) {
|
||||
return 'data:text/plain;base64,' + encodeURIComponent(window.btoa(unescape(encodeURIComponent(Storage.createReplayFile(room)))));
|
||||
};
|
||||
|
||||
/*********************************************************
|
||||
* Node-webkit
|
||||
*********************************************************/
|
||||
|
||||
Reference in New Issue
Block a user