New REM client: REM-Client 771c9ce7, 64-bit (pilots window: Freelancer IDs, pilots and the picked pilot in one screen, changing the ID asks in a box; server list: Connect, Refresh and Star in one row on top)

This commit is contained in:
2026-11-10 10:24:32 +01:00
parent 28f96394c9
commit 561743134c
29 changed files with 89 additions and 31 deletions
+3 -3
View File
@@ -1,6 +1,6 @@
REM-Client test build (64-bit) REM-Client test build (64-bit)
date: 2026-11-10 09:17 date: 2026-11-10 10:24
commit: b9fbafb2 (main) commit: 771c9ce7 (main)
subject: Comm window: an ether speaker's faction as the second line under its name (rem-server 12f5081, REM message 'h') subject: Server list: Connect, Refresh and Star in one row on top of the side column, Connect twice as wide
tree: clean tree: clean
build: OK build: OK
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
Binary file not shown.
+77 -23
View File
@@ -3,13 +3,24 @@
<title>Characters</title> <title>Characters</title>
<link type="text/rcss" href="rem.rcss"/> <link type="text/rcss" href="rem.rcss"/>
<style> <style>
/* the pilots window: the Freelancer IDs | the pilots of the picked ID | the picked pilot and its buttons */
.split { flex: 1; display: flex; flex-direction: row; min-height: 0; } .split { flex: 1; display: flex; flex-direction: row; min-height: 0; }
.colm { display: flex; flex-direction: column; min-width: 0; min-height: 0; } .colm { display: flex; flex-direction: column; min-width: 0; min-height: 0; }
.colm.list { flex: 1; } .colm.ids { flex: 0 0 22%; }
.colm.side { flex: 0 0 32%; margin-left: 18dp; } .colm.list { flex: 1; margin-left: 18dp; }
.colm.fig { flex: 0 0 22%; margin-left: 18dp; } .colm.side { flex: 0 0 34%; margin-left: 18dp; }
#figure { flex: 1; decorator: vertical-gradient(#0a1424 #05080d); cursor: move; } .idlist { flex: 1; overflow-y: auto; }
.fig .hint { text-align: center; margin-top: 6dp; } .id { padding: 10dp 12dp; margin-bottom: 8dp; border-left: 3dp #3d6d96; background-color: #5cc8f010; }
.id:hover { border-left-color: #5cc8f0; }
.id.selected { background-color: #f2b13c1a; border-left-color: #f2b13c; }
.id .top { display: flex; flex-direction: row; align-items: center; }
.id .n { flex: 1; font-family: "Saira SemiCondensed"; font-weight: 600; font-size: 18dp; }
.id.selected .n { color: #f2b13c; }
.id .tag { font-family: "IBM Plex Mono"; font-size: 11dp; color: #5fd08a; margin-left: 8dp; }
.id .c { font-family: "IBM Plex Mono"; font-size: 12dp; color: #5cc8f0; margin-top: 4dp; }
.newid { padding: 12dp; margin-top: 8dp; background-color: #5cc8f008; }
.newid input.text { display: block; width: 100%; margin: 8dp 0dp 10dp 0dp; }
.idmsg { margin-bottom: 8dp; }
.roster { flex: 1; overflow-y: auto; } .roster { flex: 1; overflow-y: auto; }
.pilot { display: flex; flex-direction: row; align-items: center; padding: 10dp 12dp; margin-bottom: 8dp; border-left: 3dp #3d6d96; background-color: #5cc8f010; } .pilot { display: flex; flex-direction: row; align-items: center; padding: 10dp 12dp; margin-bottom: 8dp; border-left: 3dp #3d6d96; background-color: #5cc8f010; }
.pilot:hover { border-left-color: #5cc8f0; } .pilot:hover { border-left-color: #5cc8f0; }
@@ -21,55 +32,99 @@
.pilot .k { font-size: 13dp; color: #8197ad; margin-top: 2dp; } .pilot .k { font-size: 13dp; color: #8197ad; margin-top: 2dp; }
.pilot .r { text-align: right; } .pilot .r { text-align: right; }
.pilot .m { font-family: "IBM Plex Mono"; color: #f2b13c; } .pilot .m { font-family: "IBM Plex Mono"; color: #f2b13c; }
.pilot.add { border-left-color: #5fd08a; background-color: #5fd08a10; }
.pilot.add .n { color: #5fd08a; }
.pilot.add.disabled { opacity: 0.5; }
.pilot .lv { font-family: "IBM Plex Mono"; font-size: 12dp; color: #5cc8f0; margin-top: 2dp; } .pilot .lv { font-family: "IBM Plex Mono"; font-size: 12dp; color: #5cc8f0; margin-top: 2dp; }
.detail { padding: 12dp; margin-bottom: 12dp; background-color: #5cc8f008; } /* Launch: big, above the figure */
.btn.launch { display: flex; flex-direction: row; align-items: center; justify-content: center; height: 64dp; margin-bottom: 10dp;
font-family: "Saira SemiCondensed"; font-weight: 600; font-size: 24dp; letter-spacing: 3dp; }
.btn.launch img { width: 44dp; height: 44dp; margin-right: 12dp; }
#figure { flex: 1; min-height: 160dp; decorator: vertical-gradient(#0a1424 #05080d); cursor: move; }
.side .hint.turn { text-align: center; margin: 4dp 0dp 8dp 0dp; }
.detail { padding: 12dp; margin-bottom: 10dp; background-color: #5cc8f008; }
.detail .n { font-family: "Saira SemiCondensed"; font-weight: 600; font-size: 22dp; margin-bottom: 4dp; } .detail .n { font-family: "Saira SemiCondensed"; font-weight: 600; font-size: 22dp; margin-bottom: 4dp; }
.detail .k { font-size: 14dp; color: #8197ad; } .detail .k { font-size: 14dp; color: #8197ad; }
.detail .s { white-space: pre-line; font-family: "IBM Plex Mono"; font-size: 13dp; line-height: 1.5; margin-top: 8dp; } .detail .s { white-space: pre-line; font-family: "IBM Plex Mono"; font-size: 13dp; line-height: 1.5; margin-top: 8dp; }
.motd { flex: 1; overflow-y: auto; white-space: pre-line; line-height: 1.45; font-size: 14dp; padding: 12dp; background-color: #5cc8f008; } .motd { flex: 0 0 22%; overflow-y: auto; white-space: pre-line; line-height: 1.45; font-size: 14dp; padding: 12dp; background-color: #5cc8f008; }
.empty-roster { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; } .changeid { display: flex; flex-direction: column; align-items: center; text-align: center; padding: 24dp 12dp; margin-bottom: 12dp; background-color: #f2b13c10; }
.changeid .hint { margin-bottom: 12dp; }
.changeid .btn { font-size: 18dp; padding: 10dp 24dp; }
.empty-roster { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; }
</style> </style>
</head> </head>
<body class="window" data-model="charselect"> <body class="window" data-model="charselect">
<div class="win-head"> <div class="win-head">
<span class="title">{{ server }}</span><span class="sl">\\\</span> <span class="title">{{ server }}</span><span class="sl">\\\</span>
<span class="spacer"></span> <span class="spacer"></span>
<span class="chip" data-if="who != ''">Discord <span class="v">{{ who }}</span></span>
<span class="chip">Characters <span class="v">{{ chars.size }}</span><span data-if="limit &gt; 0"> / <span class="v">{{ limit }}</span></span></span> <span class="chip">Characters <span class="v">{{ chars.size }}</span><span data-if="limit &gt; 0"> / <span class="v">{{ limit }}</span></span></span>
</div> </div>
<div class="win-main"> <div class="win-main">
<div class="content"> <div class="content">
<div class="split"> <div class="split">
<!-- the Freelancer IDs of the Discord account -->
<div class="colm ids">
<h3 style="margin-bottom: 8dp;">Freelancer IDs</h3>
<div class="hint idmsg" data-if="id_message != ''">{{ id_message }}</div>
<div class="hint" data-if="id_state == 'loading'">Asking the REM website...</div>
<div class="btn" data-if="id_state == 'error'" data-action="retry">Try again</div>
<div class="idlist" data-if="id_state == 'ready'">
<div class="id" data-for="r : ids" data-class-selected="r.selected" data-action="pickid" data-attr-data-arg="r.key">
<div class="top"><span class="n">{{ r.name }}</span><span class="tag" data-if="r.current">IN USE</span></div>
<div class="c">{{ r.pilots }}</div>
</div>
</div>
<div class="newid" data-if="id_state == 'ready'">
<h3>New ID</h3>
<input class="text" type="text" data-value="new_name" placeholder="Name of the ID (only for you)" maxlength="40"/>
<div class="btn" data-class-disabled="busy || new_name == ''" data-action="create">Make the ID<div class="tip">A fresh Freelancer ID on your Discord account - for more pilots on the server. Pick it and switch to it to create its pilots.</div></div>
</div>
</div>
<!-- the pilots of the picked ID -->
<div class="colm list"> <div class="colm list">
<h3 style="margin-bottom: 8dp;">Your pilots</h3> <h3 style="margin-bottom: 8dp;">Pilots</h3>
<div class="empty-roster" data-if="chars.size == 0"> <div class="pilot add" data-if="!other_id" data-class-disabled="!can_new || !ready" data-action="new">
<div class="txt"><div class="n">+ New pilot</div></div>
<div class="tip">Creates a new pilot (as many per ID as the server allows).</div>
</div>
<div class="empty-roster" data-if="!other_id && chars.size == 0">
<div class="hint">No pilot on this server yet. Create one to begin.</div> <div class="hint">No pilot on this server yet. Create one to begin.</div>
</div> </div>
<div class="roster" data-if="chars.size &gt; 0"> <div class="roster" data-if="!other_id && chars.size &gt; 0">
<div class="pilot" data-for="c : chars" data-class-selected="c.selected" data-action="pick" data-attr-data-arg="c.key"> <div class="pilot" data-for="c : chars" data-class-selected="c.selected" data-action="pick" data-attr-data-arg="c.key">
<img data-if="c.icon != ''" data-attr-src="c.icon"/> <img data-if="c.icon != ''" data-attr-src="c.icon"/>
<div class="txt"><div class="n">{{ c.name }}</div><div class="k">{{ c.ship }} - {{ c.place }}</div></div> <div class="txt"><div class="n">{{ c.name }}</div><div class="k">{{ c.ship }} - {{ c.place }}</div></div>
<div class="r"><div class="m">{{ c.money }}</div><div class="lv">{{ c.level }}</div></div> <div class="r"><div class="m">{{ c.money }}</div><div class="lv">{{ c.level }}</div></div>
</div> </div>
</div> </div>
<div class="actions" style="margin-top: 10dp;"> <div class="changeid" data-if="other_id">
<div class="btn primary" data-class-disabled="!has_pick || !ready" data-action="load">Launch<div class="tip">Plays the picked pilot. A double click on a pilot does the same.</div></div> <div class="hint">The pilots of this ID show once you play with it.</div>
<div class="btn" data-class-disabled="!can_new || !ready" data-action="new">New pilot<div class="tip">Creates a new pilot (as many per ID as the server allows).</div></div> <div class="btn primary" data-class-disabled="busy || !ready" data-action="switchid">Click here to change ID<div class="tip">Leaves the server and joins it again with this ID; you pick the pilot there.</div></div>
<div class="btn" data-class-disabled="!has_pick || !ready" data-action="delete">Delete<div class="tip">Deletes the picked pilot for good (you are asked first).</div></div> </div>
<div class="roster" data-if="other_id && other_chars.size &gt; 0">
<div class="hint" style="margin-bottom: 8dp;">Known pilots of this ID (pick one to launch it right after the change):</div>
<div class="pilot" data-for="c : other_chars" data-class-selected="c.selected" data-action="pickother" data-attr-data-arg="c.key">
<div class="txt"><div class="n">{{ c.name }}</div></div>
<div class="r"><div class="m">{{ c.money }}</div></div>
</div>
</div> </div>
</div> </div>
<div class="colm fig"> <!-- the picked pilot and what can be done with it -->
<h3 style="margin-bottom: 8dp;">Pilot</h3>
<div id="figure"></div>
<div class="hint">drag to turn</div>
</div>
<div class="colm side"> <div class="colm side">
<div class="detail" data-if="has_pick"> <div class="btn primary launch" data-class-disabled="!can_launch" data-action="load"><img src="3db:interface/baseside/take_off.3db"/>{{ launch_label }}<div class="tip">Plays the picked pilot (a double click on it does the same). On another ID: switches to it, joins the server again and plays the picked pilot.</div></div>
<div id="figure" data-if="!other_id"></div>
<div class="hint turn" data-if="!other_id">drag to turn</div>
<div class="detail" data-if="!other_id && has_pick">
<div class="n">{{ pick.name }}</div> <div class="n">{{ pick.name }}</div>
<div class="k">{{ pick.level }} - {{ pick.money }}</div> <div class="k">{{ pick.level }} - {{ pick.money }}</div>
<div class="k">{{ pick.ship }}, {{ pick.place }}</div> <div class="k">{{ pick.ship }}, {{ pick.place }}</div>
<div class="s">{{ pick_stats }}</div> <div class="s">{{ pick_stats }}</div>
</div> </div>
<div class="detail" data-if="!has_pick"><div class="k">Pick a pilot.</div></div> <div class="detail" data-if="!other_id && !has_pick"><div class="k">Pick a pilot.</div></div>
<div class="actions" style="margin-bottom: 10dp;">
<div class="btn danger" data-class-disabled="other_id || !has_pick || !ready" data-action="delete">Delete<div class="tip">Deletes the picked pilot for good (you are asked first).</div></div>
</div>
<h3 style="margin-bottom: 8dp;">Message of the day</h3> <h3 style="margin-bottom: 8dp;">Message of the day</h3>
<div class="motd">{{ motd }}</div> <div class="motd">{{ motd }}</div>
</div> </div>
@@ -78,7 +133,6 @@
</div> </div>
<div class="win-foot"> <div class="win-foot">
<div class="btn" data-action="back">Back to servers</div> <div class="btn" data-action="back">Back to servers</div>
<div class="btn" data-action="accounts">Change account<div class="tip">Another Freelancer ID of your Discord account (its own pilots), or a new one.</div></div>
<div class="btn" data-action="menu">Main menu</div> <div class="btn" data-action="menu">Main menu</div>
</div> </div>
</body> </body>
+9 -5
View File
@@ -27,6 +27,10 @@
.table .c0 img.on { opacity: 1; } .table .c0 img.on { opacity: 1; }
.facts { white-space: pre-line; font-family: "IBM Plex Mono"; font-size: 13dp; line-height: 1.5; color: #8197ad; margin-bottom: 10dp; } .facts { white-space: pre-line; font-family: "IBM Plex Mono"; font-size: 13dp; line-height: 1.5; color: #8197ad; margin-bottom: 10dp; }
.desc { flex: 1; overflow-y: auto; white-space: pre-line; line-height: 1.45; padding: 12dp; background-color: #5cc8f008; } .desc { flex: 1; overflow-y: auto; white-space: pre-line; line-height: 1.45; padding: 12dp; background-color: #5cc8f008; }
/* the buttons on top in one row: Connect twice as wide as Refresh and Star */
.actions.top { flex-wrap: nowrap; margin-bottom: 10dp; }
.actions.top .btn { flex: 1 1 0; text-align: center; margin: 0 0 0 8dp; }
.actions.top .btn.connect { flex: 2 1 0; margin-left: 0; font-size: 16dp; letter-spacing: 3dp; }
.pick-name { font-family: "Saira SemiCondensed"; font-weight: 600; font-size: 21dp; margin-bottom: 6dp; } .pick-name { font-family: "Saira SemiCondensed"; font-weight: 600; font-size: 21dp; margin-bottom: 6dp; }
</style> </style>
</head> </head>
@@ -68,17 +72,17 @@
</div> </div>
</div> </div>
<div class="colm side"> <div class="colm side">
<div class="actions top">
<div class="btn primary connect" data-class-disabled="!can_connect" data-action="connect">Connect<div class="tip">Joins the picked server; a locked one asks for its password.</div></div>
<div class="btn" data-action="refresh">Refresh<div class="tip">Asks the list server again.</div></div>
<div class="btn" data-if="has_pick" data-action="fav">{{ pick_fav ? 'Unstar' : 'Star' }}<div class="tip">Favourite servers are listed under FAV SERVERS (and in the launcher).</div></div>
</div>
<div data-if="has_pick"> <div data-if="has_pick">
<div class="pick-name">{{ pick_name }}</div> <div class="pick-name">{{ pick_name }}</div>
<div class="facts">{{ pick_facts }}</div> <div class="facts">{{ pick_facts }}</div>
</div> </div>
<div class="desc" data-if="has_pick">{{ pick_text }}</div> <div class="desc" data-if="has_pick">{{ pick_text }}</div>
<div class="hint" data-if="!has_pick">Pick a server. A double click joins it.</div> <div class="hint" data-if="!has_pick">Pick a server. A double click joins it.</div>
<div class="actions" style="margin-top: 12dp;">
<div class="btn primary" data-class-disabled="!can_connect" data-action="connect">Connect<div class="tip">Joins the picked server; a locked one asks for its password.</div></div>
<div class="btn" data-action="refresh">Refresh<div class="tip">Asks the list server again.</div></div>
<div class="btn" data-if="has_pick" data-action="fav">{{ pick_fav ? 'Unstar' : 'Star' }}<div class="tip">Favourite servers are listed under FAV SERVERS (and in the launcher).</div></div>
</div>
</div> </div>
</div> </div>
</div> </div>
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.