~starkingdoms/starkingdoms

5858f61132af20fb3a03c130c49bff53291c7bad — ghostlyzsh 1 year, 11 months ago f4c1d03 + 58de35a
Merge branch 'bevy_rewrite' of https://gitlab.com/starkingdoms.tk/starkingdoms.tk into bevy_rewrite
M starkingdoms-client/src/components/Chatbox.svelte => starkingdoms-client/src/components/Chatbox.svelte +63 -15
@@ 1,29 1,77 @@
<script lang="ts">
  import Popup from "./ui/Popup.svelte";
  import { type Packet, PacketType } from "../protocol.ts";
  import { sendPacket } from "../hub.ts";
  import { global } from "../globals.js";
  import { afterUpdate } from "svelte";
  import TextInput from "./ui/TextInput.svelte";

  interface Message {
    classname: string;
    message: string;
  }

  let messages: Message[] = [];
  let chatbox: HTMLDivElement | null;
  let value = "";

  export function addMessage(classname: string, message: string) {
    let chatbox = document.getElementById("chatbox")!;
    let should_scroll =
      chatbox!.scrollTop == chatbox!.scrollHeight - chatbox!.offsetHeight;
    let p = document.createElement("p");
    p.innerText = message;
    p.classList.add("message");
    p.classList.add(classname);
    if (chatbox.children.length > 128) {
      chatbox.children[0]!.remove();
    messages.push({ classname: classname, message: message });
    messages = messages; // Trigger Svelte reactivity
  }

  afterUpdate(() => {
    if (chatbox !== null) {
      chatbox.scrollTo(0, chatbox.scrollHeight);
    }
    chatbox!.appendChild(p);
    if (should_scroll) {
      chatbox!.scrollTop = chatbox!.scrollHeight;
  });

  function onkeydown(e: KeyboardEvent) {
    if (e.key === "Enter") {
      if (value.startsWith(".msg")) {
        let args = value.split(" ");
        if (args.length < 3) {
          addMessage("server-error", "Command error");

          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(global.client!, chat_packet);

        addMessage("direct-message", `you -> ${target}: ${message}`);
      } else {
        let chat_packet: Packet = {
          t: PacketType.SendMessage,
          c: {
            target: null,
            content: value,
          },
        };
        sendPacket(global.client!, chat_packet);
      }
      value = "";
    }
  }
</script>

<Popup draggable minimizable title="Chat" class="chat-container" id="chat">
  <div id="chatbox" class="chat-table mono">
    <!-- Filled by script -->
  <div bind:this={chatbox} id="chatbox" class="chat-table mono">
    {#each messages as message}
      <p class="message {message.classname}">{message.message}</p>
    {/each}
  </div>
  <input
  <TextInput
    bind:value
    on:keydown={onkeydown}
    placeholder="Enter message or command here..."
    class="chat-box"
    id="chatentry"

A starkingdoms-client/src/components/ui/Button.svelte => starkingdoms-client/src/components/ui/Button.svelte +28 -0
@@ 0,0 1,28 @@
<script lang="ts">
  let clazz: string = "";
  export { clazz as class };
  export let id: string = "";
  export let disabled = false;
  export let style = "";
</script>

<button {id} class="btn {clazz}" {disabled} on:click on:focus {style}>
  <slot />
</button>

<style lang="scss">
  .btn {
    appearance: none;
    background: transparent;
    color: var(--text);
    padding: 0.675em 1em;
    border-radius: 0.25rem;
    cursor: text;
    border: 2px solid var(--links);
    transition: 0.1s ease-in-out;
  }
  .btn:hover {
    cursor: pointer;
    background-color: var(--links-transparent);
  }
</style>

M starkingdoms-client/src/components/ui/Popup.svelte => starkingdoms-client/src/components/ui/Popup.svelte +7 -20
@@ 3,6 3,7 @@
  import MovableIcon from "../../icons/MovableIcon.svelte";
  import ChevronDown from "../../icons/ChevronDown.svelte";
  import ChevronUp from "../../icons/ChevronUp.svelte";
  import Button from "./Button.svelte";

  let clazz = "";
  export { clazz as class };


@@ 26,16 27,15 @@
  let minimized = false;

  onMount(() => {
    console.log("popup mounted");
    if (draggable) {
      console.log("importing old window positions");

      let top = window.localStorage.getItem(`pop-${id}top`);
      let left = window.localStorage.getItem(`pop-${id}left`);

      popup.style.top = top;
      popup.style.left = left;
      console.log("imported, top = " + top + " left = " + left);
    }
    if (minimizable) {
      minimized = window.localStorage.getItem(`pop-${id}minim`) === "yes";
    }
  });



@@ 60,15 60,6 @@

    window.localStorage.setItem(`pop-${id}top`, popup.style.top);
    window.localStorage.setItem(`pop-${id}left`, popup.style.left);

    console.log(
      "dragged, top = " +
        (popup.offsetTop - pos2) +
        "px" +
        " left = " +
        (popup.offsetLeft - pos1) +
        "px",
    );
  }

  function closeDragElement() {


@@ 82,6 73,7 @@
  function toggleMinimized() {
    if (minimizable) {
      minimized = !minimized;
      window.localStorage.setItem(`pop-${id}minim`, minimized ? "yes" : "no");
    }
  }
</script>


@@ 96,13 88,13 @@
        {title}
      </h1>
      {#if minimizable}
        <button class="hdrbtn" on:click|preventDefault={toggleMinimized}>
        <Button class="hdrbtn" on:click={toggleMinimized}>
          {#if minimized}
            <ChevronDown class="hdrbtn-icon" />
          {:else}
            <ChevronUp class="hdrbtn-icon" />
          {/if}
        </button>
        </Button>
      {/if}
    </div>
  {/if}


@@ 133,16 125,11 @@
  }

  :global(.hdrbtn) {
    cursor: pointer;
    position: absolute;
    width: 2rem;
    height: 2rem;
    right: 1em;
    top: 1em;
    border: 1px solid var(--links);
    border-radius: 0.25rem;
    appearance: none;
    background: transparent;
  }

  :global(.hdrbtn-icon) {

A starkingdoms-client/src/components/ui/TextInput.svelte => starkingdoms-client/src/components/ui/TextInput.svelte +40 -0
@@ 0,0 1,40 @@
<script lang="ts">
  let clazz: string = "";
  export { clazz as class };
  export let id: string = "";
  export let disabled = false;
  export let style = "";
  export let required = false;
  export let autocomplete = "";
  export let value = "";
  export let placeholder = "";
</script>

<input
  bind:value
  type="text"
  {id}
  class="txt {clazz}"
  {disabled}
  on:click
  on:focus
  on:input
  on:change
  on:keydown
  on:keyup
  {style}
  {required}
  {autocomplete}
  {placeholder} />

<style lang="scss">
  .txt {
    appearance: none;
    background: transparent;
    color: var(--text);
    padding: 0.675em 1em;
    border: 1px solid var(--links);
    border-radius: 0.25rem;
    cursor: text;
  }
</style>

M starkingdoms-client/src/css/form.scss => starkingdoms-client/src/css/form.scss +0 -10
@@ 22,16 22,6 @@
  max-width: 100%;
}

.btn {
  @extend %form-element-shared;
  border: 2px solid var(--links);
  transition: 0.1s ease-in-out;
}
.btn:hover {
  cursor: pointer;
  background-color: var(--links-transparent);
}

.textentry {
  @extend %form-element-shared;
}

M starkingdoms-client/src/hub.ts => starkingdoms-client/src/hub.ts +1 -40
@@ 50,6 50,7 @@ export async function hub_connect(
    let client: ClientHub = {
      socket: ws,
    };
    global.client = client;

    let packet: Packet = {
      t: PacketType.ClientLogin,


@@ 163,46 164,6 @@ export async function hub_connect(
      }
    };

    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) {
            chatbox.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);

          chatbox.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);


M starkingdoms-client/src/packet_ui.ts => starkingdoms-client/src/packet_ui.ts +0 -1
@@ 136,7 136,6 @@ 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)!

M starkingdoms-client/src/pages/Home.svelte => starkingdoms-client/src/pages/Home.svelte +8 -6
@@ 7,6 7,8 @@
  import HeartIcon from "../icons/HeartIcon.svelte";
  import WarningIcon from "../icons/WarningIcon.svelte";
  import Popup from "../components/ui/Popup.svelte";
  import Button from "../components/ui/Button.svelte";
  import TextInput from "../components/ui/TextInput.svelte";

  let config = DEFAULT_CONFIG;
  // Top-level await. Sets the default config, and overwrites it when the new config is avail. Thanks reactivity!


@@ 32,10 34,10 @@

  const is_development = window.localStorage.getItem("stk-mode") === "debug";

  let nonprod_warning;
  let nonprod_warning: HTMLSpanElement;

  let server;
  let username;
  let server = "";
  let username = "";

  function playGame() {
    window.location.href = `/play/?srv=${server}&username=${username}`;


@@ 58,9 60,9 @@

  <form id="join-fm" class="form" on:submit|preventDefault={playGame}>
    <label for="username" class="label">Username</label>
    <input
    <TextInput
      style="width: 100%; max-width: 100%;"
      bind:value={username}
      class="textentry"
      id="username"
      required
      autocomplete="off" />


@@ 81,7 83,7 @@
      {/each}
    </select>

    <button id="launch-btn" class="btn">Launch!</button>
    <Button style="width: 100%; max-width: 100%;">Launch!</Button>

    <span bind:this={nonprod_warning} class="server-danger hidden">
      <WarningIcon class="server-danger-icon" />

M starkingdoms-client/src/rendering.ts => starkingdoms-client/src/rendering.ts +0 -2
@@ 41,7 41,6 @@ export function startRender() {
      } else {
        part_sprite = PIXI.Sprite.from(part_texture_url(part.part_type));
        global.rendering!.part_sprite_map.set(id, part_sprite);
        console.log("adding part sprite");
        global.rendering!.app.stage.addChild(part_sprite);
      }



@@ 62,7 61,6 @@ export function startRender() {
          planet_texture_url(planet.planet_type),
        );
        global.rendering!.planet_sprite_map.set(id, planet_sprite);
        console.log("adding planet sprite");
        global.rendering!.app.stage.addChild(planet_sprite);
      }