M .drone.yml => .drone.yml +4 -4
@@ 9,7 9,7 @@ trigger:
- rollback
steps:
- - name: client_formatting
+ - name: client_fmt
image: node
commands:
- cd starkingdoms-client
@@ 17,7 17,7 @@ steps:
- yarn prettier . --check
- name: client_build
depends_on:
- - client_formatting
+ - client_fmt
image: node
commands:
- cd starkingdoms-client
@@ 42,7 42,7 @@ steps:
target: builds/${DRONE_COMMIT_SHA}/client.tar.xz
path_style: true
- - name: server_formatting
+ - name: server_fmt
image: coresdev/stk_build_env
commands:
- cd server
@@ 63,7 63,7 @@ steps:
- name: server_clippy
image: coresdev/stk_build_env
depends_on:
- - server_formatting
+ - server_fmt
commands:
- cd server
- cargo clippy --color always
M starkingdoms-client/.prettierrc => starkingdoms-client/.prettierrc +1 -3
M starkingdoms-client/index.html => starkingdoms-client/index.html +114 -96
@@ 1,109 1,127 @@
<!doctype html>
<html lang="en">
- <head>
- <meta charset="UTF-8"/>
- <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
- <title>StarKingdoms</title>
- </head>
- <body class="bg-grid">
+ <head>
+ <meta charset="UTF-8" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+ <title>StarKingdoms</title>
+ </head>
+ <body class="bg-grid">
+ <div id="gamewindow">
+ <!-- Canvas gets added here by the game script -->
+ </div>
- <div id="gamewindow">
- <!-- Canvas gets added here by the game script -->
- </div>
-
- <div class="popup popup-center popup-max-width-300" id="server_selector">
-
- <h1>StarKingdoms</h1>
- <h2>Join Game</h2>
+ <div class="popup popup-center popup-max-width-300" id="server_selector">
+ <h1>StarKingdoms</h1>
+ <h2>Join Game</h2>
- <form id="join-fm">
- <label>Choose server</label>
+ <form id="join-fm">
+ <label>Choose server</label>
- <div class="fm-select">
- <button class="fm-select-button" role="combobox" aria-labelledby="server selector"
- aria-haspopup="listbox"
- aria-expanded="false" aria-controls="fm-select-dropdown">
- <span class="fm-selected-value">Loading servers list</span>
- <span class="fm-arrow"></span>
- </button>
- <ul class="fm-select-dropdown" role="listbox" id="fm-select-dropdown">
- <!-- Filled by TS -->
- </ul>
- </div>
-
- <label for="username" class="username-label">Username</label>
- <input class="username-box" id="username" required autocomplete="off"/>
- <button id="launch-btn" class="launch-btn">Launch!</button>
- <span id="server-danger" class="server-danger hidden">
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" class="server-danger-icon">
- <path fill-rule="evenodd"
- d="M8.485 2.495c.673-1.167 2.357-1.167 3.03 0l6.28 10.875c.673 1.167-.17 2.625-1.516 2.625H3.72c-1.347 0-2.189-1.458-1.515-2.625L8.485 2.495zM10 5a.75.75 0 01.75.75v3.5a.75.75 0 01-1.5 0v-3.5A.75.75 0 0110 5zm0 9a1 1 0 100-2 1 1 0 000 2z"
- clip-rule="evenodd"/>
-</svg>
-Here be dragons! You have a <b>prerelease server</b> selected. Expect bugs, and save data on this server may be wiped at any time.
- </span>
- </form>
+ <div class="fm-select">
+ <button
+ class="fm-select-button"
+ role="combobox"
+ aria-labelledby="server selector"
+ aria-haspopup="listbox"
+ aria-expanded="false"
+ aria-controls="fm-select-dropdown"
+ >
+ <span class="fm-selected-value">Loading servers list</span>
+ <span class="fm-arrow"></span>
+ </button>
+ <ul class="fm-select-dropdown" role="listbox" id="fm-select-dropdown">
+ <!-- Filled by TS -->
+ </ul>
</div>
- <div class="popup popup-wmin log-hidden log-container popup-max-width-300" id="packet_log">
- <h1>Packet Log</h1>
- <table class="log">
- <thead>
- <tr class="log-wfull">
- <th class="log-wfull log-lalign log-header log-w50">#</th>
- <th class="log-wfull log-lalign log-header">Dir</th>
- <th class="log-wfull log-lalign log-header log-w240">Type</th>
- <th class="log-wfull log-lalign log-header">Delta</th>
- </tr>
- </thead>
- <tbody id="log_body">
+ <label for="username" class="username-label">Username</label>
+ <input class="username-box" id="username" required autocomplete="off" />
+ <button id="launch-btn" class="launch-btn">Launch!</button>
+ <span id="server-danger" class="server-danger hidden">
+ <svg
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 20 20"
+ fill="currentColor"
+ class="server-danger-icon"
+ >
+ <path
+ fill-rule="evenodd"
+ d="M8.485 2.495c.673-1.167 2.357-1.167 3.03 0l6.28 10.875c.673 1.167-.17 2.625-1.516 2.625H3.72c-1.347 0-2.189-1.458-1.515-2.625L8.485 2.495zM10 5a.75.75 0 01.75.75v3.5a.75.75 0 01-1.5 0v-3.5A.75.75 0 0110 5zm0 9a1 1 0 100-2 1 1 0 000 2z"
+ clip-rule="evenodd"
+ />
+ </svg>
+ Here be dragons! You have a <b>prerelease server</b> selected. Expect
+ bugs, and save data on this server may be wiped at any time.
+ </span>
+ </form>
+ </div>
- </tbody>
- </table>
- <hr>
- <h1>Packet Explorer</h1>
- <p id="explorer_selected" class="mono">Selected: --</p>
- <table class="mono json" id="explorer_json"></table>
- </div>
+ <div
+ class="popup popup-wmin log-hidden log-container popup-max-width-300"
+ id="packet_log"
+ >
+ <h1>Packet Log</h1>
+ <table class="log">
+ <thead>
+ <tr class="log-wfull">
+ <th class="log-wfull log-lalign log-header log-w50">#</th>
+ <th class="log-wfull log-lalign log-header">Dir</th>
+ <th class="log-wfull log-lalign log-header log-w240">Type</th>
+ <th class="log-wfull log-lalign log-header">Delta</th>
+ </tr>
+ </thead>
+ <tbody id="log_body"></tbody>
+ </table>
+ <hr />
+ <h1>Packet Explorer</h1>
+ <p id="explorer_selected" class="mono">Selected: --</p>
+ <table class="mono json" id="explorer_json"></table>
+ </div>
- <div class="popup chat-container hidden" id="chat">
- <h1>Chat</h1>
- <div id="chatbox" class="chat-table mono">
- <!-- Filled by script -->
- </div>
- <input placeholder="Enter message or command here..." class="chat-box" id="chatentry" required autocomplete="off"/>
- </div>
+ <div class="popup chat-container hidden" id="chat">
+ <h1>Chat</h1>
+ <div id="chatbox" class="chat-table mono">
+ <!-- Filled by script -->
+ </div>
+ <input
+ placeholder="Enter message or command here..."
+ class="chat-box"
+ id="chatentry"
+ required
+ autocomplete="off"
+ />
+ </div>
- <div class="hud hidden" id="hud">
- <div class="popup" id="hud-content-wrapper">
- <table>
- <thead>
- <tr>
- <th class="hud-d">Position</th>
- <th class="hud-d">Velocity</th>
- <th class="hud-d">Track Angle</th>
- </tr>
- </thead>
- <tbody>
- <tr>
- <td id="pos">
- <span id="pos-val-x">--</span>, <span id="pos-val-y">--</span>
- </td>
- <td id="velocity">
- <span id="velocity-val">--</span>
- </td>
- <td id="track">
- <span id="track-val">--</span>
- </td>
- </tr>
- </tbody>
- </table>
- </div>
- </div>
+ <div class="hud hidden" id="hud">
+ <div class="popup" id="hud-content-wrapper">
+ <table>
+ <thead>
+ <tr>
+ <th class="hud-d">Position</th>
+ <th class="hud-d">Velocity</th>
+ <th class="hud-d">Track Angle</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td id="pos">
+ <span id="pos-val-x">--</span>, <span id="pos-val-y">--</span>
+ </td>
+ <td id="velocity">
+ <span id="velocity-val">--</span>
+ </td>
+ <td id="track">
+ <span id="track-val">--</span>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ </div>
- <span class="footer-left" id="footer-left"></span>
- <span class="footer-right" id="footer-right"></span>
+ <span class="footer-left" id="footer-left"></span>
+ <span class="footer-right" id="footer-right"></span>
- <script type="module" src="src/main.ts"></script>
- </body>
+ <script type="module" src="src/main.ts"></script>
+ </body>
</html>
M starkingdoms-client/src/chat.ts => starkingdoms-client/src/chat.ts +5 -5
@@ 1,7 1,7 @@
export function addMessage(classname: string, message: string) {
- let p = document.createElement("p");
- p.innerText = message;
- p.classList.add("message");
- p.classList.add(classname);
- document.getElementById("chatbox")!.appendChild(p);
+ let p = document.createElement("p");
+ p.innerText = message;
+ p.classList.add("message");
+ p.classList.add(classname);
+ document.getElementById("chatbox")!.appendChild(p);
}
M starkingdoms-client/src/config.json => starkingdoms-client/src/config.json +1 -1
@@ 33,4 33,4 @@
"isPrimary": false
}
}
-}>
\ No newline at end of file
+}
M starkingdoms-client/src/config.ts => starkingdoms-client/src/config.ts +29 -29
@@ 6,43 6,43 @@ const logger = createDebug("config");
const CONFIG_URL = "https://configuration.starkingdoms.io";
export interface Config {
- servers: {[id: string]: ConfigServer}
+ servers: { [id: string]: ConfigServer };
}
export interface ConfigServer {
- name: string;
- clientHubUrl: string;
- apiBaseUrl: string;
- isProduction: boolean;
- isDevelopment: boolean;
- isPrimary: boolean;
+ name: string;
+ clientHubUrl: string;
+ apiBaseUrl: string;
+ isProduction: boolean;
+ isDevelopment: boolean;
+ isPrimary: boolean;
}
async function fetchWithTimeout(resource: RequestInfo | URL, options = {}) {
- // @ts-ignore
- const { timeout = 8000 } = options;
+ // @ts-ignore
+ const { timeout = 8000 } = options;
- const controller = new AbortController();
- const id = setTimeout(() => controller.abort(), timeout);
+ const controller = new AbortController();
+ const id = setTimeout(() => controller.abort(), timeout);
- const response = await fetch(resource, {
- ...options,
- signal: controller.signal
- });
- clearTimeout(id);
+ const response = await fetch(resource, {
+ ...options,
+ signal: controller.signal,
+ });
+ clearTimeout(id);
- return response;
+ return response;
}
export async function loadConfig(): Promise<Config> {
- logger("loading configuration from " + CONFIG_URL);
- try {
- const response = await fetchWithTimeout(CONFIG_URL, {
- timeout: 1000
- });
- return await response.json();
- } catch (e) {
- logger(`error loading configuration: ${e}, using fallback`);
- // @ts-ignore strong types are unhelpful here
- return CONFIG;
- }
-}>
\ No newline at end of file
+ logger("loading configuration from " + CONFIG_URL);
+ try {
+ const response = await fetchWithTimeout(CONFIG_URL, {
+ timeout: 1000,
+ });
+ return await response.json();
+ } catch (e) {
+ logger(`error loading configuration: ${e}, using fallback`);
+ // @ts-ignore strong types are unhelpful here
+ return CONFIG;
+ }
+}
M starkingdoms-client/src/css/chat.css => starkingdoms-client/src/css/chat.css +30 -30
@@ 1,48 1,48 @@
.chat-container {
- position: absolute;
- top: 0.5em;
- right: 0.5em;
- width: 30vw;
- height: min-content;
- font-size: 0.875rem; /* 14px */
- line-height: 1.25rem; /* 20px */
- font-weight: 500;
+ position: absolute;
+ top: 0.5em;
+ right: 0.5em;
+ width: 30vw;
+ height: min-content;
+ font-size: 0.875rem; /* 14px */
+ line-height: 1.25rem; /* 20px */
+ font-weight: 500;
}
.chat-table {
- height: 23vh;
- display: block;
- overflow: auto;
+ height: 23vh;
+ display: block;
+ overflow: auto;
}
.chat-box {
- appearance: none;
- background: transparent;
- color: var(--text);
- padding: 0.675em 1em;
- border: 1px solid var(--links);
- border-radius: 0.25rem;
- cursor: text;
- width: 100%;
- max-width: 100%;
+ appearance: none;
+ background: transparent;
+ color: var(--text);
+ padding: 0.675em 1em;
+ border: 1px solid var(--links);
+ border-radius: 0.25rem;
+ cursor: text;
+ width: 100%;
+ max-width: 100%;
}
.chat-box:focus {
- outline: none;
- background-color: var(--links-ultratransparent);
+ outline: none;
+ background-color: var(--links-ultratransparent);
}
.message {
- padding-top: 0;
- padding-bottom: 0;
- margin-top: 1px;
- margin-bottom: 1px;
+ padding-top: 0;
+ padding-bottom: 0;
+ margin-top: 1px;
+ margin-bottom: 1px;
}
.server-message {
- color: #facb61;
+ color: #facb61;
}
.server-error {
- color: #ff2222;
+ color: #ff2222;
}
.global-message {
- color: #4de640;
+ color: #4de640;
}
.direct-message {
- color: #599fbd;
+ color: #599fbd;
}
M => +14 -14
@@ 1,20 1,20 @@
.footer-left {
font-size: 0.75rem;
line-height: 1rem;
position: absolute;
bottom: 1em;
left: 1em;
font-size: 0.75rem;
line-height: 1rem;
position: absolute;
bottom: 1em;
left: 1em;
}
.footer-right {
font-size: 0.75rem;
line-height: 1rem;
position: absolute;
bottom: 1vh;
right: 1vw;
font-size: 0.75rem;
line-height: 1rem;
position: absolute;
bottom: 1vh;
right: 1vw;
}
.footer-icon {
vertical-align: middle;
display: inline-block;
width: 1rem;
height: 1rem;
vertical-align: middle;
display: inline-block;
width: 1rem;
height: 1rem;
}
M starkingdoms-client/src/css/form.css => starkingdoms-client/src/css/form.css +96 -94
@@ 1,156 1,158 @@
.launch-btn {
- appearance: none;
- width: 100%;
- padding: 1em;
- margin-top: 1em;
- color: var(--text);
- background: transparent;
- border: 2px solid var(--links);
- border-radius: 5px;
- transition: 0.1s ease-in-out;
+ appearance: none;
+ width: 100%;
+ padding: 1em;
+ margin-top: 1em;
+ color: var(--text);
+ background: transparent;
+ border: 2px solid var(--links);
+ border-radius: 5px;
+ transition: 0.1s ease-in-out;
}
.launch-btn:hover {
- cursor: pointer;
- background-color: var(--links-transparent);
+ cursor: pointer;
+ background-color: var(--links-transparent);
}
.username-label {
- margin-top: 1em;
+ margin-top: 1em;
}
.fm-select {
- margin-bottom: 1em;
- position: relative;
+ margin-bottom: 1em;
+ position: relative;
}
.username-box {
- appearance: none;
- background: transparent;
- color: var(--text);
- padding: 0.675em 1em;
- border: 1px solid var(--links);
- border-radius: 0.25rem;
- cursor: text;
- width: 100%;
- max-width: 100%;
+ appearance: none;
+ background: transparent;
+ color: var(--text);
+ padding: 0.675em 1em;
+ border: 1px solid var(--links);
+ border-radius: 0.25rem;
+ cursor: text;
+ width: 100%;
+ max-width: 100%;
}
.username-box:focus {
- outline: none;
- background-color: var(--links-ultratransparent);
+ outline: none;
+ background-color: var(--links-ultratransparent);
}
.fm-select-button {
- appearance: none;
- background: transparent;
- color: var(--text);
- width: 100%;
- padding: 0.675em 1em;
- border: 1px solid var(--links);
- border-radius: 0.25rem;
- cursor: pointer;
- display: flex;
- justify-content: space-between;
- align-items: center;
+ appearance: none;
+ background: transparent;
+ color: var(--text);
+ width: 100%;
+ padding: 0.675em 1em;
+ border: 1px solid var(--links);
+ border-radius: 0.25rem;
+ cursor: pointer;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
}
.fm-selected-value {
- text-align: left;
+ text-align: left;
}
.fm-arrow {
- border-left: 5px solid transparent;
- border-right: 5px solid transparent;
- border-top: 6px solid var(--links);
- transition: transform ease-in-out 0.3s;
+ border-left: 5px solid transparent;
+ border-right: 5px solid transparent;
+ border-top: 6px solid var(--links);
+ transition: transform ease-in-out 0.3s;
}
.fm-select-dropdown {
- position: absolute;
- list-style: none;
- width: 100%;
- box-shadow: 0 10px 25px rgba(0, 0, 0, 0.2);
- background-color: var(--bg-secondary-1);
- border: 1px solid var(--links);
- border-radius: 4px;
- padding: 10px;
- margin-top: 10px;
- max-height: 200px;
- overflow-y: auto;
- transition: 0.2s ease;
+ position: absolute;
+ list-style: none;
+ width: 100%;
+ box-shadow: 0 10px 25px rgba(0, 0, 0, 0.2);
+ background-color: var(--bg-secondary-1);
+ border: 1px solid var(--links);
+ border-radius: 4px;
+ padding: 10px;
+ margin-top: 10px;
+ max-height: 200px;
+ overflow-y: auto;
+ transition: 0.2s ease;
- /*transform: scaleY(0);*/
- opacity: 0;
- visibility: hidden;
+ /*transform: scaleY(0);*/
+ opacity: 0;
+ visibility: hidden;
}
.fm-select-dropdown:focus-within {
- box-shadow: 0 10px 25px var(--links-ultratransparent);
+ box-shadow: 0 10px 25px var(--links-ultratransparent);
}
.fm-select-dropdown li {
- position: relative;
- cursor: pointer;
- display: flex;
- gap: 1rem;
- align-items: center;
+ position: relative;
+ cursor: pointer;
+ display: flex;
+ gap: 1rem;
+ align-items: center;
}
.fm-select-dropdown li label {
- width: 100%;
- padding: 8px 10px;
- cursor: pointer;
+ width: 100%;
+ padding: 8px 10px;
+ cursor: pointer;
}
.fm-select-dropdown::-webkit-scrollbar {
- width: 7px;
+ width: 7px;
}
.fm-select-dropdown::-webkit-scrollbar-track {
- background: #f1f1f1;
- border-radius: 25px;
+ background: #f1f1f1;
+ border-radius: 25px;
}
.fm-select-dropdown::-webkit-scrollbar-thumb {
- background: #ccc;
- border-radius: 25px;
+ background: #ccc;
+ border-radius: 25px;
}
.fm-select-dropdown li + li {
- margin-top: 5px;
+ margin-top: 5px;
}
-.fm-select-dropdown li, .fm-select-dropdown input ~ label {
- border-radius: 5px;
+.fm-select-dropdown li,
+.fm-select-dropdown input ~ label {
+ border-radius: 5px;
}
-.fm-select-dropdown li:hover, .fm-select-dropdown input:checked ~ label {
- background-color: var(--surface-0);
+.fm-select-dropdown li:hover,
+.fm-select-dropdown input:checked ~ label {
+ background-color: var(--surface-0);
}
.fm-select-dropdown input:focus ~ label {
- background-color: var(--surface-1);
+ background-color: var(--surface-1);
}
.fm-select-dropdown input[type="radio"] {
- position: absolute;
- left: 0;
- opacity: 0;
+ position: absolute;
+ left: 0;
+ opacity: 0;
}
.fm-select.active .fm-arrow {
- transform: rotate(180deg);
+ transform: rotate(180deg);
}
.fm-select.active .fm-select-dropdown {
- opacity: 1;
- visibility: visible;
- /*transform: scaleY(1);*/
+ opacity: 1;
+ visibility: visible;
+ /*transform: scaleY(1);*/
}
.server-danger {
- width: 100%;
- display: block;
- height: max-content;
- margin-top: 1em;
- color: var(--error);
- font-size: 0.875rem;
- line-height: 1.25rem;
+ width: 100%;
+ display: block;
+ height: max-content;
+ margin-top: 1em;
+ color: var(--error);
+ font-size: 0.875rem;
+ line-height: 1.25rem;
}
.server-danger.hidden {
- display: none;
+ display: none;
}
.server-danger-icon {
- height: 1.25rem;
- vertical-align: middle;
- display: inline-block;
+ height: 1.25rem;
+ vertical-align: middle;
+ display: inline-block;
}
M starkingdoms-client/src/css/game.css => starkingdoms-client/src/css/game.css +10 -10
@@ 1,11 1,11 @@
.game {
- width: 100vw;
- height: 100vh;
- margin: 0;
- padding: 0;
- position: fixed;
- left: 0;
- top: 0;
- z-index: -1;
- background: url("../assets/starfield.svg");
-}>
\ No newline at end of file
+ width: 100vw;
+ height: 100vh;
+ margin: 0;
+ padding: 0;
+ position: fixed;
+ left: 0;
+ top: 0;
+ z-index: -1;
+ background: url("../assets/starfield.svg");
+}
M starkingdoms-client/src/css/globals.css => starkingdoms-client/src/css/globals.css +31 -14
@@ 1,28 1,45 @@
html {
- box-sizing: border-box;
+ box-sizing: border-box;
}
-*, *:before, *:after {
- box-sizing: inherit;
+*,
+*:before,
+*:after {
+ box-sizing: inherit;
}
body {
- background-color: var(--bg);
- color: var(--body);
- /* Stolen from Tailwind. Looks good in most places. */
- font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
- font-size: 1rem;
- line-height: 1.5rem;
+ background-color: var(--bg);
+ color: var(--body);
+ /* Stolen from Tailwind. Looks good in most places. */
+ font-family:
+ ui-sans-serif,
+ system-ui,
+ -apple-system,
+ BlinkMacSystemFont,
+ "Segoe UI",
+ Roboto,
+ "Helvetica Neue",
+ Arial,
+ "Noto Sans",
+ sans-serif,
+ "Apple Color Emoji",
+ "Segoe UI Emoji",
+ "Segoe UI Symbol",
+ "Noto Color Emoji";
+ font-size: 1rem;
+ line-height: 1.5rem;
}
.mono {
- font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
+ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas,
+ "Liberation Mono", "Courier New", monospace;
}
h1 {
- font-size: 1.25rem;
- line-height: 1.75rem;
+ font-size: 1.25rem;
+ line-height: 1.75rem;
}
h2 {
- font-size: 1.125rem;
- line-height: 1.75rem;
+ font-size: 1.125rem;
+ line-height: 1.75rem;
}
M starkingdoms-client/src/css/grid.css => starkingdoms-client/src/css/grid.css +3 -3
@@ 1,5 1,5 @@
.bg-grid {
- background-image: linear-gradient(to right, #80808012 1px, transparent 1px),
+ background-image: linear-gradient(to right, #80808012 1px, transparent 1px),
linear-gradient(to bottom, #80808012 1px, transparent 1px);
- background-size: 24px 24px;
-}>
\ No newline at end of file
+ background-size: 24px 24px;
+}
M starkingdoms-client/src/css/hud.css => starkingdoms-client/src/css/hud.css +11 -11
@@ 1,25 1,25 @@
.hud {
- position: absolute;
- bottom: .5em;
- left: .5em;
- width: calc(100% - 1em);
+ position: absolute;
+ bottom: 0.5em;
+ left: 0.5em;
+ width: calc(100% - 1em);
}
#hud-content-wrapper {
- width: min(100vw, 620px);
- margin: 0 auto;
+ width: min(100vw, 620px);
+ margin: 0 auto;
}
#hud-content-wrapper > table {
- width: 100%;
- table-layout: fixed;
+ width: 100%;
+ table-layout: fixed;
}
#hud-content-wrapper td {
- text-align: center;
+ text-align: center;
}
.hud-d {
- margin-left: 5px;
- margin-right: 5px;
+ margin-left: 5px;
+ margin-right: 5px;
}
M starkingdoms-client/src/css/json.css => starkingdoms-client/src/css/json.css +10 -10
@@ 1,21 1,21 @@
:root {
- --ident: #75bfff;
- --string: #ff7de9;
- --literal: #86de74;
- --indent-spacing: 16px;
+ --ident: #75bfff;
+ --string: #ff7de9;
+ --literal: #86de74;
+ --indent-spacing: 16px;
}
.json-ident {
- color: var(--ident);
+ color: var(--ident);
}
.json-string {
- color: var(--string);
+ color: var(--string);
}
.json-literal {
- color: var(--literal);
+ color: var(--literal);
}
.json {
- max-height: 200px;
- display: block;
- overflow: auto;
+ max-height: 200px;
+ display: block;
+ overflow: auto;
}
M starkingdoms-client/src/css/log.css => starkingdoms-client/src/css/log.css +24 -24
@@ 1,55 1,55 @@
.log-icon {
- width: 16px
+ width: 16px;
}
.log-lalign {
- text-align: left;
+ text-align: left;
}
.log-item {
- cursor: pointer;
+ cursor: pointer;
}
.log-item:hover {
- background-color: #4a4a4f;
+ background-color: #4a4a4f;
}
.log {
- border: none;
- border-collapse: collapse;
- display: block;
- max-height: 200px;
- overflow: auto;
- width: 100%;
- table-layout: fixed;
+ border: none;
+ border-collapse: collapse;
+ display: block;
+ max-height: 200px;
+ overflow: auto;
+ width: 100%;
+ table-layout: fixed;
}
.log-selected {
- background-color: #204e8a;
- cursor: default;
+ background-color: #204e8a;
+ cursor: default;
}
.log-leaving {
- color: var(--error);
+ color: var(--error);
}
.log-arriving {
- color: var(--success);
+ color: var(--success);
}
.log > tbody > tr > td {
- padding: 2px;
+ padding: 2px;
}
.log-hidden {
- display: none;
+ display: none;
}
#log_body {
- width: 100%;
+ width: 100%;
}
.log-container {
- width: 350px;
+ width: 350px;
}
.log-header {
- padding: 5px;
+ padding: 5px;
}
.log-w240 {
- width: 240px;
+ width: 240px;
}
.log-w50 {
- width: 50px;
+ width: 50px;
}
.log-td {
- padding: 5px;
-}>
\ No newline at end of file
+ padding: 5px;
+}
M => +18 -18
@@ 1,35 1,35 @@
.popup {
padding: 1em;
padding: 1em;
background-color: var(--bg-secondary-1);
background-color: var(--bg-secondary-1);
height: min-content;
height: min-content;
border-radius: 5px;
z-index: 100000;
border-radius: 5px;
z-index: 100000;
}
.popup-max-width-300 {
max-width: 300px;
max-width: 300px;
}
.popup-wmin {
width: min-content;
width: min-content;
}
.popup-center {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: auto;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: auto;
}
.popup > h1 {
margin: 0;
margin: 0;
}
.popup > h2 {
margin: 0 0 0.5em;
color: var(--sub-headline);
margin: 0 0 0.5em;
color: var(--sub-headline);
}
.hidden {
display: none;
visibility: hidden;
display: none;
visibility: hidden;
}
M starkingdoms-client/src/css/style.css => starkingdoms-client/src/css/style.css +1 -1
@@ 7,4 7,4 @@
@import "log.css";
@import "game.css";
@import "hud.css";
-@import "chat.css";>
\ No newline at end of file
+@import "chat.css";
M starkingdoms-client/src/css/themes/catppuccin-common/definitions.css => starkingdoms-client/src/css/themes/catppuccin-common/definitions.css +28 -28
@@ 2,34 2,34 @@
/* This is also a good reference if you want to make your own themes, for what variables you *must* define. */
:root {
- /* Background colors */
- --bg: rgb(var(--base));
- --bg-secondary-1: rgb(var(--crust));
- --bg-secondary-2: rgb(var(--mantle));
+ /* Background colors */
+ --bg: rgb(var(--base));
+ --bg-secondary-1: rgb(var(--crust));
+ --bg-secondary-2: rgb(var(--mantle));
- --surface-0: rgb(var(--surface0));
- --surface-1: rgb(var(--surface1));
- --surface-2: rgb(var(--surface2));
+ --surface-0: rgb(var(--surface0));
+ --surface-1: rgb(var(--surface1));
+ --surface-2: rgb(var(--surface2));
- --overlay-0: rgb(var(--overlay0));
- --overlay-1: rgb(var(--overlay1));
- --overlay-2: rgb(var(--overlay2));
+ --overlay-0: rgb(var(--overlay0));
+ --overlay-1: rgb(var(--overlay1));
+ --overlay-2: rgb(var(--overlay2));
- /* Typography */
- --body: rgb(var(--text));
- --headline: rgb(var(--text));
- --sub-headline: rgb(var(--subtext0));
- --label: rgb(var(--subtext0));
- --subtle: rgb(var(--overlay1));
- --links: rgb(var(--blue));
- --links-transparent: rgba(var(--blue), 0.35);
- --links-ultratransparent: rgba(var(--blue), 0.15);
- --success: rgb(var(--green));
- --warning: rgb(var(--yellow));
- --error: rgb(var(--red));
- --tag: rgb(var(--blue));
- --pill: rgb(var(--blue));
- --sel-bg: rgba(var(--surface2), 0.4);
- --cursor: rgb(var(--rosewater));
- --dm: rgb(var(--teal));
-}>
\ No newline at end of file
+ /* Typography */
+ --body: rgb(var(--text));
+ --headline: rgb(var(--text));
+ --sub-headline: rgb(var(--subtext0));
+ --label: rgb(var(--subtext0));
+ --subtle: rgb(var(--overlay1));
+ --links: rgb(var(--blue));
+ --links-transparent: rgba(var(--blue), 0.35);
+ --links-ultratransparent: rgba(var(--blue), 0.15);
+ --success: rgb(var(--green));
+ --warning: rgb(var(--yellow));
+ --error: rgb(var(--red));
+ --tag: rgb(var(--blue));
+ --pill: rgb(var(--blue));
+ --sel-bg: rgba(var(--surface2), 0.4);
+ --cursor: rgb(var(--rosewater));
+ --dm: rgb(var(--teal));
+}
M starkingdoms-client/src/css/themes/catppuccin-mocha/colors.css => starkingdoms-client/src/css/themes/catppuccin-mocha/colors.css +26 -27
@@ 2,31 2,30 @@
@import "../catppuccin-common/definitions.css";
:root {
- --rosewater: 245, 224, 220;
- --flamingo: 242, 205, 205;
- --pink: 245, 194, 231;
- --mauve: 203, 166, 247;
- --red: 243, 139, 169;
- --maroon: 235, 160, 172;
- --peach: 250, 179, 135;
- --yellow: 249, 226, 175;
- --green: 166, 227, 161;
- --teal: 148, 226, 213;
- --sky: 137, 220, 235;
- --sapphire: 116, 199, 236;
- --blue: 137, 180, 250;
- --lavender: 180, 190, 254;
- --text: 205, 214, 244;
- --subtext1: 186, 194, 222;
- --subtext0: 166, 173, 200;
- --overlay2: 147, 153, 178;
- --overlay1: 127, 132, 156;
- --overlay0: 108, 112, 134;
- --surface2: 88, 91, 112;
- --surface1: 69, 71, 90;
- --surface0: 49, 50, 68;
- --base: 30, 30, 46;
- --mantle: 24, 24, 37;
- --crust: 17, 17, 27;
+ --rosewater: 245, 224, 220;
+ --flamingo: 242, 205, 205;
+ --pink: 245, 194, 231;
+ --mauve: 203, 166, 247;
+ --red: 243, 139, 169;
+ --maroon: 235, 160, 172;
+ --peach: 250, 179, 135;
+ --yellow: 249, 226, 175;
+ --green: 166, 227, 161;
+ --teal: 148, 226, 213;
+ --sky: 137, 220, 235;
+ --sapphire: 116, 199, 236;
+ --blue: 137, 180, 250;
+ --lavender: 180, 190, 254;
+ --text: 205, 214, 244;
+ --subtext1: 186, 194, 222;
+ --subtext0: 166, 173, 200;
+ --overlay2: 147, 153, 178;
+ --overlay1: 127, 132, 156;
+ --overlay0: 108, 112, 134;
+ --surface2: 88, 91, 112;
+ --surface1: 69, 71, 90;
+ --surface0: 49, 50, 68;
+ --base: 30, 30, 46;
+ --mantle: 24, 24, 37;
+ --crust: 17, 17, 27;
}
-
M starkingdoms-client/src/env.d.ts => starkingdoms-client/src/env.d.ts +1 -1
@@ 1,2 1,2 @@
declare const APP_VERSION: string;
-declare const COMMIT_HASH: string;>
\ No newline at end of file
+declare const COMMIT_HASH: string;
M starkingdoms-client/src/hub.ts => starkingdoms-client/src/hub.ts +195 -188
@@ 1,212 1,219 @@
import createDebug from "debug";
import {
- MessagePacket,
- MessageType,
- Packet,
- PacketType,
- PartPositionsPacket,
- PlanetPositionsPacket,
- PlayerLeavePacket,
- PlayerListPacket,
- SpawnPlayerPacket,
+ MessagePacket,
+ MessageType,
+ Packet,
+ PacketType,
+ PartPositionsPacket,
+ PlanetPositionsPacket,
+ PlayerLeavePacket,
+ PlayerListPacket,
+ SpawnPlayerPacket,
} from "./protocol.ts";
-import {appendPacket} from "./packet_ui.ts";
-import {global} from "./main.ts";
-import {startRender} from "./rendering.ts";
-import {addMessage} from "./chat.ts";
+import { appendPacket } from "./packet_ui.ts";
+import { global } from "./main.ts";
+import { startRender } from "./rendering.ts";
+import { addMessage } from "./chat.ts";
const logger = createDebug("hub");
export interface ClientHub {
- socket: WebSocket;
+ socket: WebSocket;
}
export function sendPacket(client: ClientHub, packet: Packet) {
- client.socket.send(JSON.stringify(packet));
- appendPacket(packet);
+ client.socket.send(JSON.stringify(packet));
+ appendPacket(packet);
}
-export async function hub_connect(url: string, username: string): Promise<ClientHub | null> {
- logger("connecting to client hub at " + url)
+export async function hub_connect(
+ url: string,
+ username: string,
+): Promise<ClientHub | null> {
+ logger("connecting to client hub at " + url);
- let ws = new WebSocket(url);
+ let ws = new WebSocket(url);
- ws.onerror = (e) => {
- console.error(e);
- throw e;
- }
+ ws.onerror = (e) => {
+ console.error(e);
+ throw e;
+ };
- ws.onopen = () => {
- logger("connected to client hub, sending username and auth details");
+ ws.onopen = () => {
+ logger("connected to client hub, sending username and auth details");
- let client: ClientHub = {
- socket: ws
- };
+ let client: ClientHub = {
+ socket: ws,
+ };
- let packet: Packet = {
- t: PacketType.ClientLogin,
+ let packet: Packet = {
+ t: PacketType.ClientLogin,
+ c: {
+ username,
+ jwt: null,
+ },
+ };
+ sendPacket(client, packet);
+
+ // input
+ document.onkeydown = (e) => {
+ // currently, input packet is sent on any key down. fix that
+ if (e.key == "ArrowUp" || e.key == "w") {
+ global.up = true;
+ }
+ if (e.key == "ArrowDown" || e.key == "s") {
+ global.down = true;
+ }
+ if (e.key == "ArrowLeft" || e.key == "a") {
+ global.left = true;
+ }
+ if (e.key == "ArrowRight" || e.key == "d") {
+ global.right = true;
+ }
+ let input_packet: Packet = {
+ t: PacketType.PlayerInput,
+ c: {
+ up: global.up,
+ down: global.down,
+ left: global.left,
+ right: global.right,
+ },
+ };
+ sendPacket(client, input_packet);
+ };
+ document.onkeyup = (e) => {
+ if (e.key == "ArrowUp" || e.key == "w") {
+ global.up = false;
+ }
+ if (e.key == "ArrowDown" || e.key == "s") {
+ global.down = false;
+ }
+ if (e.key == "ArrowLeft" || e.key == "a") {
+ global.left = false;
+ }
+ if (e.key == "ArrowRight" || e.key == "d") {
+ global.right = false;
+ }
+ let input_packet: Packet = {
+ t: PacketType.PlayerInput,
+ c: {
+ up: global.up,
+ down: global.down,
+ left: global.left,
+ right: global.right,
+ },
+ };
+ sendPacket(client, input_packet);
+ };
+
+ document.getElementById("chatentry")!.onkeydown = (e) => {
+ if (e.key === "Enter") {
+ let value = (<HTMLInputElement>document.getElementById("chatentry")!)
+ .value;
+
+ if (value.startsWith(".msg")) {
+ let args = value.split(" ");
+ if (args.length < 3) {
+ addMessage("server-error", "Command error");
+
+ (<HTMLInputElement>document.getElementById("chatentry")!).value =
+ "";
+ return;
+ }
+ let target = args[1];
+ let message = args.slice(2).join(" ");
+ let chat_packet: Packet = {
+ t: PacketType.SendMessage,
c: {
- username,
- jwt: null
- }
- };
- sendPacket(client, packet);
-
- // input
- document.onkeydown = (e) => {
- // currently, input packet is sent on any key down. fix that
- if(e.key == "ArrowUp" || e.key == "w") {
- global.up = true;
- }
- if(e.key == "ArrowDown" || e.key == "s") {
- global.down = true;
- }
- if(e.key == "ArrowLeft" || e.key == "a") {
- global.left = true;
- }
- if(e.key == "ArrowRight" || e.key == "d") {
- global.right = true;
- }
- let input_packet: Packet = {
- t: PacketType.PlayerInput,
- c: {
- up: global.up,
- down: global.down,
- left: global.left,
- right: global.right,
- }
- }
- sendPacket(client, input_packet);
- }
- document.onkeyup = (e) => {
- if(e.key == "ArrowUp" || e.key == "w") {
- global.up = false;
- }
- if(e.key == "ArrowDown" || e.key == "s") {
- global.down = false;
- }
- if(e.key == "ArrowLeft" || e.key == "a") {
- global.left = false;
- }
- if(e.key == "ArrowRight" || e.key == "d") {
- global.right = false;
- }
- let input_packet: Packet = {
- t: PacketType.PlayerInput,
- c: {
- up: global.up,
- down: global.down,
- left: global.left,
- right: global.right,
- }
- }
- sendPacket(client, input_packet);
+ target: target,
+ content: message,
+ },
+ };
+ sendPacket(client, chat_packet);
+
+ addMessage("direct-message", `you -> ${target}: ${message}`);
+ } else {
+ let chat_packet: Packet = {
+ t: PacketType.SendMessage,
+ c: {
+ target: null,
+ content: value,
+ },
+ };
+ sendPacket(client, chat_packet);
}
+ (<HTMLInputElement>document.getElementById("chatentry")!).value = "";
+ }
+ };
- document.getElementById("chatentry")!.onkeydown = (e) => {
- if (e.key === 'Enter') {
- let value = (<HTMLInputElement>document.getElementById("chatentry")!).value;
-
- if (value.startsWith(".msg")) {
- let args = value.split(" ");
- if (args.length < 3) {
- addMessage("server-error", "Command error");
-
- (<HTMLInputElement>document.getElementById("chatentry")!).value = "";
- return;
- }
- let target = args[1];
- let message = args.slice(2).join(" ");
- let chat_packet: Packet = {
- t: PacketType.SendMessage,
- c: {
- target: target,
- content: message
- }
- };
- sendPacket(client, chat_packet);
-
- addMessage("direct-message", `you -> ${target}: ${message}`);
- } else {
- let chat_packet: Packet = {
- t: PacketType.SendMessage,
- c: {
- target: null,
- content: value
- }
- };
- sendPacket(client, chat_packet);
- }
- (<HTMLInputElement>document.getElementById("chatentry")!).value = "";
- }
+ ws.onmessage = (e) => {
+ let packet: Packet = JSON.parse(e.data);
+
+ appendPacket(packet);
+
+ if (packet.t == PacketType.SpawnPlayer) {
+ let p = <SpawnPlayerPacket>packet.c;
+ if (p.username === username) {
+ global.me = {
+ username: p.username,
+ part_id: p.id,
+ };
+ logger(`client spawned (username=${p.username} part_id=${p.id})`);
+ startRender();
+ } else {
+ global.players_map.set(p.id, p.username);
+ global.inverse_players_map.set(p.username, p.id);
+ logger(`player joined (username=${p.username} part_id=${p.id})`);
}
-
- ws.onmessage = (e) => {
- let packet: Packet = JSON.parse(e.data);
-
- appendPacket(packet);
-
- if (packet.t == PacketType.SpawnPlayer) {
- let p = <SpawnPlayerPacket> packet.c;
- if (p.username === username) {
- global.me = {
- username: p.username,
- part_id: p.id
- };
- logger(`client spawned (username=${p.username} part_id=${p.id})`);
- startRender();
- } else {
- global.players_map.set(p.id, p.username);
- global.inverse_players_map.set(p.username, p.id);
- logger(`player joined (username=${p.username} part_id=${p.id})`);
- }
- } else if (packet.t == PacketType.PlayerList) {
- let p = <PlayerListPacket> packet.c;
- for (let i = 0; i < p.players.length; i++) {
- global.players_map.set(p.players[i][0], p.players[i][1]);
- global.inverse_players_map.set(p.players[i][1], p.players[i][0]);
- }
- logger(`added ${p.players.length} existing players to player list`);
- } else if (packet.t == PacketType.PlanetPositions) {
- let p = <PlanetPositionsPacket> packet.c;
- for (let i = 0; i < p.planets.length; i++) {
- global.planets_map.set(p.planets[i][0], p.planets[i][1]);
- }
- } else if (packet.t == PacketType.PartPositions) {
- let p = <PartPositionsPacket> packet.c;
- for (let i = 0; i < p.parts.length; i++) {
- global.parts_map.set(p.parts[i][0], p.parts[i][1]);
- }
- } else if (packet.t == PacketType.PlayerLeave) {
- let p = <PlayerLeavePacket>packet.c;
- let username = global.players_map.get(p.id)!;
- global.inverse_players_map.delete(username);
- global.players_map.delete(p.id);
- logger(`player removed (id=${p.id})`);
- } else if (packet.t == PacketType.Message) {
- let p = <MessagePacket>packet.c;
- logger(`message type=${p.message_type} actor=${p.actor} content=${p.content}`);
-
- if (p.message_type == MessageType.Server) {
- addMessage("server-message", `[SERVER] ${p.content}`);
- } else if (p.message_type == MessageType.Chat) {
- addMessage("global-message", `${p.actor}: ${p.content}`);
- } else if (p.message_type == MessageType.Direct) {
- // actor is who sent the message. destination is not included in this packet
- if (p.actor === global.me!.username) {
- // skip (shown above)
- } else {
- addMessage("direct-message", `${p.actor} -> you: ${p.content}`);
- }
- } else {
- addMessage("server-error", `${p.content}`);
- }
- } else {
- logger(`unrecognized packet type ${packet.t}`);
- }
+ } else if (packet.t == PacketType.PlayerList) {
+ let p = <PlayerListPacket>packet.c;
+ for (let i = 0; i < p.players.length; i++) {
+ global.players_map.set(p.players[i][0], p.players[i][1]);
+ global.inverse_players_map.set(p.players[i][1], p.players[i][0]);
}
-
- return client;
+ logger(`added ${p.players.length} existing players to player list`);
+ } else if (packet.t == PacketType.PlanetPositions) {
+ let p = <PlanetPositionsPacket>packet.c;
+ for (let i = 0; i < p.planets.length; i++) {
+ global.planets_map.set(p.planets[i][0], p.planets[i][1]);
+ }
+ } else if (packet.t == PacketType.PartPositions) {
+ let p = <PartPositionsPacket>packet.c;
+ for (let i = 0; i < p.parts.length; i++) {
+ global.parts_map.set(p.parts[i][0], p.parts[i][1]);
+ }
+ } else if (packet.t == PacketType.PlayerLeave) {
+ let p = <PlayerLeavePacket>packet.c;
+ let username = global.players_map.get(p.id)!;
+ global.inverse_players_map.delete(username);
+ global.players_map.delete(p.id);
+ logger(`player removed (id=${p.id})`);
+ } else if (packet.t == PacketType.Message) {
+ let p = <MessagePacket>packet.c;
+ logger(
+ `message type=${p.message_type} actor=${p.actor} content=${p.content}`,
+ );
+
+ if (p.message_type == MessageType.Server) {
+ addMessage("server-message", `[SERVER] ${p.content}`);
+ } else if (p.message_type == MessageType.Chat) {
+ addMessage("global-message", `${p.actor}: ${p.content}`);
+ } else if (p.message_type == MessageType.Direct) {
+ // actor is who sent the message. destination is not included in this packet
+ if (p.actor === global.me!.username) {
+ // skip (shown above)
+ } else {
+ addMessage("direct-message", `${p.actor} -> you: ${p.content}`);
+ }
+ } else {
+ addMessage("server-error", `${p.content}`);
+ }
+ } else {
+ logger(`unrecognized packet type ${packet.t}`);
+ }
};
- return null;
+
+ return client;
+ };
+ return null;
}
M starkingdoms-client/src/main.ts => starkingdoms-client/src/main.ts +120 -96
@@ 1,166 1,190 @@
import createDebug from "debug";
-import {ClientHub, hub_connect} from "./hub.ts";
-import {ConfigServer, loadConfig} from "./config.ts";
+import { ClientHub, hub_connect } from "./hub.ts";
+import { ConfigServer, loadConfig } from "./config.ts";
import "./css/style.css";
import "./css/themes/catppuccin-mocha/colors.css";
-import {Part, Planet} from "./protocol.ts";
+import { Part, Planet } from "./protocol.ts";
let config = await loadConfig();
const logger = createDebug("main");
-logger(`Hello, world! StarKingdoms ${APP_VERSION} (${COMMIT_HASH}) at your service!`);
+logger(
+ `Hello, world! StarKingdoms ${APP_VERSION} (${COMMIT_HASH}) at your service!`,
+);
if (window.localStorage.getItem("stk-packet-mode") === "debug") {
- document.getElementById("packet_log")!.classList.remove("log-hidden");
+ document.getElementById("packet_log")!.classList.remove("log-hidden");
} else {
- document.getElementById("packet_log")!.remove();
+ document.getElementById("packet_log")!.remove();
}
export interface GlobalData {
- client: ClientHub | null,
- me: GlobalMe | null,
+ client: ClientHub | null;
+ me: GlobalMe | null;
- players_map: Map<number, string>,
- inverse_players_map: Map<string, number>,
+ players_map: Map<number, string>;
+ inverse_players_map: Map<string, number>;
- planets_map: Map<number, Planet>,
+ planets_map: Map<number, Planet>;
- parts_map: Map<number, Part>,
+ parts_map: Map<number, Part>;
- up: boolean,
- down: boolean,
- left: boolean,
- right: boolean,
+ up: boolean;
+ down: boolean;
+ left: boolean;
+ right: boolean;
- rendering: GlobalRendering | null
+ rendering: GlobalRendering | null;
}
export interface GlobalMe {
- username: string,
- part_id: number
+ username: string;
+ part_id: number;
}
export interface GlobalRendering {
- canvas: HTMLCanvasElement,
- ctx: CanvasRenderingContext2D
+ canvas: HTMLCanvasElement;
+ ctx: CanvasRenderingContext2D;
}
export const global: GlobalData = {
- client: null,
- me: null,
- players_map: new Map(),
- inverse_players_map: new Map(),
- planets_map: new Map(),
- parts_map: new Map(),
- up: false,
- down: false,
- left: false,
- right: false,
- rendering: null
-}
+ client: null,
+ me: null,
+ players_map: new Map(),
+ inverse_players_map: new Map(),
+ planets_map: new Map(),
+ parts_map: new Map(),
+ up: false,
+ down: false,
+ left: false,
+ right: false,
+ rendering: null,
+};
export function player(): Part | undefined {
- if (global.me !== null) {
- return global.parts_map.get(global.me!.part_id);
- } else {
- return undefined;
- }
+ if (global.me !== null) {
+ return global.parts_map.get(global.me!.part_id);
+ } else {
+ return undefined;
+ }
}
const version_string = `StarKingdoms Client ${APP_VERSION} (${COMMIT_HASH})`;
document.getElementById("footer-left")!.innerHTML = version_string;
-document.getElementById("footer-right")!.innerHTML = `Made with <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" class="footer-icon"><path d="M9.653 16.915l-.005-.003-.019-.01a20.759 20.759 0 01-1.162-.682 22.045 22.045 0 01-2.582-1.9C4.045 12.733 2 10.352 2 7.5a4.5 4.5 0 018-2.828A4.5 4.5 0 0118 7.5c0 2.852-2.044 5.233-3.885 6.82a22.049 22.049 0 01-3.744 2.582l-.019.01-.005.003h-.002a.739.739 0 01-.69.001l-.002-.001z" /></svg> by the StarKingdoms team`;
+document.getElementById("footer-right")!.innerHTML =
+ `Made with <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" class="footer-icon"><path d="M9.653 16.915l-.005-.003-.019-.01a20.759 20.759 0 01-1.162-.682 22.045 22.045 0 01-2.582-1.9C4.045 12.733 2 10.352 2 7.5a4.5 4.5 0 018-2.828A4.5 4.5 0 0118 7.5c0 2.852-2.044 5.233-3.885 6.82a22.049 22.049 0 01-3.744 2.582l-.019.01-.005.003h-.002a.739.739 0 01-.69.001l-.002-.001z" /></svg> by the StarKingdoms team`;
// Dropdown stuff
const custom_select = document.querySelector(".fm-select")!;
-const custom_select_btn = <HTMLButtonElement>document.querySelector(".fm-select-button")!;
+const custom_select_btn = <HTMLButtonElement>(
+ document.querySelector(".fm-select-button")!
+);
custom_select_btn.onclick = (e) => {
- e.stopPropagation();
- e.preventDefault();
- custom_select.classList.toggle("active");
- custom_select_btn.setAttribute("aria-expanded", custom_select_btn.getAttribute("aria-expanded") === "true" ? "false" : "true");
+ e.stopPropagation();
+ e.preventDefault();
+ custom_select.classList.toggle("active");
+ custom_select_btn.setAttribute(
+ "aria-expanded",
+ custom_select_btn.getAttribute("aria-expanded") === "true"
+ ? "false"
+ : "true",
+ );
};
const selected_value = document.querySelector(".fm-selected-value")!;
// Populate the main page server selector
-
-let inverse_server_lookup: {[name: string]: string} = {};
+let inverse_server_lookup: { [name: string]: string } = {};
const dropdown = document.getElementById("fm-select-dropdown")!;
dropdown.innerHTML = "";
for (let server_id in config.servers) {
- let server: ConfigServer = config.servers[server_id];
- if (server.isDevelopment && window.localStorage.getItem("stk-mode") !== "debug") {
- continue;
- }
- let html_text = `
+ let server: ConfigServer = config.servers[server_id];
+ if (
+ server.isDevelopment &&
+ window.localStorage.getItem("stk-mode") !== "debug"
+ ) {
+ continue;
+ }
+ let html_text = `
<li>
- <input type="radio" id="${server_id}" name="server" autocomplete="off" ${server.isPrimary ? "checked" : ""} />
+ <input type="radio" id="${server_id}" name="server" autocomplete="off" ${
+ server.isPrimary ? "checked" : ""
+ } />
<label for="${server_id}">${server.name}</label>
</li>
`;
- inverse_server_lookup[server.name] = server_id;
- dropdown.innerHTML += html_text;
- if (server.isPrimary) {
- selected_value.textContent = server.name;
- }
+ inverse_server_lookup[server.name] = server_id;
+ dropdown.innerHTML += html_text;
+ if (server.isPrimary) {
+ selected_value.textContent = server.name;
+ }
}
const options_list = document.querySelectorAll(".fm-select-dropdown li");
options_list.forEach((option) => {
- function handler(e: Event) {
- if (e.type === "click" && (<PointerEvent>e).clientX !== 0 && (<PointerEvent>e).clientY !== 0) {
- // @ts-ignore
- selected_value.textContent = this.children[1].textContent;
- custom_select.classList.remove("active");
- }
- if (e.type === "keyup") {
- console.log((<KeyboardEvent>e).target!);
- // @ts-ignore
- selected_value.textContent = this.textContent;
- custom_select.classList.remove("active");
- }
- if (!config.servers[inverse_server_lookup[selected_value.textContent!]].isProduction) {
- document.getElementById("server-danger")!.classList.remove("hidden");
- } else {
- document.getElementById("server-danger")!.classList.add("hidden");
- }
+ function handler(e: Event) {
+ if (
+ e.type === "click" &&
+ (<PointerEvent>e).clientX !== 0 &&
+ (<PointerEvent>e).clientY !== 0
+ ) {
+ // @ts-ignore
+ selected_value.textContent = this.children[1].textContent;
+ custom_select.classList.remove("active");
+ }
+ if (e.type === "keyup") {
+ console.log((<KeyboardEvent>e).target!);
+ // @ts-ignore
+ selected_value.textContent = this.textContent;
+ custom_select.classList.remove("active");
+ }
+ if (
+ !config.servers[inverse_server_lookup[selected_value.textContent!]]
+ .isProduction
+ ) {
+ document.getElementById("server-danger")!.classList.remove("hidden");
+ } else {
+ document.getElementById("server-danger")!.classList.add("hidden");
}
- // @ts-ignore
- option.onkeyup = handler;
- // @ts-ignore
- option.onclick = handler;
+ }
+ // @ts-ignore
+ option.onkeyup = handler;
+ // @ts-ignore
+ option.onclick = handler;
});
function setStatus(stat: string) {
- document.getElementById("launch-btn")!.textContent = stat;
+ document.getElementById("launch-btn")!.textContent = stat;
}
document.getElementById("join-fm")!.onsubmit = async (e) => {
- e.preventDefault();
+ e.preventDefault();
- setStatus("Connecting...");
- (<HTMLButtonElement>custom_select_btn).disabled = true;
- (<HTMLInputElement>document.getElementById("username")!).disabled = true;
+ setStatus("Connecting...");
+ (<HTMLButtonElement>custom_select_btn).disabled = true;
+ (<HTMLInputElement>document.getElementById("username")!).disabled = true;
- try {
- let server_name = selected_value.textContent!;
- let server_id = inverse_server_lookup[server_name];
- let server: ConfigServer = config.servers[server_id];
+ try {
+ let server_name = selected_value.textContent!;
+ let server_id = inverse_server_lookup[server_name];
+ let server: ConfigServer = config.servers[server_id];
- let username = (<HTMLInputElement>document.getElementById("username")!).value;
+ let username = (<HTMLInputElement>document.getElementById("username")!)
+ .value;
- logger(`connecting to ${server.clientHubUrl} as ${username} with auth = none`);
+ logger(
+ `connecting to ${server.clientHubUrl} as ${username} with auth = none`,
+ );
- global.client = await hub_connect(server.clientHubUrl, username);
- } catch (e) {
- setStatus("Connection failed!");
- console.error(e);
- (<HTMLButtonElement>custom_select_btn).disabled = false;
- (<HTMLInputElement>document.getElementById("username")!).disabled = false;
- }
+ global.client = await hub_connect(server.clientHubUrl, username);
+ } catch (e) {
+ setStatus("Connection failed!");
+ console.error(e);
+ (<HTMLButtonElement>custom_select_btn).disabled = false;
+ (<HTMLInputElement>document.getElementById("username")!).disabled = false;
+ }
};
M starkingdoms-client/src/packet_ui.ts => starkingdoms-client/src/packet_ui.ts +98 -80
@@ 1,5 1,5 @@
// @ts-ignore
-import {Direction, Packet, type_direction} from "./protocol.ts";
+import { Direction, Packet, type_direction } from "./protocol.ts";
import createDebug from "debug";
const logger = createDebug("jsonview");
@@ 7,40 7,47 @@ const logger = createDebug("jsonview");
let selected = document.getElementById("explorer_selected")!;
let table = document.getElementById("explorer_json")!;
-export function show_packet(maybe_packet: Packet | null, sequence_number: number) {
- logger(`selected packet ${sequence_number}`);
- if (maybe_packet === null) {
- selected.textContent = "Selected: --";
- table.innerHTML = "";
- return;
- }
- let packet = maybe_packet!;
- let direction = type_direction(packet.t);
+export function show_packet(
+ maybe_packet: Packet | null,
+ sequence_number: number,
+) {
+ logger(`selected packet ${sequence_number}`);
+ if (maybe_packet === null) {
+ selected.textContent = "Selected: --";
+ table.innerHTML = "";
+ return;
+ }
+ let packet = maybe_packet!;
+ let direction = type_direction(packet.t);
- selected.textContent = `Selected: #${sequence_number} ${direction} ${packet.t}`;
+ selected.textContent = `Selected: #${sequence_number} ${direction} ${packet.t}`;
- // iterate over everything and calculate a max depth
- let max_depth = depthOf(packet.c);
- logger(`indent depth ${max_depth}`);
+ // iterate over everything and calculate a max depth
+ let max_depth = depthOf(packet.c);
+ logger(`indent depth ${max_depth}`);
- // generate a tree
- let tree = generateTree(packet.c, 0);
+ // generate a tree
+ let tree = generateTree(packet.c, 0);
- logger(`generating tree of ${tree.length} items`);
+ logger(`generating tree of ${tree.length} items`);
- let table_html = "";
+ let table_html = "";
- for (let i = 0; i < tree.length; i++) {
- let [indent, key, value, is_text] = tree[i];
- table_html += `
+ for (let i = 0; i < tree.length; i++) {
+ let [indent, key, value, is_text] = tree[i];
+ table_html += `
<tr>
<td style="padding-left: calc(var(--indent-spacing) * ${indent})" class="json-ident">${key}</td>
- <td style="padding-left: calc(var(--indent-spacing) * ${max_depth + 1})" class="${is_text ? "json-string" : "json-literal"}">${value}</td>
+ <td style="padding-left: calc(var(--indent-spacing) * ${
+ max_depth + 1
+ })" class="${
+ is_text ? "json-string" : "json-literal"
+ }">${value}</td>
</tr>
- `
- }
+ `;
+ }
- table.innerHTML = `
+ table.innerHTML = `
<!-- Rendered tree of ${tree.length} items -->
<thead>
<tr></tr>
@@ 53,57 60,64 @@ export function show_packet(maybe_packet: Packet | null, sequence_number: number
}
function depthOf(object: any) {
- let level = 0;
- for(let key in object) {
- if (!object.hasOwnProperty(key)) continue;
+ let level = 0;
+ for (let key in object) {
+ if (!object.hasOwnProperty(key)) continue;
- if(typeof object[key] == 'object'){
- let depth = depthOf(object[key]) + 1;
- level = Math.max(depth, level);
- }
+ if (typeof object[key] == "object") {
+ let depth = depthOf(object[key]) + 1;
+ level = Math.max(depth, level);
}
- return level;
+ }
+ return level;
}
-
-function generateTree(object: any, level: number): [indent: number, key: string, value: string, value_string: boolean][] {
- let items: [indent: number, key: string, value: string, value_string: boolean][] = [];
-
- for (let key in object) {
- if (!object.hasOwnProperty(key)) continue;
-
- if (object[key] === null) {
- items.push([level, key, "null", false]);
- } else if (object[key] === undefined) {
- items.push([level, key, "undefined", false]);
- } else if (typeof object[key] === 'object') {
- if (Array.isArray(object[key])) {
- if (object[key].length == 0) {
- items.push([level, key + ":", "[]", false]);
- } else {
- items.push([level, key + ":", "", false]);
- }
- for (let i = 0; i < object[key].length; i++) {
- items.push([level+1, i.toString() + ":", "", false]);
- items = items.concat(generateTree(object[key][i], level+2));
- }
- continue;
- }
- items.push([level, key + ":", "", false]);
- items = items.concat(generateTree(object[key], level + 1));
- } else if (Array.isArray(object[key])) {
- for (let i = 0; i < object[key].length; i++) {
- items.push([level, i.toString() + ":", "", false]);
- items = items.concat(generateTree(object[key][i], level));
- }
- } else if (typeof object[key] === 'string') {
- items.push([level, key + ":", "\"" + object[key] + "\"", true]);
+function generateTree(
+ object: any,
+ level: number,
+): [indent: number, key: string, value: string, value_string: boolean][] {
+ let items: [
+ indent: number,
+ key: string,
+ value: string,
+ value_string: boolean,
+ ][] = [];
+
+ for (let key in object) {
+ if (!object.hasOwnProperty(key)) continue;
+
+ if (object[key] === null) {
+ items.push([level, key, "null", false]);
+ } else if (object[key] === undefined) {
+ items.push([level, key, "undefined", false]);
+ } else if (typeof object[key] === "object") {
+ if (Array.isArray(object[key])) {
+ if (object[key].length == 0) {
+ items.push([level, key + ":", "[]", false]);
} else {
- items.push([level, key + ":", object[key].toString(), false]);
+ items.push([level, key + ":", "", false]);
+ }
+ for (let i = 0; i < object[key].length; i++) {
+ items.push([level + 1, i.toString() + ":", "", false]);
+ items = items.concat(generateTree(object[key][i], level + 2));
}
+ continue;
+ }
+ items.push([level, key + ":", "", false]);
+ items = items.concat(generateTree(object[key], level + 1));
+ } else if (Array.isArray(object[key])) {
+ for (let i = 0; i < object[key].length; i++) {
+ items.push([level, i.toString() + ":", "", false]);
+ items = items.concat(generateTree(object[key][i], level));
+ }
+ } else if (typeof object[key] === "string") {
+ items.push([level, key + ":", '"' + object[key] + '"', true]);
+ } else {
+ items.push([level, key + ":", object[key].toString(), false]);
}
+ }
- return items;
+ return items;
}
export let packets: Packet[] = [];
@@ 123,21 137,25 @@ const down_arrow = `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox=
</svg>`;
export function selectPacket(id: number) {
- console.log("selecting packet " + id);
- if (selected_packet !== null) {
- document.getElementById("packet-" + selected_packet)!.classList.remove("log-selected");
- document.getElementById("packet-" + selected_packet)!.classList.add("log-item");
- }
- document.getElementById("packet-" + id)!.classList.add("log-selected");
- document.getElementById("packet-" + id)!.classList.remove("log-item");
- selected_packet = id;
- show_packet(packets[id], id);
+ console.log("selecting packet " + id);
+ if (selected_packet !== null) {
+ document
+ .getElementById("packet-" + selected_packet)!
+ .classList.remove("log-selected");
+ document
+ .getElementById("packet-" + selected_packet)!
+ .classList.add("log-item");
+ }
+ document.getElementById("packet-" + id)!.classList.add("log-selected");
+ document.getElementById("packet-" + id)!.classList.remove("log-item");
+ selected_packet = id;
+ show_packet(packets[id], id);
}
export function appendPacket(packet: Packet) {
- packets.push(packet);
- return;
-/*
+ packets.push(packet);
+ return;
+ /*
let duration = "--";
if (last_packet !== null) {
duration = (new Date().getTime() - last_packet!.getTime()).toString() + "ms";
M starkingdoms-client/src/planet_colors.ts => starkingdoms-client/src/planet_colors.ts +7 -7
@@ 1,9 1,9 @@
-import {PlanetType} from "./protocol.ts";
+import { PlanetType } from "./protocol.ts";
export function planet_color(type: PlanetType): string {
- if (type === PlanetType.Earth) {
- return "limegreen";
- } else {
- return "white";
- }
-}>
\ No newline at end of file
+ if (type === PlanetType.Earth) {
+ return "limegreen";
+ } else {
+ return "white";
+ }
+}
M starkingdoms-client/src/protocol.ts => starkingdoms-client/src/protocol.ts +76 -56
@@ 1,99 1,119 @@
export interface ProtoTransform {
- x: number,
- y: number,
- rot: number
+ x: number;
+ y: number;
+ rot: number;
}
export enum PlanetType {
- Earth = "Earth"
+ Earth = "Earth",
}
export enum PartType {
- Hearty = "Hearty"
+ Hearty = "Hearty",
}
export interface Planet {
- planet_type: PlanetType,
- transform: ProtoTransform,
- radius: number
+ planet_type: PlanetType;
+ transform: ProtoTransform;
+ radius: number;
}
export interface Part {
- part_type: PartType,
- transform: ProtoTransform
+ part_type: PartType;
+ transform: ProtoTransform;
}
export interface ClientLoginPacket {
- username: string,
- jwt: string | null,
+ username: string;
+ jwt: string | null;
}
export interface SpawnPlayerPacket {
- id: number,
- username: string
+ id: number;
+ username: string;
}
export interface PlanetPositionsPacket {
- planets: [number, Planet][]
+ planets: [number, Planet][];
}
export interface PartPositionsPacket {
- parts: [number, Part][]
+ parts: [number, Part][];
}
export interface PlayerInputPacket {
- up: boolean,
- down: boolean,
- left: boolean,
- right: boolean,
+ up: boolean;
+ down: boolean;
+ left: boolean;
+ right: boolean;
}
export interface PlayerListPacket {
- players: [number, string][]
+ players: [number, string][];
}
export interface PlayerLeavePacket {
- id: number
+ id: number;
}
export interface SendMessagePacket {
- target: string | null,
- content: string
+ target: string | null;
+ content: string;
}
export enum MessageType {
- Server = "Server",
- Error = "Error",
- Chat = "Chat",
- Direct = "Direct"
+ Server = "Server",
+ Error = "Error",
+ Chat = "Chat",
+ Direct = "Direct",
}
export interface MessagePacket {
- message_type: MessageType,
- actor: string,
- content: string
+ message_type: MessageType;
+ actor: string;
+ content: string;
}
export enum PacketType {
- // serverbound
- ClientLogin = "ClientLogin",
- SendMessage = "SendMessage",
- PlayerInput = "PlayerInput",
- // clientbound
- SpawnPlayer = "SpawnPlayer",
- PlayerList = "PlayerList",
- PlanetPositions = "PlanetPositions",
- PartPositions = "PartPositions",
- PlayerLeave = "PlayerLeave",
- Message = "Message"
+ // serverbound
+ ClientLogin = "ClientLogin",
+ SendMessage = "SendMessage",
+ PlayerInput = "PlayerInput",
+ // clientbound
+ SpawnPlayer = "SpawnPlayer",
+ PlayerList = "PlayerList",
+ PlanetPositions = "PlanetPositions",
+ PartPositions = "PartPositions",
+ PlayerLeave = "PlayerLeave",
+ Message = "Message",
}
export interface Packet {
- t: PacketType,
- c: ClientLoginPacket | SpawnPlayerPacket | PlayerListPacket | PlanetPositionsPacket | PartPositionsPacket | PlayerLeavePacket | SendMessagePacket | MessagePacket | PlayerInputPacket
+ t: PacketType;
+ c:
+ | ClientLoginPacket
+ | SpawnPlayerPacket
+ | PlayerListPacket
+ | PlanetPositionsPacket
+ | PartPositionsPacket
+ | PlayerLeavePacket
+ | SendMessagePacket
+ | MessagePacket
+ | PlayerInputPacket;
}
-export const SERVERBOUND = [PacketType.ClientLogin, PacketType.SendMessage, PacketType.PlayerInput];
-export const CLIENTBOUND = [PacketType.SpawnPlayer, PacketType.PlayerList, PacketType.PlanetPositions, PacketType.PartPositions, PacketType.PlayerLeave, PacketType.Message];
+export const SERVERBOUND = [
+ PacketType.ClientLogin,
+ PacketType.SendMessage,
+ PacketType.PlayerInput,
+];
+export const CLIENTBOUND = [
+ PacketType.SpawnPlayer,
+ PacketType.PlayerList,
+ PacketType.PlanetPositions,
+ PacketType.PartPositions,
+ PacketType.PlayerLeave,
+ PacketType.Message,
+];
export enum Direction {
- Serverbound = "Serverbound",
- Clientbound = "Clientbound",
- InvalidType = "InvalidType"
+ Serverbound = "Serverbound",
+ Clientbound = "Clientbound",
+ InvalidType = "InvalidType",
}
export function type_direction(type: PacketType): Direction {
- if (SERVERBOUND.includes(type)) {
- return Direction.Serverbound;
- } else if (CLIENTBOUND.includes(type)) {
- return Direction.Clientbound;
- } else {
- return Direction.InvalidType;
- }
+ if (SERVERBOUND.includes(type)) {
+ return Direction.Serverbound;
+ } else if (CLIENTBOUND.includes(type)) {
+ return Direction.Clientbound;
+ } else {
+ return Direction.InvalidType;
+ }
}
M starkingdoms-client/src/rendering.ts => starkingdoms-client/src/rendering.ts +114 -95
@@ 1,117 1,136 @@
-import {global, player} from "./main.ts";
-import {part_texture, planet_texture} from "./textures.ts";
-import {planet_color} from "./planet_colors.ts";
+import { global, player } from "./main.ts";
+import { part_texture, planet_texture } from "./textures.ts";
+import { planet_color } from "./planet_colors.ts";
//let t = performance.now();
//let delta = 0.0;
export function startRender() {
- // hide the launch popup
- document.getElementById("server_selector")!.classList.add("hidden");
- // show the HUD
- document.getElementById("hud")!.classList.remove("hidden");
- // and chat
- document.getElementById("chat")!.classList.remove("hidden");
- // create the canvas
- let canvas = document.createElement("canvas");
- canvas.classList.add("game");
- // append it
- document.getElementById("gamewindow")!.appendChild(canvas);
- let ctx = canvas.getContext("2d")!;
+ // hide the launch popup
+ document.getElementById("server_selector")!.classList.add("hidden");
+ // show the HUD
+ document.getElementById("hud")!.classList.remove("hidden");
+ // and chat
+ document.getElementById("chat")!.classList.remove("hidden");
+ // create the canvas
+ let canvas = document.createElement("canvas");
+ canvas.classList.add("game");
+ // append it
+ document.getElementById("gamewindow")!.appendChild(canvas);
+ let ctx = canvas.getContext("2d")!;
+ ctx.canvas.width = window.innerWidth;
+ ctx.canvas.height = window.innerHeight;
+
+ window.onresize = () => {
ctx.canvas.width = window.innerWidth;
ctx.canvas.height = window.innerHeight;
-
- window.onresize = () => {
- ctx.canvas.width = window.innerWidth;
- ctx.canvas.height = window.innerHeight;
- }
-
- global.rendering = {
- canvas: canvas,
- ctx: ctx
- };
- //t = performance.now();
- //delta = 0.0;
- // start the render loop
- requestAnimationFrame(renderLoop);
+ };
+
+ global.rendering = {
+ canvas: canvas,
+ ctx: ctx,
+ };
+ //t = performance.now();
+ //delta = 0.0;
+ // start the render loop
+ requestAnimationFrame(renderLoop);
}
async function renderLoop(_newT: DOMHighResTimeStamp) {
- //delta = newT - t;
- //t = newT;
+ //delta = newT - t;
+ //t = newT;
- let viewer_size_x = global.rendering?.canvas.width!;
- let viewer_size_y = global.rendering?.canvas.height!;
+ let viewer_size_x = global.rendering?.canvas.width!;
+ let viewer_size_y = global.rendering?.canvas.height!;
- global.rendering!.canvas.style.setProperty("background-position", `${player()?.transform.x!/5}px ${-player()?.transform.y!/5}px`);
+ global.rendering!.canvas.style.setProperty(
+ "background-position",
+ `${player()?.transform.x! / 5}px ${-player()?.transform.y! / 5}px`,
+ );
- global.rendering!.ctx.setTransform(1, 0, 0, 1, 0, 0);
- global.rendering!.ctx.clearRect(0, 0, viewer_size_x, viewer_size_y);
+ global.rendering!.ctx.setTransform(1, 0, 0, 1, 0, 0);
+ global.rendering!.ctx.clearRect(0, 0, viewer_size_x, viewer_size_y);
- // *dont* translate the camera. we're moving everything else around us. cameracentrism.
- // only translation will be to center our core module.
+ // *dont* translate the camera. we're moving everything else around us. cameracentrism.
+ // only translation will be to center our core module.
- global.rendering!.ctx.translate(viewer_size_x / 2, viewer_size_y / 2);
+ global.rendering!.ctx.translate(viewer_size_x / 2, viewer_size_y / 2);
- /*
+ /*
todo: track indicator
*/
- for (let [_id, planet] of global.planets_map) {
- global.rendering!.ctx.drawImage(
- await planet_texture(planet.planet_type),
- (planet.transform.x - planet.radius - player()?.transform.x!), // dx
- (planet.transform.y - planet.radius - player()?.transform.y!), // dy
- planet.radius * 2, // dw
- planet.radius * 2 // dh
- );
-
- global.rendering!.ctx.beginPath();
- global.rendering!.ctx.strokeStyle = planet_color(planet.planet_type);
- global.rendering!.ctx.lineWidth = 5;
- global.rendering!.ctx.moveTo(player()!.transform.x - player()!.transform.x, player()!.transform.y - player()!.transform.y);
- global.rendering!.ctx.lineTo(planet.transform.x - player()!.transform.x, planet.transform.y - player()!.transform.y);
- global.rendering!.ctx.stroke();
- }
-
- for (let [_id, part] of global.parts_map) {
- global.rendering!.ctx.save();
-
- // x_{screen} = x_{world} - player_{x_{world}}
- // x_{world} = x_{screen} + player_{x_{world}}
-
- global.rendering!.ctx.translate(part.transform.x - player()!.transform.x, part.transform.y - player()!.transform.y);
-
- global.rendering!.ctx.rotate(part.transform.rot);
-
- global.rendering!.ctx.drawImage(
- await part_texture(part.part_type),
- -25, -25, 50, 50
- );
-
- global.rendering!.ctx.restore();
-
- // todo: clicked stuff
+ for (let [_id, planet] of global.planets_map) {
+ global.rendering!.ctx.drawImage(
+ await planet_texture(planet.planet_type),
+ planet.transform.x - planet.radius - player()?.transform.x!, // dx
+ planet.transform.y - planet.radius - player()?.transform.y!, // dy
+ planet.radius * 2, // dw
+ planet.radius * 2, // dh
+ );
+
+ global.rendering!.ctx.beginPath();
+ global.rendering!.ctx.strokeStyle = planet_color(planet.planet_type);
+ global.rendering!.ctx.lineWidth = 5;
+ global.rendering!.ctx.moveTo(
+ player()!.transform.x - player()!.transform.x,
+ player()!.transform.y - player()!.transform.y,
+ );
+ global.rendering!.ctx.lineTo(
+ planet.transform.x - player()!.transform.x,
+ planet.transform.y - player()!.transform.y,
+ );
+ global.rendering!.ctx.stroke();
+ }
+
+ for (let [_id, part] of global.parts_map) {
+ global.rendering!.ctx.save();
+
+ // x_{screen} = x_{world} - player_{x_{world}}
+ // x_{world} = x_{screen} + player_{x_{world}}
+
+ global.rendering!.ctx.translate(
+ part.transform.x - player()!.transform.x,
+ part.transform.y - player()!.transform.y,
+ );
+
+ global.rendering!.ctx.rotate(part.transform.rot);
+
+ global.rendering!.ctx.drawImage(
+ await part_texture(part.part_type),
+ -25,
+ -25,
+ 50,
+ 50,
+ );
+
+ global.rendering!.ctx.restore();
+
+ // todo: clicked stuff
+ }
+
+ for (let [id, username] of global.players_map) {
+ let part = global.parts_map.get(id);
+
+ if (part !== undefined) {
+ global.rendering!.ctx.save();
+
+ global.rendering!.ctx.translate(
+ part!.transform.x - player()!.transform.x,
+ part!.transform.y - player()!.transform.y,
+ );
+
+ global.rendering!.ctx.textAlign = "center";
+ global.rendering!.ctx.font =
+ '30px ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"';
+ global.rendering!.ctx.fillStyle = "white";
+ global.rendering!.ctx.fillText(username, 0, -35);
+
+ global.rendering!.ctx.restore();
}
+ }
- for (let [id, username] of global.players_map) {
- let part = global.parts_map.get(id);
-
- if (part !== undefined) {
- global.rendering!.ctx.save();
-
- global.rendering!.ctx.translate(part!.transform.x - player()!.transform.x, part!.transform.y - player()!.transform.y);
-
- global.rendering!.ctx.textAlign = "center";
- global.rendering!.ctx.font = '30px ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"';
- global.rendering!.ctx.fillStyle = "white";
- global.rendering!.ctx.fillText(username, 0, -35);
+ // particles stuff
- global.rendering!.ctx.restore();
- }
- }
-
- // particles stuff
-
- requestAnimationFrame(renderLoop);
-}>
\ No newline at end of file
+ requestAnimationFrame(renderLoop);
+}
M starkingdoms-client/src/textures.ts => starkingdoms-client/src/textures.ts +39 -37
@@ 1,4 1,4 @@
-import {PartType, PlanetType} from "./protocol.ts";
+import { PartType, PlanetType } from "./protocol.ts";
import tex_earth from "./assets/earth.svg";
import tex_hearty from "./assets/hearty.svg";
import tex_missing from "./assets/missing.svg";
@@ 6,49 6,51 @@ import tex_missing from "./assets/missing.svg";
let planet_textures: Map<PlanetType, HTMLImageElement> = new Map();
function planet_texture_url(type: PlanetType): string {
- if (type == PlanetType.Earth) {
- return tex_earth;
- }
- return tex_missing;
+ if (type == PlanetType.Earth) {
+ return tex_earth;
+ }
+ return tex_missing;
}
-export async function planet_texture(type: PlanetType): Promise<HTMLImageElement> {
- return new Promise((resolve, reject) => {
- if (planet_textures.has(type)) {
- resolve(planet_textures.get(type)!);
- } else {
- let img = new Image();
- img.onload = () => {
- planet_textures.set(type, img);
- resolve(img);
- };
- img.onerror = reject;
- img.src = planet_texture_url(type)
- }
- });
+export async function planet_texture(
+ type: PlanetType,
+): Promise<HTMLImageElement> {
+ return new Promise((resolve, reject) => {
+ if (planet_textures.has(type)) {
+ resolve(planet_textures.get(type)!);
+ } else {
+ let img = new Image();
+ img.onload = () => {
+ planet_textures.set(type, img);
+ resolve(img);
+ };
+ img.onerror = reject;
+ img.src = planet_texture_url(type);
+ }
+ });
}
let part_textures: Map<PartType, HTMLImageElement> = new Map();
function part_texture_url(type: PartType): string {
- if (type == PartType.Hearty) {
- return tex_hearty;
- }
- return tex_missing;
+ if (type == PartType.Hearty) {
+ return tex_hearty;
+ }
+ return tex_missing;
}
export async function part_texture(type: PartType): Promise<HTMLImageElement> {
- return new Promise((resolve, reject) => {
- if (part_textures.has(type)) {
- resolve(part_textures.get(type)!);
- } else {
- let img = new Image();
- img.onload = () => {
- part_textures.set(type, img);
- resolve(img);
- };
- img.onerror = reject;
- img.src = part_texture_url(type)
- }
- });
-}>
\ No newline at end of file
+ return new Promise((resolve, reject) => {
+ if (part_textures.has(type)) {
+ resolve(part_textures.get(type)!);
+ } else {
+ let img = new Image();
+ img.onload = () => {
+ part_textures.set(type, img);
+ resolve(img);
+ };
+ img.onerror = reject;
+ img.src = part_texture_url(type);
+ }
+ });
+}
M starkingdoms-client/vite.config.ts => starkingdoms-client/vite.config.ts +15 -12
@@ 1,16 1,19 @@
-import {defineConfig} from "vite";
+import { defineConfig } from "vite";
import * as child from "child_process";
-const commitHash = child.execSync('git describe --no-match --always --abbrev=8 --dirty').toString().trim();
+const commitHash = child
+ .execSync("git describe --no-match --always --abbrev=8 --dirty")
+ .toString()
+ .trim();
export default defineConfig({
- plugins: [],
- define: {
- APP_VERSION: JSON.stringify(process.env.npm_package_version),
- COMMIT_HASH: JSON.stringify(commitHash)
- },
- build: {
- target: ['chrome89', 'edge89', 'firefox89', 'safari15'],
- cssCodeSplit: false,
- }
-})>
\ No newline at end of file
+ plugins: [],
+ define: {
+ APP_VERSION: JSON.stringify(process.env.npm_package_version),
+ COMMIT_HASH: JSON.stringify(commitHash),
+ },
+ build: {
+ target: ["chrome89", "edge89", "firefox89", "safari15"],
+ cssCodeSplit: false,
+ },
+});