mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-14 10:05:44 -04:00
Add full example of simple flask website that hosts the web client
This commit is contained in:
parent
41666d939b
commit
04cc22f3dc
238
misc/hosting-flask.md
Normal file
238
misc/hosting-flask.md
Normal file
@ -0,0 +1,238 @@
|
||||
The website will be structured like so:
|
||||
|
||||
```
|
||||
websrv.py
|
||||
templates/tmpl.html
|
||||
templates/tmpl_lite.html
|
||||
templates/play.html
|
||||
static/classisphere.js
|
||||
static/default.zip
|
||||
static/style.css
|
||||
static/jquery.js
|
||||
```
|
||||
|
||||
## Content
|
||||
#### websrv.py
|
||||
```Python
|
||||
from flask import Flask, render_template, request
|
||||
app = Flask(__name__)
|
||||
|
||||
@app.route("/")
|
||||
def index():
|
||||
return '<html><h1>Welcome!</h1>Click <a href="/play">here</a> to play</h1></html>'
|
||||
|
||||
@app.route("/play")
|
||||
@app.route("/play/")
|
||||
def play():
|
||||
user = request.args.get('user') or 'Singleplayer'
|
||||
ver = request.args.get('mppass') or ''
|
||||
addr = request.args.get('ip')
|
||||
port = request.args.get('port') or '25565'
|
||||
|
||||
if addr:
|
||||
args = "['%s', '%s', '%s', '%s']" % (user, ver, addr, port)
|
||||
else:
|
||||
args = "['%s']" % user
|
||||
return render_template('play.html', game_args=args)
|
||||
|
||||
if __name__ == "__main__":
|
||||
app.run()
|
||||
```
|
||||
|
||||
#### templates/tmpl.html
|
||||
```HTML
|
||||
<html>
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width">
|
||||
<link href="/static/style.css" rel="stylesheet">
|
||||
<script src="/static/jquery.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="header">
|
||||
<div class="row">
|
||||
<a href="/"><h1 class="columns">Home</h1></a>
|
||||
<a href="/play"><h1 class="columns">Play</h1></a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="body">
|
||||
{% block main %} {% endblock %}
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
#### templates/tmpl_lite.html
|
||||
```HTML
|
||||
<html>
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width">
|
||||
<link href="/static/style.css" rel="stylesheet">
|
||||
<script src="/static/jquery.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="body">
|
||||
{% block main %} {% endblock %}
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
#### templates/play.html
|
||||
```HTML
|
||||
{% set mobile_mode = request.user_agent.platform in ('android', 'iphone', 'ipad') %}
|
||||
{% if mobile_mode %}
|
||||
{% extends 'tmpl_lite.html' %}
|
||||
{% else %}
|
||||
{% extends 'tmpl.html' %}
|
||||
{% endif %}
|
||||
{% block main %}
|
||||
<style>
|
||||
/* the canvas *must not* have any border or padding, or mouse coords will be wrong */
|
||||
#GameCanvas { display:block; box-sizing:border-box; border-width:0px !important; padding:0 !important; margin:0 auto; background-color: black; width:100%; height:auto; }
|
||||
</style>
|
||||
<div class="sec">
|
||||
<div class="row">
|
||||
<canvas id="GameCanvas" oncontextmenu="event.preventDefault()" tabindex=-1 width="1000" height="562"></canvas>
|
||||
<span id="logmsg" style="font-size:18px;color:#F67;"></span>
|
||||
</div>
|
||||
</div>
|
||||
<script type='text/javascript'>
|
||||
// need to load IndexedDB before running the game
|
||||
function preloadIndexedDB() {
|
||||
addRunDependency('load-idb');
|
||||
FS.mkdir('/classicube');
|
||||
FS.mount(IDBFS, {}, '/classicube');
|
||||
FS.syncfs(true, function(err) {
|
||||
if (err) window.cc_idbErr = err;
|
||||
removeRunDependency('load-idb');
|
||||
})
|
||||
}
|
||||
|
||||
function resizeGameCanvas() {
|
||||
var cc_canv = $('canvas#GameCanvas');
|
||||
var dpi = window.devicePixelRatio;
|
||||
var aspect_ratio = 16/9;
|
||||
|
||||
var viewport_w = cc_canv.parent().width();
|
||||
var viewport_h = viewport_w / aspect_ratio;
|
||||
|
||||
var canv_w = Math.round(viewport_w);
|
||||
var canv_h = Math.round(viewport_h);
|
||||
|
||||
if (canv_h % 2) { canv_h = canv_h - 1; }
|
||||
if (canv_w % 2) { canv_w = canv_w - 1; }
|
||||
|
||||
{% if mobile_mode %}
|
||||
canv_h = Math.min(canv_h, window.outerHeight);
|
||||
{% endif %}
|
||||
cc_canv[0].width = canv_w * dpi;
|
||||
cc_canv[0].height = canv_h * dpi;
|
||||
}
|
||||
|
||||
var Module = {
|
||||
preRun: [ preloadIndexedDB, resizeGameCanvas ],
|
||||
postRun: [],
|
||||
arguments: {{game_args|safe}},
|
||||
print: function(text) {
|
||||
if (arguments.length > 1) text = Array.prototype.slice.call(arguments).join(' ');
|
||||
console.log(text);
|
||||
},
|
||||
printErr: function(text) {
|
||||
if (arguments.length > 1) text = Array.prototype.slice.call(arguments).join(' ');
|
||||
console.error(text);
|
||||
},
|
||||
canvas: (function() { return getElementById('GameCanvas'); })(),
|
||||
setStatus: function(text) {
|
||||
console.log(text);
|
||||
document.getElementById('logmsg').innerHTML = text;
|
||||
},
|
||||
totalDependencies: 0,
|
||||
monitorRunDependencies: function(left) {
|
||||
this.totalDependencies = Math.max(this.totalDependencies, left);
|
||||
Module.setStatus(left ? 'Preparing... (' + (this.totalDependencies-left) + '/' + this.totalDependencies + ')' : 'All downloads complete.');
|
||||
}
|
||||
};
|
||||
Module.setStatus('Downloading...');
|
||||
window.onerror = function(event) {
|
||||
// TODO: do not warn on ok events like simulating an infinite loop or exitStatus
|
||||
Module.setStatus('Exception thrown, see JavaScript console');
|
||||
Module.setStatus = function(text) {
|
||||
if (text) Module.printErr('[post-exception status] ' + text);
|
||||
};
|
||||
};
|
||||
</script>
|
||||
<script async type="text/javascript" src="/static/classisphere.js"></script>
|
||||
|
||||
{% if mobile_mode %}
|
||||
<style>
|
||||
#body {min-height: 0px;}
|
||||
.sec {padding: 0px;}
|
||||
.row {padding: 0px;}
|
||||
</style>
|
||||
{% else %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
```
|
||||
|
||||
#### static/classisphere.js
|
||||
Download `classicube.s3.amazonaws.com/client/latest/ClassiCube.js` for this
|
||||
|
||||
#### static/default.zip
|
||||
Download `classicube.net/static/default.zip` for this
|
||||
|
||||
#### static/style.css
|
||||
```CSS
|
||||
.row:before, .row:after {
|
||||
content: " ";
|
||||
display: table;
|
||||
}
|
||||
|
||||
.row:after { clear: both; }
|
||||
|
||||
body { margin: 0; }
|
||||
|
||||
.row {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
max-width: 62.5em;
|
||||
}
|
||||
|
||||
a { text-decoration: none; }
|
||||
|
||||
.columns {
|
||||
position: relative;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.sec {
|
||||
background:#f1ecfa;
|
||||
padding:10px 0 5px;
|
||||
}
|
||||
|
||||
#header { background-color:#5870b0; }
|
||||
|
||||
#header h1 {
|
||||
color:#fff;
|
||||
margin:0px 10px 0px 10px;
|
||||
}
|
||||
```
|
||||
|
||||
#### static/jquery.js
|
||||
Download some version of jQuery for this. Version 2.1.1 is known to work.
|
||||
|
||||
## Results
|
||||
|
||||
* If you don't want the game to resize to fit different resolutions, remove the `resizeGameCanvas` code.
|
||||
|
||||
* tmpl_lite.html and
|
||||
|
||||
## Results
|
||||
|
||||
After all this setup, you need to install the flask package for python.
|
||||
|
||||
Then in command prompt/terminal enter: `python websrv.py`
|
||||
|
||||
Then navigate to `http://127.0.0.1:5000/play` in your web browser. If all goes well you should see the web client start in singleplayer.
|
||||
|
||||
To start in multiplayer instead, navigate to `http://127.0.0.1:5000/play?user=test&ip=127.0.0.1&port=25565`
|
Loading…
x
Reference in New Issue
Block a user