Add MineGeo gameplay systems and interface
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
import Link from "next/link";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { Copy, Users, Crown, Trophy } from "lucide-react";
|
||||
import { Copy, Users, Crown, Trophy, MessageCircle } from "lucide-react";
|
||||
import { Brand } from "./Brand";
|
||||
import { MultiplayerGame } from "./MultiplayerGame";
|
||||
import { RoomChat } from "./RoomChat";
|
||||
@@ -22,6 +22,8 @@ export function MultiplayerRoom({ id }: { id: string }) {
|
||||
const [name, setName] = useState("");
|
||||
const [invite, setInvite] = useState("");
|
||||
const [copied, setCopied] = useState(false);
|
||||
const [sharing, setSharing] = useState(false);
|
||||
const [shareMessage, setShareMessage] = useState("");
|
||||
const clock = useRef<ReturnType<typeof roundClock> | null>(null);
|
||||
const version = useRef(0);
|
||||
const acting = useRef(false);
|
||||
@@ -105,6 +107,22 @@ export function MultiplayerRoom({ id }: { id: string }) {
|
||||
setError("Copy the invite link from the field below");
|
||||
}
|
||||
}
|
||||
async function publishParty() {
|
||||
if (sharing) return;
|
||||
setSharing(true);
|
||||
setShareMessage("");
|
||||
try {
|
||||
await api(`rooms/${id}/discord`, {});
|
||||
setShareMessage(
|
||||
"Party announcement queued. Anyone in the Discord channel can open the invite and join.",
|
||||
);
|
||||
await load();
|
||||
} catch (failure) {
|
||||
setShareMessage((failure as Error).message);
|
||||
} finally {
|
||||
setSharing(false);
|
||||
}
|
||||
}
|
||||
const activeGame =
|
||||
!!room?.you && ["loading", "playing", "results"].includes(room.status);
|
||||
if (activeGame && room)
|
||||
@@ -235,6 +253,60 @@ export function MultiplayerRoom({ id }: { id: string }) {
|
||||
<Copy size={16} /> {copied ? t("Copied!") : t("Copy link")}
|
||||
</button>
|
||||
</div>
|
||||
{owner && (room.discord?.available || room.discord?.state) && (
|
||||
<div className="discord-party-share">
|
||||
<p className="muted">
|
||||
{t(
|
||||
"Publishing shares this invite with everyone in the community Discord channel.",
|
||||
)}
|
||||
</p>
|
||||
{room.discord.state === null && (
|
||||
<button
|
||||
className="button"
|
||||
disabled={
|
||||
sharing ||
|
||||
busy ||
|
||||
room.playerCount >= room.playerLimit
|
||||
}
|
||||
onClick={() => void publishParty()}
|
||||
>
|
||||
<MessageCircle size={16} aria-hidden="true" />
|
||||
{sharing
|
||||
? t("Publishing…")
|
||||
: t("Publish party to Discord")}
|
||||
</button>
|
||||
)}
|
||||
{room.discord.state === "sent" && (
|
||||
<p role="status">{t("Party posted to Discord.")}</p>
|
||||
)}
|
||||
{["pending", "sending"].includes(
|
||||
room.discord.state ?? "",
|
||||
) && (
|
||||
<p role="status">
|
||||
{t(
|
||||
"Party announcement is waiting for Discord delivery.",
|
||||
)}
|
||||
</p>
|
||||
)}
|
||||
{room.discord.state === "failed" && (
|
||||
<p role="status">
|
||||
{t(
|
||||
"Discord delivery needs an administrator to check the bot setup and retry.",
|
||||
)}
|
||||
</p>
|
||||
)}
|
||||
{room.discord.state === "skipped" && (
|
||||
<p role="status">
|
||||
{t(
|
||||
"This party announcement expired or the lobby is no longer available.",
|
||||
)}
|
||||
</p>
|
||||
)}
|
||||
{shareMessage && !room.discord.state && (
|
||||
<p role="status">{t(shareMessage)}</p>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
<h2>
|
||||
{t("{count} / {limit} players", {
|
||||
count: room.playerCount,
|
||||
|
||||
Reference in New Issue
Block a user