PROGRESS! mostly ui, got admin stuff
This commit is contained in:
parent
2658f3d28c
commit
e730f9a870
6 changed files with 198 additions and 68 deletions
|
@ -110,11 +110,17 @@ tavern.onlogin = (s) => {
|
||||||
let game = document.getElementById('game');
|
let game = document.getElementById('game');
|
||||||
login.style.display = 'none';
|
login.style.display = 'none';
|
||||||
game.style.display = 'flex';
|
game.style.display = 'flex';
|
||||||
|
document.getElementById('admin-panel-button').style.display = tavern.admin ? 'block' : 'none';
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
alert("Invalid username or password!");
|
alert("Invalid username or password!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
tavern.onclose = () => {
|
||||||
|
document.getElementById('game-closed-screen').style.display = 'flex';
|
||||||
|
document.getElementById('login-screen').style.display = 'none';
|
||||||
|
document.getElementById('game').style.display = 'none';
|
||||||
|
}
|
||||||
tavern.onmessage = (m) => {
|
tavern.onmessage = (m) => {
|
||||||
console.log(m);
|
console.log(m);
|
||||||
let msg = document.createElement('div');
|
let msg = document.createElement('div');
|
||||||
|
@ -216,7 +222,31 @@ tavern.onscenelist = (list) => {
|
||||||
let div = document.getElementById('scene-list');
|
let div = document.getElementById('scene-list');
|
||||||
div.innerHTML = '';
|
div.innerHTML = '';
|
||||||
for (let scene of list.scenes) {
|
for (let scene of list.scenes) {
|
||||||
div.innerHTML += `<button onclick='tavern.get_scene(${scene[0]});'>${scene[1]}</button>`;
|
let row = document.createElement('div');
|
||||||
|
row.style.display = 'flex';
|
||||||
|
row.style.gap = '2px';
|
||||||
|
row.style.background = 'transparent';
|
||||||
|
row.innerHTML = `<button onclick='tavern.get_scene(${scene[0]});'>${scene[1]}</button>`;
|
||||||
|
if (tavern.admin) {
|
||||||
|
row.innerHTML += `<button onclick='tavern.show_scene(${scene[0]});'>Force</button>`;
|
||||||
|
row.innerHTML += `<button onclick='tavern.set_scene_visible(${scene[0]}, !${scene[2]});'>${scene[2] ? 'Hide' : 'Show'}</button>`;
|
||||||
|
}
|
||||||
|
div.appendChild(row);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tavern.onconnectedplayers = (connected) => {
|
||||||
|
console.log(connected);
|
||||||
|
// no reason to update the list of kick players if not an admin
|
||||||
|
if (tavern.admin) {
|
||||||
|
let select = document.getElementById('admin-kick-name');
|
||||||
|
Array.from(select.children).filter(c => c.tagName == 'OPTION').forEach(c => select.removeChild(c));
|
||||||
|
connected.forEach(p => {
|
||||||
|
let opt = document.createElement('option');
|
||||||
|
opt.value = p;
|
||||||
|
opt.innerText = p;
|
||||||
|
opt.selected = select.children.length == 0;
|
||||||
|
select.appendChild(opt);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function onLoginClick() {
|
function onLoginClick() {
|
||||||
|
|
|
@ -8,6 +8,17 @@
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body onload="init()">
|
<body onload="init()">
|
||||||
|
<!-- GAME SERVER CLOSED PAGE -->
|
||||||
|
<div id="game-closed-screen" style="display: none; justify-content: center; width: 100%; height: 100%;">
|
||||||
|
<div style="display: flex; justify-content: center; flex-direction: column; gap: 4px;">
|
||||||
|
<h1>Disconnected from game server</h1>
|
||||||
|
<p>
|
||||||
|
This could be either because the game server got shutdown,
|
||||||
|
internet is out,
|
||||||
|
or you got kicked for some reason
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<!-- LOGIN PAGE -->
|
<!-- LOGIN PAGE -->
|
||||||
<div id="login-screen" style="display: flex; justify-content: center; width: 100%; height: 100%;">
|
<div id="login-screen" style="display: flex; justify-content: center; width: 100%; height: 100%;">
|
||||||
<div style="display: flex; justify-content: center; flex-direction: column; gap: 4px;">
|
<div style="display: flex; justify-content: center; flex-direction: column; gap: 4px;">
|
||||||
|
@ -59,9 +70,11 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
style="position: absolute; top: 10px; right: 10px; color: black; z-index: 5; display: flex; flex-direction: row;">
|
style="position: absolute; top: 10px; right: 10px; color: black; z-index: 5; display: flex; flex-direction: row; gap: 4px;">
|
||||||
<button style="background-color: #ffffd6;" onclick="showHideDiv('settings-window')"><b>s</b></button>
|
<button style="background-color: #ffffd6;" onclick="showHideDiv('settings-window')"><b>s</b></button>
|
||||||
<button style="background-color: #ffffd6;" onclick="showHideDiv('initiative-tracker')"><b>i</b></button>
|
<button style="background-color: #ffffd6;" onclick="showHideDiv('initiative-tracker')"><b>i</b></button>
|
||||||
|
<button id="admin-panel-button" style="background-color: #ffffd6;"
|
||||||
|
onclick="showHideDiv('admin-panel')">Admin</button>
|
||||||
</div>
|
</div>
|
||||||
<div id="map" style="position:absolute; transform-origin: top left; user-select: none;">
|
<div id="map" style="position:absolute; transform-origin: top left; user-select: none;">
|
||||||
<img id="map-background" onload="updateGrid()" onerror="alert('Failed loading map')">
|
<img id="map-background" onload="updateGrid()" onerror="alert('Failed loading map')">
|
||||||
|
@ -69,62 +82,80 @@
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<!-- FLOATY (game view) WINDOWS -->
|
||||||
<!-- FLOATY (game view) WINDOWS -->
|
<div id="msg-context-menu" class="chat-message">
|
||||||
<div id="msg-context-menu" class="chat-message">
|
<ul>
|
||||||
<ul>
|
<li>Delete (TODO)</li>
|
||||||
<li>Delete (TODO)</li>
|
</ul>
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div id="initiative-tracker" style="position: absolute; background-color: #ffffd6; color:black; display: none;
|
|
||||||
flex-direction: column; top: 40px; right: 8px; padding: 8px; border-radius: 8px;">
|
|
||||||
<div style="min-width: 150px; user-select: none; display: flex;"
|
|
||||||
onmousedown="onMoveableDivMouseDown(event, 'initiative-tracker')">
|
|
||||||
<h3 style="flex-grow: 1; margin: 8px 0;">Initiative</h3>
|
|
||||||
<!-- it looks bad, for now just click the 'open initiative tracker' button again -->
|
|
||||||
<button onclick="document.getElementById('initiative-tracker').style.display = 'none';"
|
|
||||||
style="height: fit-content; align-self: center; background-color: transparent; font-size: 20px; border: 0;">
|
|
||||||
X
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
<hr style="width: 100%; margin: 0px; align-self: center;" />
|
<div id="initiative-tracker" style="position: absolute; background-color: #ffffd6; color:black; display: none;
|
||||||
<div>
|
flex-direction: column; top: 40px; right: 8px; padding: 8px; border-radius: 8px;">
|
||||||
aaaa
|
<div style="min-width: 150px; user-select: none; display: flex;"
|
||||||
|
onmousedown="onMoveableDivMouseDown(event, 'initiative-tracker');">
|
||||||
|
<h3 style="flex-grow: 1; margin: 8px 0;">Initiative</h3>
|
||||||
|
<!-- it looks bad, for now just click the 'open initiative tracker' button again -->
|
||||||
|
<button class="exit-button"
|
||||||
|
onclick="document.getElementById('initiative-tracker').style.display = 'none';">
|
||||||
|
X
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<hr style="width: 100%; margin: 0px; align-self: center;" />
|
||||||
|
<div>
|
||||||
|
aaaa
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
bbbb
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
cccc
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div id="settings-window" style="position: absolute; background-color: #ffffd6; color:black; display: none;
|
||||||
bbbb
|
flex-direction: column; top: 40px; right: 8px; padding: 8px; border-radius: 8px;">
|
||||||
|
<div style="min-width: 150px; user-select: none; display: flex;"
|
||||||
|
onmousedown="onMoveableDivMouseDown(event, 'settings-window')">
|
||||||
|
<h3 style="flex-grow: 1; margin: 8px 0;">Settings</h3>
|
||||||
|
<!-- it looks bad, for now just click the 'open initiative tracker' button again -->
|
||||||
|
<button class="exit-button"
|
||||||
|
onclick="document.getElementById('settings-window').style.display = 'none';">
|
||||||
|
X
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<hr style="width: 100%; margin: 0px; align-self: center;" />
|
||||||
|
<div style="display: grid; grid-template-columns: auto auto; gap: 16px; margin-top: 8px;">
|
||||||
|
<div>Grid width</div>
|
||||||
|
<input id="settings-grid-width" type="number" onchange="updateGridWidth(event.target.value)"
|
||||||
|
style="width: 55px;">
|
||||||
|
<div>Grid color</div>
|
||||||
|
<input id="settings-grid-color" type="color" onchange="updateGridColor(event.target.value)">
|
||||||
|
<div>Grid type</div>
|
||||||
|
<select id="settings-grid-type" onchange="updateGridDashType(event.target.selectedIndex)"
|
||||||
|
style="width: 140px;">
|
||||||
|
<option value="0" selected>Solid</option>
|
||||||
|
<option value="1">Cross</option>
|
||||||
|
<option value="2">Hollow cross</option>
|
||||||
|
<option value="3">Large hollow cross</option>
|
||||||
|
<option value="4">Squire</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div id="admin-panel" style="position: absolute; background-color: #ffffd6; color:black; display: none;
|
||||||
cccc
|
flex-direction: column; top: 40px; right: 8px; padding: 8px; border-radius: 8px;">
|
||||||
</div>
|
<div style="min-width: 150px; user-select: none; display: flex;"
|
||||||
</div>
|
onmousedown="onMoveableDivMouseDown(event, 'admin-panel')">
|
||||||
<div id="settings-window" style="position: absolute; background-color: #ffffd6; color:black; display: none;
|
<h3 style="flex-grow: 1; margin: 8px 0;">Admin</h3>
|
||||||
flex-direction: column; top: 40px; right: 8px; padding: 8px; border-radius: 8px;">
|
<!-- it looks bad, for now just click the 'open initiative tracker' button again -->
|
||||||
<div style="min-width: 150px; user-select: none; display: flex;"
|
<button class="exit-button" onclick="document.getElementById('admin-panel').style.display = 'none';">
|
||||||
onmousedown="onMoveableDivMouseDown(event, 'settings-window')">
|
X
|
||||||
<h3 style="flex-grow: 1; margin: 8px 0;">Settings</h3>
|
</button>
|
||||||
<!-- it looks bad, for now just click the 'open initiative tracker' button again -->
|
</div>
|
||||||
<button onclick="document.getElementById('settings-window').style.display = 'none';"
|
<hr style="width: 100%; margin: 0px; align-self: center;" />
|
||||||
style="height: fit-content; align-self: center; background-color: transparent; font-size: 20px; border: 0;">
|
<div style="display: grid; grid-template-columns: auto auto; gap: 16px; margin-top: 8px;">
|
||||||
X
|
<button onclick="tavern.save()">Save</button>
|
||||||
</button>
|
<button onclick="tavern.shutdown()">Shutdown</button>
|
||||||
</div>
|
<select id="admin-kick-name"></select>
|
||||||
<hr style="width: 100%; margin: 0px; align-self: center;" />
|
<button onclick="tavern.kick(document.getElementById('admin-kick-name').value)">Kick</button>
|
||||||
<div style="display: grid; grid-template-columns: auto auto; gap: 16px; margin-top: 8px;">
|
</div>
|
||||||
<div>Grid width</div>
|
|
||||||
<input id="settings-grid-width" type="number" onchange="updateGridWidth(event.target.value)"
|
|
||||||
style="width: 55px;">
|
|
||||||
<div>Grid color</div>
|
|
||||||
<input id="settings-grid-color" type="color" onchange="updateGridColor(event.target.value)">
|
|
||||||
<div>Grid type</div>
|
|
||||||
<select id="settings-grid-type" onchange="updateGridDashType(event.target.selectedIndex)"
|
|
||||||
style="width: 140px;">
|
|
||||||
<option value="0" selected>Solid</option>
|
|
||||||
<option value="1">Cross</option>
|
|
||||||
<option value="2">Hollow cross</option>
|
|
||||||
<option value="3">Large hollow cross</option>
|
|
||||||
<option value="4">Squire</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -102,13 +102,21 @@ body {
|
||||||
top: 10px;
|
top: 10px;
|
||||||
left: 5px;
|
left: 5px;
|
||||||
z-index: 5;
|
z-index: 5;
|
||||||
border-color: black;
|
border-color: transparent;
|
||||||
border-width: 2px;
|
border-width: 0px;
|
||||||
border-style: solid;
|
border-style: solid;
|
||||||
background-color: black;
|
background-color: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
#scene-list button {
|
#scene-list button {
|
||||||
background-color: wheat;
|
background-color: wheat;
|
||||||
border-width: 0px;
|
border-width: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.exit-button {
|
||||||
|
height: fit-content;
|
||||||
|
align-self: center;
|
||||||
|
background-color: transparent;
|
||||||
|
font-size: 20px;
|
||||||
|
border: 0;
|
||||||
}
|
}
|
|
@ -1,7 +1,21 @@
|
||||||
class Tavern {
|
class Tavern {
|
||||||
|
// Callback definitions!
|
||||||
|
onlogin = (_loggedIn) => { };
|
||||||
|
onmessage = (_message) => { };
|
||||||
|
onspawntoken = (_spawnToken) => { };
|
||||||
|
onmovetoken = (_moveToken) => { };
|
||||||
|
onshowscene = (_scene) => { };
|
||||||
|
onscenelist = (_sceneList) => { };
|
||||||
|
onconnectedplayers = (_playersList) => { };
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.socket = new WebSocket('ws:/' + window.location.host + '/ws');
|
this.socket = new WebSocket('ws:/' + window.location.host + '/ws');
|
||||||
this.socket.onopen = () => this.connected = true;
|
this.socket.onopen = () => this.connected = true;
|
||||||
|
this.socket.onclose = () => {
|
||||||
|
this.connected = false;
|
||||||
|
this.loggedIn = false;
|
||||||
|
this.call(this.onclose);
|
||||||
|
};
|
||||||
this.msgs = [];
|
this.msgs = [];
|
||||||
this.connected = false;
|
this.connected = false;
|
||||||
this.loggedIn = false;
|
this.loggedIn = false;
|
||||||
|
@ -36,6 +50,9 @@ class Tavern {
|
||||||
if (m.scene_list) {
|
if (m.scene_list) {
|
||||||
this.call(this.onscenelist, m.scene_list);
|
this.call(this.onscenelist, m.scene_list);
|
||||||
}
|
}
|
||||||
|
if (m.connected_players) {
|
||||||
|
this.call(this.onconnectedplayers, m.connected_players);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
call(f, ...args) {
|
call(f, ...args) {
|
||||||
|
@ -101,7 +118,7 @@ class Tavern {
|
||||||
}
|
}
|
||||||
get_scene = (id) => {
|
get_scene = (id) => {
|
||||||
if (!this.connected || this.loggedIn) { return; }
|
if (!this.connected || this.loggedIn) { return; }
|
||||||
this.socket.send(JSON.stringify({ get_scene: { id: id } }))
|
this.socket.send(JSON.stringify({ get_scene: { scene: id } }))
|
||||||
}
|
}
|
||||||
get_scene_list = () => {
|
get_scene_list = () => {
|
||||||
if (!this.connected || this.loggedIn) { return; }
|
if (!this.connected || this.loggedIn) { return; }
|
||||||
|
@ -120,9 +137,25 @@ class Tavern {
|
||||||
this.socket.send(JSON.stringify({ create_scene: { title: title } }));
|
this.socket.send(JSON.stringify({ create_scene: { title: title } }));
|
||||||
}
|
}
|
||||||
shutdown = () => {
|
shutdown = () => {
|
||||||
if (!this.connected || this.loggedIn) { return; }
|
if (!this.connected || this.loggedIn || !this.admin) { return; }
|
||||||
this.socket.send(JSON.stringify('shutdown'));
|
this.socket.send(JSON.stringify('shutdown'));
|
||||||
}
|
}
|
||||||
|
save = () => {
|
||||||
|
if (!this.connected || this.loggedIn || !this.admin) { return; }
|
||||||
|
this.socket.send(JSON.stringify('save'));
|
||||||
|
}
|
||||||
|
kick = (id) => {
|
||||||
|
if (!this.connected || this.loggedIn || !this.admin) { return; }
|
||||||
|
this.socket.send(JSON.stringify({ kick: id }));
|
||||||
|
}
|
||||||
|
show_scene = (id) => {
|
||||||
|
if (!this.connected || this.loggedIn || !this.admin) { return; }
|
||||||
|
this.socket.send(JSON.stringify({ show_scene: { scene: id } }));
|
||||||
|
}
|
||||||
|
set_scene_visible = (id, visible) => {
|
||||||
|
if (!this.connected || this.loggedIn || !this.admin) { return; }
|
||||||
|
this.socket.send(JSON.stringify({ set_scene_visible: { scene: id, visible: visible } }));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const tavern = new Tavern();
|
const tavern = new Tavern();
|
||||||
|
|
|
@ -16,6 +16,7 @@ pub enum Request {
|
||||||
Login(login::LoginRequest),
|
Login(login::LoginRequest),
|
||||||
Quit,
|
Quit,
|
||||||
Kick(String),
|
Kick(String),
|
||||||
|
Save,
|
||||||
Shutdown,
|
Shutdown,
|
||||||
// Character stuff
|
// Character stuff
|
||||||
CreateCharacter,
|
CreateCharacter,
|
||||||
|
@ -57,12 +58,15 @@ pub enum Request {
|
||||||
grid_cell_size: f32,
|
grid_cell_size: f32,
|
||||||
grid_offset: [f32; 2],
|
grid_offset: [f32; 2],
|
||||||
},
|
},
|
||||||
SceneSetVisible {
|
SetSceneVisible {
|
||||||
scene: usize,
|
scene: usize,
|
||||||
visible: bool,
|
visible: bool,
|
||||||
},
|
},
|
||||||
GetScene {
|
GetScene {
|
||||||
id: usize,
|
scene: usize,
|
||||||
|
},
|
||||||
|
ShowScene {
|
||||||
|
scene: usize,
|
||||||
},
|
},
|
||||||
/// TODO: Perhaps remove it, as the client should auto get it on login and on scene list updates
|
/// TODO: Perhaps remove it, as the client should auto get it on login and on scene list updates
|
||||||
GetSceneList,
|
GetSceneList,
|
||||||
|
@ -101,7 +105,7 @@ pub enum Response {
|
||||||
grid_offset: Option<[f32; 2]>,
|
grid_offset: Option<[f32; 2]>,
|
||||||
},
|
},
|
||||||
SceneList {
|
SceneList {
|
||||||
scenes: Vec<(usize, String)>,
|
scenes: Vec<(usize, String, bool)>,
|
||||||
},
|
},
|
||||||
MoveToken {
|
MoveToken {
|
||||||
token_id: usize,
|
token_id: usize,
|
||||||
|
@ -110,6 +114,7 @@ pub enum Response {
|
||||||
},
|
},
|
||||||
SpawnToken(SpawnToken),
|
SpawnToken(SpawnToken),
|
||||||
CharacterCreated(usize),
|
CharacterCreated(usize),
|
||||||
|
ConnectedPlayers(Vec<String>),
|
||||||
Quit {
|
Quit {
|
||||||
id: String,
|
id: String,
|
||||||
},
|
},
|
||||||
|
|
33
src/lib.rs
33
src/lib.rs
|
@ -69,6 +69,7 @@ impl GameServer {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn save(&self) {
|
pub async fn save(&self) {
|
||||||
|
println!("Saving game data!");
|
||||||
let _ = tokio::fs::create_dir("data").await;
|
let _ = tokio::fs::create_dir("data").await;
|
||||||
if let Ok(json) = serde_json::to_string(self) {
|
if let Ok(json) = serde_json::to_string(self) {
|
||||||
let _ = tokio::fs::write(GAME_SAVE_FILE, json.as_bytes()).await;
|
let _ = tokio::fs::write(GAME_SAVE_FILE, json.as_bytes()).await;
|
||||||
|
@ -108,6 +109,8 @@ impl GameServer {
|
||||||
// Send the list of scenes and chat history and such
|
// Send the list of scenes and chat history and such
|
||||||
_ = broadcast.send((SendTo::User(login.username.clone()), self.get_scene_list(admin)));
|
_ = broadcast.send((SendTo::User(login.username.clone()), self.get_scene_list(admin)));
|
||||||
_ = broadcast.send((SendTo::User(login.username.clone()), self.get_last_messages(50)));
|
_ = broadcast.send((SendTo::User(login.username.clone()), self.get_last_messages(50)));
|
||||||
|
let c = self.users.keys().cloned().collect();
|
||||||
|
_ = broadcast.send((SendTo::All, api::Response::ConnectedPlayers(c)))
|
||||||
} else {
|
} else {
|
||||||
_ = broadcast.send((
|
_ = broadcast.send((
|
||||||
SendTo::User(id.clone()),
|
SendTo::User(id.clone()),
|
||||||
|
@ -163,11 +166,26 @@ impl GameServer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
api::Request::GetScene { id: scene_id } => {
|
api::Request::GetScene { scene } => {
|
||||||
if let Some(response) = self.get_scene(&id, scene_id) {
|
if let Some(response) = self.get_scene(&id, scene) {
|
||||||
_ = broadcast.send((SendTo::User(id), response));
|
_ = broadcast.send((SendTo::User(id), response));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
api::Request::ShowScene { scene } => {
|
||||||
|
if self.is_admin(&id) {
|
||||||
|
if let Some(s) = self.game.get_scene_mut(scene) {
|
||||||
|
// Force visible to players
|
||||||
|
if !s.visible_to_users {
|
||||||
|
s.visible_to_users = true;
|
||||||
|
_ = broadcast.send((SendTo::AllBut(id.clone()), self.get_scene_list(false)));
|
||||||
|
_ = broadcast.send((SendTo::User(id.clone()), self.get_scene_list(true)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Some(response) = self.get_scene(&id, scene) {
|
||||||
|
_ = broadcast.send((SendTo::All, response))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
api::Request::CreateScene { title } => {
|
api::Request::CreateScene { title } => {
|
||||||
if self.is_admin(&id) {
|
if self.is_admin(&id) {
|
||||||
self.game.create_scene(title);
|
self.game.create_scene(title);
|
||||||
|
@ -197,7 +215,7 @@ impl GameServer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
api::Request::SceneSetVisible { scene, visible } => {
|
api::Request::SetSceneVisible { scene, visible } => {
|
||||||
if self.is_admin(&id) {
|
if self.is_admin(&id) {
|
||||||
self.game.scene_visible(scene, visible);
|
self.game.scene_visible(scene, visible);
|
||||||
_ = broadcast.send((SendTo::AllBut(id.clone()), self.get_scene_list(false)));
|
_ = broadcast.send((SendTo::AllBut(id.clone()), self.get_scene_list(false)));
|
||||||
|
@ -272,19 +290,24 @@ impl GameServer {
|
||||||
if self.users.contains_key(&id) {
|
if self.users.contains_key(&id) {
|
||||||
self.users.remove(&id);
|
self.users.remove(&id);
|
||||||
}
|
}
|
||||||
_ = broadcast.send((SendTo::All, api::Response::Quit { id }));
|
// _ = broadcast.send((SendTo::All, api::Response::Quit { id }));
|
||||||
|
let c = self.users.keys().cloned().collect();
|
||||||
|
_ = broadcast.send((SendTo::All, api::Response::ConnectedPlayers(c)))
|
||||||
}
|
}
|
||||||
api::Request::Kick(id) => {
|
api::Request::Kick(id) => {
|
||||||
if self.users.contains_key(&id) {
|
if self.users.contains_key(&id) {
|
||||||
self.users.remove(&id);
|
self.users.remove(&id);
|
||||||
}
|
}
|
||||||
_ = broadcast.send((SendTo::User(id), api::Response::Shutdown));
|
_ = broadcast.send((SendTo::User(id), api::Response::Shutdown));
|
||||||
|
let c = self.users.keys().cloned().collect();
|
||||||
|
_ = broadcast.send((SendTo::All, api::Response::ConnectedPlayers(c)))
|
||||||
}
|
}
|
||||||
api::Request::Shutdown => {
|
api::Request::Shutdown => {
|
||||||
if self.is_admin(&id) {
|
if self.is_admin(&id) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
api::Request::Save => self.save().await,
|
||||||
api::Request::CharacterDisplay { id: _ } => {}
|
api::Request::CharacterDisplay { id: _ } => {}
|
||||||
api::Request::CharacterInputs { id: _ } => todo!(),
|
api::Request::CharacterInputs { id: _ } => todo!(),
|
||||||
api::Request::CharacterGetField { id: _, field: _ } => todo!(),
|
api::Request::CharacterGetField { id: _, field: _ } => todo!(),
|
||||||
|
@ -313,7 +336,7 @@ impl GameServer {
|
||||||
.map(|id| self.game.get_scene(*id).map(|s| (id, s)))
|
.map(|id| self.game.get_scene(*id).map(|s| (id, s)))
|
||||||
.flatten()
|
.flatten()
|
||||||
.filter(|(_, scene)| admin || scene.visible_to_users)
|
.filter(|(_, scene)| admin || scene.visible_to_users)
|
||||||
.map(|(id, s)| (*id, s.title.to_string()))
|
.map(|(id, s)| (*id, s.title.to_string(), s.visible_to_users))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
api::Response::SceneList { scenes }
|
api::Response::SceneList { scenes }
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue