Advanced features
Make it multiplayer
You may not have realized it, but you’ve just made a game that is almost completely ready to become massively multiplayer. MUD has handled all of the network code out-of-the-box and there is a naturally shared, accessible database via the blockchain.
By writing a simple query to find all players and render them in the client, we’re prepared for any number of players. We'll add this to GameBoard.tsx
.
packages/client/src/GameBoard.tsx
import { useComponentValue, useEntityQuery } from "@latticexyz/react";
import { GameMap } from "./GameMap";
import { useMUD } from "./MUDContext";
import { useKeyboardMovement } from "./useKeyboardMovement";
import { hexToArray } from "@latticexyz/utils";
import { TerrainType, terrainTypes } from "./terrainTypes";
import { singletonEntity } from "@latticexyz/store-sync/recs";
import { Entity, Has, getComponentValueStrict } from "@latticexyz/recs";
import { EncounterScreen } from "./EncounterScreen";
import { MonsterType, monsterTypes } from "./monsterTypes";
export const GameBoard = () => {
useKeyboardMovement();
const {
components: { Encounter, MapConfig, Monster, Player, Position },
network: { playerEntity },
systemCalls: { spawn },
} = useMUD();
const canSpawn = useComponentValue(Player, playerEntity)?.value !== true;
const players = useEntityQuery([Has(Player), Has(Position)]).map((entity) => {
const position = getComponentValueStrict(Position, entity);
return {
entity,
x: position.x,
y: position.y,
emoji: entity === playerEntity ? "🤠" : "🥸",
};
});
const mapConfig = useComponentValue(MapConfig, singletonEntity);
if (mapConfig == null) {
throw new Error("map config not set or not ready, only use this hook after loading state === LIVE");
}
const { width, height, terrain: terrainData } = mapConfig;
const terrain = Array.from(hexToArray(terrainData)).map((value, index) => {
const { emoji } = value in TerrainType ? terrainTypes[value as TerrainType] : { emoji: "" };
return {
x: index % width,
y: Math.floor(index / width),
emoji,
};
});
const encounter = useComponentValue(Encounter, playerEntity);
const monsterType = useComponentValue(Monster, encounter ? (encounter.monster as Entity) : undefined)?.value;
const monster = monsterType != null && monsterType in MonsterType ? monsterTypes[monsterType as MonsterType] : null;
return (
<GameMap
width={width}
height={height}
terrain={terrain}
onTileClick={canSpawn ? spawn : undefined}
players={players}
encounter={
encounter ? (
<EncounterScreen monsterName={monster?.name ?? "MissingNo"} monsterEmoji={monster?.emoji ?? "💱"} />
) : undefined
}
/>
);
};
You can run this command to update all the files to this point in the game's development.
git reset --hard origin/step-4
All you have to do now is deploy to testnet!
Deploy to a blockchain
You can deploy this game to a blockchain using mud deploy
.