Friend
Overview
Friend gives every player a friend list. Players send a request, the other player accepts or declines it, and accepted friends can see each other's online status and teleport to one another. Everything is available through /friend commands, through TypeWriter actions and facts, and through a menu you design yourself in the web panel.
A friendship is stored by player UUID, so it survives a name change. The list lives in a single Friend Artifact. When the MySQL bridge is installed with Redis enabled, requests, friendships and online presence are shared between all the servers of a network, and /friend tp can move a player to the server where their friend is.
The menu is a GUI menu: you build its layout in the web panel and mark some items as Friend buttons. The friend heads themselves are placed by the extension.
Features
- Friend requests — send, accept, decline and remove friends by command, action entry or menu click.
- Request switch — each player can turn incoming requests off with
/friend toggle. - Friend menu — one entry holds every screen (friends, requests, tabs) with player heads, pagination and an empty-slot filler.
- Teleport to a friend — on the same server, or through the proxy to the friend's server on a network.
- Online status — local players and, with Redis, players on other servers of the same group.
- Story hooks — a fact for "is this player a friend" and one for "how many friends are online".
- Placeholders — counts, lists, indexed names and the server of a friend, usable in any MiniMessage text.
- Admin tools — list, inspect and force-link or unlink anyone's friends with
/friend admin.
Installation
- Install the GUI extension, which draws the menu.
- Optional, for several servers: install the MySQL extension and enable Redis (or Valkey) in its configuration, with the same
redis.group-idon every server. See Cross-server behaviour. - Put the Friend JAR in
plugins/Typewriter/extensions/and restart the server. - Create a Friend Artifact entry on a static page and publish it. Without it nothing is saved.
The permissions friend.use and friend.tp are given to everyone by default, friend.admin to operators.
Getting started
Build a friend menu opened by /friend:
- In the TypeWriter web panel, open a static page and add a Friend Artifact. Keep
artifactIdasfriend_data. - Open a page and add a Friend Menu entry. The command
/friendopens the first Friend Menu found, so you normally need only one. - Set
inventoryTitle,inventoryRowsandguiType, then build the layout inlayoutPooland pointmainLayoutIdat the root layout. See the GUI guides for layouts and frames. - Place your decoration and buttons. On an item, choose a Friend value in
buttonType, for exampleFRIEND_STATUSfor a counter,FRIEND_SETTINGS_TOGGLE_REQUESTSfor the request switch orNAV_CLOSEto close the menu. - Declare the screens: add one entry to
viewsper screen, then list the ids that show friends infriendListViewIdsand the ids that show incoming requests inrequestListViewIds. - Set where the player heads appear with
contentX,contentY,contentColumnsandcontentRows. - Publish, then run
/friendin game.
To open the menu from a quest, an NPC or an item, link the Friend Menu entry in the triggers of another entry, or run it as an action.
Use the Is Friend fact with targetName set to a player name, then use the fact in a criteria (value 1 means friends). Use Online Friends Count for rewards that scale with an active friend list.
How it works
Each player's data is loaded when that player is online on the server and saved to the artifact in the background. Every change is also published on the social message bus, so the server holding the other player applies it too.
Menus
The Friend Menu entry is a GUI menu with three Friend-specific parts.
Player heads. On a screen declared in friendListViewIds, every friend is a player head, online friends first. Left click teleports to the friend, right click removes the friend. On a screen declared in requestListViewIds, left click accepts the request and right click declines it. Heads fill a grid starting at contentX and contentY of contentColumns by contentRows slots. Free cells show emptySlotItem.
Buttons. An item whose buttonType is one of the values below is replaced at render time:
buttonType | What the player sees or does |
|---|---|
FRIEND_STATUS | Online, offline and total friend counts. |
FRIEND_LIST | Total number of friends, or "no friends" when the list is empty. |
FRIEND_REQUESTS | Number of pending requests. A click opens the requests view when there is at least one. |
FRIEND_SETTINGS_TOGGLE_REQUESTS | Click to turn incoming requests on or off. |
FRIEND_ONLINE_HEADER, FRIEND_OFFLINE_HEADER | Decorative section headers. |
PAGE_NAV | Page arrow. Left click goes forward, right click goes back, the name shows the page counter. Hidden when one page is enough. |
NAV_BACK, NAV_CLOSE | Go back to the previous menu, close the menu. |
FRIEND_ADD, FRIEND_REMOVE, FRIEND_ACCEPT, FRIEND_DECLINE, FRIEND_TP, FRIEND_MSG, FRIEND_PLAYER_SLOT | Display items with a fixed name and lore, without an action of their own. |
The other values offered by the editor (NAV_PREV, NAV_NEXT, PENDING_REQUESTS, FRIEND_SLOT, REQUEST_ACCEPT, REQUEST_DECLINE) are left as you configured them.
Slot commands. An item can run commands starting with friend : friend open [view], friend page next|prev|<number>, friend tp <name>, friend remove <name>, friend accept <name>, friend decline <name>, friend toggle, friend add <name>. They run as the player who clicked, with no %player% needed.
The built-in menu texts (default title "Amis", button names and head lore) are in French. Override them with the item names and lore you set in the layout and with inventoryTitle. Chat messages sent by the commands are in English.
Cross-server behaviour
Friend works on a single server without any other plugin. On a network, install MySQL and enable Redis or Valkey, then give every server of the network the same redis.group-id and a different redis.server-name. Without a group-id the social message bus stays silent and each server only sees its own changes.
With the bridge connected:
- requests, new friendships, removals and the request switch are sent to the other servers;
- a friend counts as online when Redis knows which server they are on;
/friend tpon a friend who is on another server asks the proxy to connect you to that server (the proxy must understand thebtc:bridgechannel). You arrive on the server, not at the friend's position.
Artifacts follow the active storage: when mysql.enabled is true in the MySQL configuration, the Friend Artifact is stored in the shared database, so every server reads the same friend list.
Commands
All commands need friend.use. Aliases: /friends, /f, /amis. The bare command opens the first Friend Menu and prints nothing when none exists.
| Command | Description |
|---|---|
/friend | Open the friend menu. |
/friend add <player> | Send a friend request. |
/friend accept <player> | Accept a pending request. |
/friend decline <player> | Decline a pending request. |
/friend remove <player> | Remove a friend. |
/friend list | Print your friends in chat with their online status. |
/friend toggle | Turn incoming friend requests on or off. |
/friend tp <player> | Teleport to a friend (also requires friend.tp). |
/friend admin list <player> | List the friends of an online player (requires friend.admin). |
/friend admin requests <player> | List the pending requests of an online player. |
/friend admin add <player> <player> | Make two online players friends, with no request step. |
/friend admin remove <player> <friend> | Remove a friend from the list of an online player. |
Permissions
| Permission | Default | Grants |
|---|---|---|
friend.use | Everyone | Every /friend command. Menu clicks run the same actions without checking it. |
friend.tp | Everyone | /friend tp. The head click in the menu runs the teleport directly and does not check this permission. |
friend.admin | Operators | The /friend admin commands. |
Placeholders
These are MiniPlaceholders tags, written in MiniMessage text as <friend_count>. Booleans return 1 or 0.
| Placeholder | Returns |
|---|---|
<friend_count> | Number of friends of the player. |
<friend_online_count> | Number of friends online on this server. |
<friend_online_network_count> | Number of friends known to be online on any server of the group. |
<friend_requests_count> | Number of pending requests. |
<friend_requests_enabled> | 1 when incoming requests are allowed. |
<friend_list> | Friend names separated by a comma. |
<friend_online_list> | Names of the friends online on this server. |
<friend_name:index> | Friend name at that position, starting at 0. |
<friend_online_name:index> | Online friend name at that position, starting at 0. |
<friend_is_friend:name> | 1 when the named player is a friend. |
<friend_server:name> | Server where the named player is online, empty when unknown. |
Entries
8 entries, generated from the extension source.
Actions5
- Accept Friend RequestAccept a friend request
- Friend MenuFriend Menu
- Remove FriendRemove a friend
- Send Friend RequestSend a friend request
- Teleport to FriendTeleport to a friend
Facts2
- Is FriendCheck if player is Friend
- Online Friends CountNumber of online friends
Artifacts1
- Friend ArtifactFriend Data Artifact
Troubleshooting
Friends disappear after a restart. No Friend Artifact is published, so data only lives in memory. Add the artifact on a static page and publish.
/friend does nothing. The command opens the first Friend Menu entry and stays silent when there is none. Create and publish a Friend Menu. The subcommands such as /friend list work without a menu.
The request was sent but the other player never receives it. The recipient must be online on a server of the network when the request is sent. Requests to offline players are not kept, and the sender is still told the request was sent. On several servers, check that redis.group-id is set to the same value everywhere, otherwise requests do not cross servers.
The friend list is empty on a second server. Each server needs the same redis.group-id, a unique redis.server-name, and mysql.enabled must be true so the artifact is shared through the database. Check the logs of the MySQL extension for Redis connection errors.
The head grid is empty or shows only filler items. The current screen is not listed in friendListViewIds or requestListViewIds. When the menu declares views, only the ids listed there display heads. Without views, set view to friends or requests.
Teleporting to a friend does nothing on another server. The proxy must handle the btc:bridge channel and Redis presence must be working. Without a network connection, /friend tp only works if the friend is on the same server.