Skip to content

Commit

Permalink
feat(*): chat
Browse files Browse the repository at this point in the history
  • Loading branch information
tristancamejo committed Dec 26, 2022
1 parent 5d3b24f commit cfe7f54
Show file tree
Hide file tree
Showing 10 changed files with 223 additions and 5 deletions.
37 changes: 37 additions & 0 deletions clients/js/example.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ async function playerMenu(player) {
"Remove item",
"Teleport",
"Go back",
"Send message",
"Collect message",
],
},
]);
Expand Down Expand Up @@ -144,6 +146,41 @@ async function playerMenu(player) {

console.log("Done!");
break;
case "Send message":
const message = await inquirer.prompt([
{
type: "input",
name: "message",
message: "Message",
},
]);

await player.chat.send(message.message);

console.log("Done!");
break;
case "Collect message":
await player.chat.createCollector();

await new Promise((resolve) => {
const check = async () => {
const message = await player.chat.checkCollector();

if (message.status === "collected") {
console.log(`Message: ${message.result}`);
resolve();
} else {
console.log(`No message yet, ${message.status}...`);

await new Promise((resolve) => setTimeout(resolve, 1000));

check();
}
};

check();
});

case "Go back":
menu();
return;
Expand Down
2 changes: 1 addition & 1 deletion clients/js/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "elytra",
"version": "1.2.3",
"version": "1.3.0",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"author": "Tristan Camejo <contact@tristancamejo.com>",
Expand Down
5 changes: 1 addition & 4 deletions clients/js/src/Client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ export interface ClientResponse<T> {
export class Client {
constructor(private readonly options: ClientOptions) {
this.lang = new LangService({ lang: options.lang });
this.setup();
}

private _setup = false;
Expand Down Expand Up @@ -95,11 +94,9 @@ export class Client {
public async setup() {
if (this._setup) return;
this._setup = true;
await this.init();
}

private async init() {
const res = await this.health.ping();

this.minecraftVersion = res.headers.get("X-Minecraft-Version") || "Unknown";
this.bukkitVersion = res.headers.get("X-Bukkit-Version") || "Unknown";

Expand Down
4 changes: 4 additions & 0 deletions clients/js/src/structs/Player.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@ import type { PlayerPayload } from "../schemas/infer";
import { Base } from "./Base";
import { Inventory } from "./Inventory";
import { Location } from "./Location";
import { PlayerChatManager } from "./PlayerChatManager";

export class Player extends Base {
public constructor(client: Client, private data: PlayerPayload) {
super(client);
this.location = new Location(client, this.data.uuid, this.data.location);
this.inventory = new Inventory(client, this.data.uuid, this.data.inventory);
this.chat = new PlayerChatManager(client, this);
}

public get name(): string {
Expand Down Expand Up @@ -38,4 +40,6 @@ export class Player extends Base {
public location: Location;

public inventory: Inventory;

public chat: PlayerChatManager;
}
72 changes: 72 additions & 0 deletions clients/js/src/structs/PlayerChatManager.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { z } from "zod";
import type { Client } from "../Client";
import { Base } from "./Base";
import type { Player } from "./Player";

export class PlayerChatManager extends Base {
public constructor(client: Client, private player: Player) {
super(client);
}

/**
* Send a message to the player
* @param message Message to send
* @returns New player instance
*/
public async send(message: string) {
return this.client.players.constructPlayer(
(
await this.client.post(`/players/${this.player.uuid}/chat`, {
message,
})
).data
);
}

/**
* Creates a message collector on the player this manager is for.
* @returns Whether the collector was created or it already existed
*/
public async createCollector() {
const res = z
.object({
status: z.union([
z.literal("collector-exists"),
z.literal("collector-created"),
]),
})
.parse(
await (
await this.client.post(`/players/${this.player.uuid}/chat/collector`)
).data
);

switch (res.status) {
case "collector-exists":
return false;
case "collector-created":
return true;
}
}

/**
* Returns the collected message
* @returns Collected message
*/
public async checkCollector() {
return z
.union([
z.object({
status: z.union([z.literal("no-collector"), z.literal("waiting")]),
}),
z.object({
status: z.literal("collected"),
result: z.string(),
}),
])
.parse(
(await this.client.get(`/players/${this.player.uuid}/chat/collector`))
.data
);
}
}
1 change: 1 addition & 0 deletions clients/js/src/structs/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ export * from "./Inventory";
export * from "./ItemStack";
export * from "./Location";
export * from "./Player";
export * from "./PlayerChatManager";
6 changes: 6 additions & 0 deletions src/main/java/com/tristansmp/elytra/Elytra.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.tristansmp.elytra

import com.tristansmp.elytra.events.ChatListener
import com.tristansmp.elytra.lib.ConfigManager
import com.tristansmp.elytra.lib.MemoryStore
import com.tristansmp.elytra.plugins.configureHTTP
import com.tristansmp.elytra.plugins.configureRouting
import com.tristansmp.elytra.plugins.configureSerialization
Expand All @@ -16,6 +18,7 @@ class Elytra : JavaPlugin() {
}

lateinit var config: ConfigManager
lateinit var mstore: MemoryStore

override fun onEnable() {
Thread {
Expand All @@ -26,6 +29,9 @@ class Elytra : JavaPlugin() {
instance = this

config = ConfigManager()
mstore = MemoryStore()

server.pluginManager.registerEvents(ChatListener(), this)
}

override fun onDisable() {
Expand Down
33 changes: 33 additions & 0 deletions src/main/java/com/tristansmp/elytra/events/ChatListener.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.tristansmp.elytra.events

import com.tristansmp.elytra.Elytra
import io.papermc.paper.event.player.AsyncChatEvent
import net.kyori.adventure.text.TextComponent
import org.bukkit.event.EventHandler
import org.bukkit.event.Listener


class ChatListener : Listener {
@EventHandler
fun onPlayerChat(event: AsyncChatEvent) {
val needsCollection = Elytra.instance.mstore.get<Boolean>("cc:${event.player.uniqueId}:needs_collection")

if (needsCollection == null || !needsCollection) {
return
}

event.isCancelled = true

try {
val message = event.message() as TextComponent

Elytra.instance.mstore.set("cc:${event.player.uniqueId}:results", message.content())

event.player.sendMessage("§d[Elytra] §aMessage collected.")

Elytra.instance.mstore.remove("cc:${event.player.uniqueId}:needs_collection")
} catch (e: ClassCastException) {
event.player.sendMessage("§d[Elytra] §cMessage could not be collected.")
}
}
}
27 changes: 27 additions & 0 deletions src/main/java/com/tristansmp/elytra/lib/MemoryStore.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.tristansmp.elytra.lib

import java.util.*

class MemoryStore {
private val store = mutableMapOf<String, Any>()

fun <T> get(key: String): T? {
return store[key] as T?
}

fun <T : Any> set(key: String, value: T) {
store[key] = value
}

fun remove(key: String) {
store.remove(key)
}

init {
Timer().scheduleAtFixedRate(object : TimerTask() {
override fun run() {
store.clear()
}
}, 300000, 300000)
}
}
41 changes: 41 additions & 0 deletions src/main/java/com/tristansmp/elytra/routes/Player.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.tristansmp.elytra.routes

import com.tristansmp.elytra.Elytra
import com.tristansmp.elytra.lib.SerializeUtils
import com.tristansmp.elytra.lib.getName
import io.ktor.server.application.*
Expand All @@ -25,6 +26,10 @@ data class LocationPOST(
val pitch: Float
)

data class ChatPOST(
val message: String
)

fun Player.toJson(): Map<String, Any?> {
return mapOf(
"name" to name,
Expand Down Expand Up @@ -113,6 +118,42 @@ fun Route.Player() {
call.respond(player!!.toJson())
}

post("/{target}/chat") {
val req = call.receive<ChatPOST>()

player!!.sendMessage(req.message)

call.respond(player!!.toJson())
}

post("/{target}/chat/collector") {
val existing = Elytra.instance.mstore.get<Boolean>("cc:${player!!.uniqueId}:needs_collection")

if (existing != null && existing) {
call.respond(mapOf("status" to "collector-exists"))
return@post
}

Elytra.instance.mstore.set("cc:${player!!.uniqueId}:needs_collection", true)

call.respond(mapOf("status" to "collector-created"))
}

get("/{target}/chat/collector") {
val status = Elytra.instance.mstore.get<Boolean>("cc:${player!!.uniqueId}:needs_collection")
val result = Elytra.instance.mstore.get<String>("cc:${player!!.uniqueId}:results")

when {
result != null -> {
Elytra.instance.mstore.remove("cc:${player!!.uniqueId}:results")
call.respond(mapOf("status" to "collected", "result" to result))
}

status == null -> call.respond(mapOf("status" to "no-collector"))
status -> call.respond(mapOf("status" to "waiting"))
}
}

intercept(Plugins) {
val target = call.parameters["target"] ?: return@intercept proceed()

Expand Down

0 comments on commit cfe7f54

Please sign in to comment.