Spaces:
Sleeping
Sleeping
multiplayer
Browse files
patches/convex/world.ts
CHANGED
@@ -98,30 +98,37 @@ export const restartDeadWorlds = internalMutation({
|
|
98 |
export const userStatus = query({
|
99 |
args: {
|
100 |
worldId: v.id('worlds'),
|
|
|
|
|
101 |
},
|
102 |
handler: async (ctx, args) => {
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
|
|
109 |
},
|
110 |
});
|
111 |
|
112 |
export const joinWorld = mutation({
|
113 |
args: {
|
114 |
-
|
|
|
115 |
},
|
116 |
handler: async (ctx, args) => {
|
117 |
-
|
|
|
|
|
|
|
|
|
118 |
// if (!identity) {
|
119 |
// throw new ConvexError(`Not logged in`);
|
120 |
// }
|
121 |
// const name =
|
122 |
// identity.givenName || identity.nickname || (identity.email && identity.email.split('@')[0]);
|
123 |
-
|
124 |
-
|
125 |
// if (!name) {
|
126 |
// throw new ConvexError(`Missing name on ${JSON.stringify(identity)}`);
|
127 |
// }
|
@@ -154,7 +161,7 @@ export const joinWorld = mutation({
|
|
154 |
character: randomCharacter.character,
|
155 |
description: randomCharacter.identity,
|
156 |
// description: `${identity.givenName} is a human player`,
|
157 |
-
tokenIdentifier:
|
158 |
// By default everybody is a villager
|
159 |
type: 'villager',
|
160 |
});
|
@@ -164,19 +171,21 @@ export const joinWorld = mutation({
|
|
164 |
export const leaveWorld = mutation({
|
165 |
args: {
|
166 |
worldId: v.id('worlds'),
|
|
|
167 |
},
|
168 |
handler: async (ctx, args) => {
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
|
|
174 |
const world = await ctx.db.get(args.worldId);
|
175 |
if (!world) {
|
176 |
throw new Error(`Invalid world ID: ${args.worldId}`);
|
177 |
}
|
178 |
// const existingPlayer = world.players.find((p) => p.human === tokenIdentifier);
|
179 |
-
const existingPlayer = world.players.find((p) => p.human ===
|
180 |
if (!existingPlayer) {
|
181 |
return;
|
182 |
}
|
|
|
98 |
export const userStatus = query({
|
99 |
args: {
|
100 |
worldId: v.id('worlds'),
|
101 |
+
oauthToken: v.optional(v.string()),
|
102 |
+
|
103 |
},
|
104 |
handler: async (ctx, args) => {
|
105 |
+
const { worldId, oauthToken } = args;
|
106 |
+
|
107 |
+
if (!oauthToken) {
|
108 |
+
return null;
|
109 |
+
}
|
110 |
+
|
111 |
+
return oauthToken;
|
112 |
},
|
113 |
});
|
114 |
|
115 |
export const joinWorld = mutation({
|
116 |
args: {
|
117 |
+
oauthToken: v.optional(v.string()),
|
118 |
+
|
119 |
},
|
120 |
handler: async (ctx, args) => {
|
121 |
+
const { worldId, oauthToken } = args;
|
122 |
+
|
123 |
+
if (!oauthToken) {
|
124 |
+
throw new ConvexError(`Not logged in`);
|
125 |
+
}
|
126 |
// if (!identity) {
|
127 |
// throw new ConvexError(`Not logged in`);
|
128 |
// }
|
129 |
// const name =
|
130 |
// identity.givenName || identity.nickname || (identity.email && identity.email.split('@')[0]);
|
131 |
+
const name = oauthToken;
|
|
|
132 |
// if (!name) {
|
133 |
// throw new ConvexError(`Missing name on ${JSON.stringify(identity)}`);
|
134 |
// }
|
|
|
161 |
character: randomCharacter.character,
|
162 |
description: randomCharacter.identity,
|
163 |
// description: `${identity.givenName} is a human player`,
|
164 |
+
tokenIdentifier: oauthToken, // TODO: change for multiplayer to oauth
|
165 |
// By default everybody is a villager
|
166 |
type: 'villager',
|
167 |
});
|
|
|
171 |
export const leaveWorld = mutation({
|
172 |
args: {
|
173 |
worldId: v.id('worlds'),
|
174 |
+
oauthToken: v.optional(v.string()),
|
175 |
},
|
176 |
handler: async (ctx, args) => {
|
177 |
+
const { worldId, oauthToken } = args;
|
178 |
+
|
179 |
+
if (!oauthToken) {
|
180 |
+
throw new ConvexError(`Not logged in`);
|
181 |
+
}
|
182 |
+
|
183 |
const world = await ctx.db.get(args.worldId);
|
184 |
if (!world) {
|
185 |
throw new Error(`Invalid world ID: ${args.worldId}`);
|
186 |
}
|
187 |
// const existingPlayer = world.players.find((p) => p.human === tokenIdentifier);
|
188 |
+
const existingPlayer = world.players.find((p) => p.human === oauthToken);
|
189 |
if (!existingPlayer) {
|
190 |
return;
|
191 |
}
|
patches/src/App.tsx
CHANGED
@@ -13,6 +13,7 @@ import ReactModal from 'react-modal';
|
|
13 |
import MusicButton from './components/buttons/MusicButton.tsx';
|
14 |
import Button from './components/buttons/Button.tsx';
|
15 |
import InteractButton from './components/buttons/InteractButton.tsx';
|
|
|
16 |
import FreezeButton from './components/FreezeButton.tsx';
|
17 |
import { MAX_HUMAN_PLAYERS } from '../convex/constants.ts';
|
18 |
import PoweredByConvex from './components/PoweredByConvex.tsx';
|
@@ -82,6 +83,7 @@ export default function Home() {
|
|
82 |
<Button imgUrl={helpImg} onClick={() => setHelpModalOpen(true)}>
|
83 |
Help
|
84 |
</Button>
|
|
|
85 |
<div id="footer-buttons"/>
|
86 |
</div>
|
87 |
</footer>
|
|
|
13 |
import MusicButton from './components/buttons/MusicButton.tsx';
|
14 |
import Button from './components/buttons/Button.tsx';
|
15 |
import InteractButton from './components/buttons/InteractButton.tsx';
|
16 |
+
import OAuthLogin from './components//buttons/OAuthLogin.tsx';
|
17 |
import FreezeButton from './components/FreezeButton.tsx';
|
18 |
import { MAX_HUMAN_PLAYERS } from '../convex/constants.ts';
|
19 |
import PoweredByConvex from './components/PoweredByConvex.tsx';
|
|
|
83 |
<Button imgUrl={helpImg} onClick={() => setHelpModalOpen(true)}>
|
84 |
Help
|
85 |
</Button>
|
86 |
+
<OAuthLogin />
|
87 |
<div id="footer-buttons"/>
|
88 |
</div>
|
89 |
</footer>
|
patches/src/components/PixiGame.tsx
CHANGED
@@ -27,8 +27,9 @@ export const PixiGame = (props: {
|
|
27 |
// PIXI setup.
|
28 |
const pixiApp = useApp();
|
29 |
const viewportRef = useRef<Viewport | undefined>();
|
30 |
-
|
31 |
-
const
|
|
|
32 |
const humanPlayerId = [...props.game.world.players.values()].find(
|
33 |
(p) => p.human === humanTokenIdentifier,
|
34 |
)?.id;
|
|
|
27 |
// PIXI setup.
|
28 |
const pixiApp = useApp();
|
29 |
const viewportRef = useRef<Viewport | undefined>();
|
30 |
+
const oauth = JSON.parse(localStorage.getItem('oauth'));
|
31 |
+
const oauthToken = oauth ? oauth.userInfo.fullname : undefined;
|
32 |
+
const humanTokenIdentifier = useQuery(api.world.userStatus, { worldId: props.worldId, oauthToken }) ?? null;
|
33 |
const humanPlayerId = [...props.game.world.players.values()].find(
|
34 |
(p) => p.human === humanTokenIdentifier,
|
35 |
)?.id;
|
patches/src/components/PlayerDetails.tsx
CHANGED
@@ -25,7 +25,9 @@ export default function PlayerDetails({
|
|
25 |
setSelectedElement: SelectElement;
|
26 |
scrollViewRef: React.RefObject<HTMLDivElement>;
|
27 |
}) {
|
28 |
-
const
|
|
|
|
|
29 |
|
30 |
const players = [...game.world.players.values()];
|
31 |
const humanPlayer = players.find((p) => p.human === humanTokenIdentifier);
|
|
|
25 |
setSelectedElement: SelectElement;
|
26 |
scrollViewRef: React.RefObject<HTMLDivElement>;
|
27 |
}) {
|
28 |
+
const oauth = JSON.parse(localStorage.getItem('oauth'));
|
29 |
+
const oauthToken = oauth ? oauth.userInfo.fullname : undefined;
|
30 |
+
const humanTokenIdentifier = useQuery(api.world.userStatus, { worldId, oauthToken });
|
31 |
|
32 |
const players = [...game.world.players.values()];
|
33 |
const humanPlayer = players.find((p) => p.human === humanTokenIdentifier);
|
patches/src/components/buttons/InteractButton.tsx
CHANGED
@@ -15,7 +15,9 @@ export default function InteractButton() {
|
|
15 |
const worldStatus = useQuery(api.world.defaultWorldStatus);
|
16 |
const worldId = worldStatus?.worldId;
|
17 |
const game = useServerGame(worldId);
|
18 |
-
const
|
|
|
|
|
19 |
const userPlayerId =
|
20 |
game && [...game.world.players.values()].find((p) => p.human === humanTokenIdentifier)?.id;
|
21 |
const join = useMutation(api.world.joinWorld);
|
@@ -27,7 +29,7 @@ export default function InteractButton() {
|
|
27 |
async (worldId: Id<'worlds'>) => {
|
28 |
let inputId;
|
29 |
try {
|
30 |
-
inputId = await join({ worldId });
|
31 |
} catch (e: any) {
|
32 |
if (e instanceof ConvexError) {
|
33 |
toast.error(e.data);
|
@@ -41,7 +43,7 @@ export default function InteractButton() {
|
|
41 |
toast.error(e.message);
|
42 |
}
|
43 |
},
|
44 |
-
[convex],
|
45 |
);
|
46 |
|
47 |
const joinOrLeaveGame = () => {
|
@@ -54,7 +56,7 @@ export default function InteractButton() {
|
|
54 |
}
|
55 |
if (isPlaying) {
|
56 |
console.log(`Leaving game for player ${userPlayerId}`);
|
57 |
-
void leave({ worldId });
|
58 |
} else {
|
59 |
console.log(`Joining game`);
|
60 |
void joinInput(worldId);
|
|
|
15 |
const worldStatus = useQuery(api.world.defaultWorldStatus);
|
16 |
const worldId = worldStatus?.worldId;
|
17 |
const game = useServerGame(worldId);
|
18 |
+
const oauth = JSON.parse(localStorage.getItem('oauth'));
|
19 |
+
const oauthToken = oauth ? oauth.userInfo.fullname : undefined;
|
20 |
+
const humanTokenIdentifier = useQuery(api.world.userStatus, worldId ? { worldId, oauthToken } : 'skip');
|
21 |
const userPlayerId =
|
22 |
game && [...game.world.players.values()].find((p) => p.human === humanTokenIdentifier)?.id;
|
23 |
const join = useMutation(api.world.joinWorld);
|
|
|
29 |
async (worldId: Id<'worlds'>) => {
|
30 |
let inputId;
|
31 |
try {
|
32 |
+
inputId = await join({ worldId, oauthToken });
|
33 |
} catch (e: any) {
|
34 |
if (e instanceof ConvexError) {
|
35 |
toast.error(e.data);
|
|
|
43 |
toast.error(e.message);
|
44 |
}
|
45 |
},
|
46 |
+
[convex, join, oauthToken],
|
47 |
);
|
48 |
|
49 |
const joinOrLeaveGame = () => {
|
|
|
56 |
}
|
57 |
if (isPlaying) {
|
58 |
console.log(`Leaving game for player ${userPlayerId}`);
|
59 |
+
void leave({ worldId , oauthToken});
|
60 |
} else {
|
61 |
console.log(`Joining game`);
|
62 |
void joinInput(worldId);
|