Added Team System
This commit is contained in:
parent
10183ac56b
commit
d2ab24ed64
17
discord-bot/events/MessageCreate.js
Normal file
17
discord-bot/events/MessageCreate.js
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
const { Events } = require('discord.js');
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
name: Events.MessageCreate,
|
||||||
|
async execute({ log }, message) {
|
||||||
|
|
||||||
|
if (message.channelId === process.env.MINECRAFT_CHANNEL_ID && !message.author.bot) {
|
||||||
|
await fetch(process.env.WEB_HOST + '/api/minecraft/message/chattominecraft', {
|
||||||
|
method: 'POST',
|
||||||
|
body: JSON.stringify({
|
||||||
|
content: message.content,
|
||||||
|
discordId: message.author.id,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
@ -1,6 +1,6 @@
|
|||||||
const { EmbedBuilder } = require('discord.js');
|
const { EmbedBuilder } = require('discord.js');
|
||||||
|
|
||||||
const registerEvents = ({ createEmbed, client }) => {
|
const registerEvents = ({ client }) => {
|
||||||
|
|
||||||
client.player.on('trackStart', (queue, track) => {
|
client.player.on('trackStart', (queue, track) => {
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ const { Player } = require('discord-player');
|
|||||||
const fs = require('node:fs');
|
const fs = require('node:fs');
|
||||||
const path = require('node:path');
|
const path = require('node:path');
|
||||||
const dotenv = require('dotenv');
|
const dotenv = require('dotenv');
|
||||||
|
const express = require('express');
|
||||||
|
|
||||||
const createEmbed = require('./functions/createEmbed.js');
|
const createEmbed = require('./functions/createEmbed.js');
|
||||||
dotenv.config();
|
dotenv.config();
|
||||||
@ -15,11 +16,25 @@ const log = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Register client and music events
|
// Register client and music events
|
||||||
const client = new Client({ intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildVoiceStates, GatewayIntentBits.GuildMembers] });
|
const client = new Client({ intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildVoiceStates, GatewayIntentBits.GuildMembers, GatewayIntentBits.GuildMessages, GatewayIntentBits.MessageContent] });
|
||||||
client.player = new Player(client);
|
client.player = new Player(client);
|
||||||
|
|
||||||
require('./functions/player.js').registerEvents({ client, createEmbed });
|
require('./functions/player.js').registerEvents({ client, createEmbed });
|
||||||
|
|
||||||
|
|
||||||
|
// Express
|
||||||
|
const app = express();
|
||||||
|
app.use(express.json());
|
||||||
|
|
||||||
|
const messageRoute = require('./routes/Message');
|
||||||
|
|
||||||
|
app.use('/minecraft', messageRoute);
|
||||||
|
|
||||||
|
app.listen('4000', () => {
|
||||||
|
log.Info('Express app running');
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
// Command handling
|
// Command handling
|
||||||
client.commands = new Collection();
|
client.commands = new Collection();
|
||||||
|
|
||||||
@ -53,3 +68,5 @@ for (const file of eventFiles) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
client.login(process.env.DISCORD_TOKEN);
|
client.login(process.env.DISCORD_TOKEN);
|
||||||
|
|
||||||
|
module.exports.client = client;
|
||||||
|
1448
discord-bot/package-lock.json
generated
1448
discord-bot/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -17,6 +17,8 @@
|
|||||||
"discord.js": "^14.7.1",
|
"discord.js": "^14.7.1",
|
||||||
"distube": "^4.0.4",
|
"distube": "^4.0.4",
|
||||||
"dotenv": "^16.0.3",
|
"dotenv": "^16.0.3",
|
||||||
"eslint": "^8.29.0"
|
"eslint": "^8.29.0",
|
||||||
|
"express": "^4.18.2",
|
||||||
|
"ytdl-core": "^4.11.4"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
38
discord-bot/routes/Message.js
Normal file
38
discord-bot/routes/Message.js
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
const { WebhookClient, EmbedBuilder } = require('discord.js');
|
||||||
|
const express = require('express');
|
||||||
|
|
||||||
|
const router = express.Router();
|
||||||
|
const webhookClient = new WebhookClient({ url: process.env.MINECRAFT_WEBHOOK_URL });
|
||||||
|
|
||||||
|
router.post('/sendchatmessage', (req, res) => {
|
||||||
|
const { content, username, avatarURL } = req.body;
|
||||||
|
|
||||||
|
if (!username || !content || !avatarURL) return res.status(400).send({ error: 'Content, username and avatar_url are required' });
|
||||||
|
|
||||||
|
webhookClient.send({
|
||||||
|
content: content,
|
||||||
|
username: username,
|
||||||
|
avatarURL: avatarURL,
|
||||||
|
});
|
||||||
|
|
||||||
|
res.send({ data: 'Test data' });
|
||||||
|
});
|
||||||
|
|
||||||
|
router.post('/sendgamemessage', (req, res) => {
|
||||||
|
const { content, avatarURL } = req.body;
|
||||||
|
|
||||||
|
if (!content || !avatarURL) return res.status(400).send({ error: 'Content, username and avatar_url are required' });
|
||||||
|
|
||||||
|
const messageEmbed = new EmbedBuilder()
|
||||||
|
.setColor(process.env.EMBED_COLOR)
|
||||||
|
.setAuthor({ name: content, iconURL: avatarURL });
|
||||||
|
|
||||||
|
webhookClient.send({
|
||||||
|
embeds: [messageEmbed],
|
||||||
|
username: 'Server',
|
||||||
|
});
|
||||||
|
|
||||||
|
res.send({ data: 'Test data' });
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = router;
|
@ -24,7 +24,6 @@ loom {
|
|||||||
mods {
|
mods {
|
||||||
"polarcraft-mod" {
|
"polarcraft-mod" {
|
||||||
sourceSet sourceSets.main
|
sourceSet sourceSets.main
|
||||||
sourceSet sourceSets.client
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,10 +0,0 @@
|
|||||||
package com.xeovalyte.polarcraft;
|
|
||||||
|
|
||||||
import net.fabricmc.api.ClientModInitializer;
|
|
||||||
|
|
||||||
public class ExampleModClient implements ClientModInitializer {
|
|
||||||
@Override
|
|
||||||
public void onInitializeClient() {
|
|
||||||
// This entrypoint is suitable for setting up client-specific logic, such as rendering.
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
package com.xeovalyte.polarcraft.mixin.client;
|
|
||||||
|
|
||||||
import net.minecraft.client.MinecraftClient;
|
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
|
||||||
|
|
||||||
@Mixin(MinecraftClient.class)
|
|
||||||
public class ExampleClientMixin {
|
|
||||||
@Inject(at = @At("HEAD"), method = "run")
|
|
||||||
private void run(CallbackInfo info) {
|
|
||||||
// This code is injected into the start of MinecraftClient.run()V
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
{
|
|
||||||
"required": true,
|
|
||||||
"package": "com.xeovalyte.polarcraft.mixin.client",
|
|
||||||
"compatibilityLevel": "JAVA_17",
|
|
||||||
"client": [
|
|
||||||
"ExampleClientMixin"
|
|
||||||
],
|
|
||||||
"injectors": {
|
|
||||||
"defaultRequire": 1
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,33 +1,23 @@
|
|||||||
package com.xeovalyte.polarcraft;
|
package com.xeovalyte.polarcraft;
|
||||||
|
|
||||||
import net.fabricmc.api.ModInitializer;
|
import com.xeovalyte.polarcraft.util.messageFunctions;
|
||||||
|
import com.xeovalyte.polarcraft.util.verifyFunction;
|
||||||
|
|
||||||
|
import net.fabricmc.api.ModInitializer;
|
||||||
import org.apache.commons.io.FileUtils;
|
import org.apache.commons.io.FileUtils;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents;
|
import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents;
|
||||||
import net.fabricmc.loader.api.FabricLoader;
|
import net.fabricmc.loader.api.FabricLoader;
|
||||||
import net.minecraft.network.message.SignedMessage;
|
|
||||||
import net.minecraft.server.MinecraftServer;
|
|
||||||
import net.minecraft.server.network.ServerPlayerEntity;
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
import net.minecraft.text.Text;
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.net.HttpURLConnection;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
import com.google.gson.JsonObject;
|
|
||||||
import com.google.gson.JsonElement;
|
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.GsonBuilder;
|
import com.google.gson.GsonBuilder;
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
import net.fabricmc.fabric.api.message.v1.ServerMessageEvents;
|
import net.fabricmc.fabric.api.message.v1.ServerMessageEvents;
|
||||||
|
|
||||||
public class PolarcraftMod implements ModInitializer {
|
public class PolarcraftMod implements ModInitializer {
|
||||||
@ -39,8 +29,9 @@ public class PolarcraftMod implements ModInitializer {
|
|||||||
private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
|
private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
|
||||||
private static final File CONFIG_FILE = new File(FabricLoader.getInstance().getConfigDir().toFile(), "polarcraft.json");
|
private static final File CONFIG_FILE = new File(FabricLoader.getInstance().getConfigDir().toFile(), "polarcraft.json");
|
||||||
|
|
||||||
private String configWebhookUrl = "https://discordapp.com/api/webhooks/webhookid/webhooktoken";
|
public static String configChatMessageUrl = "https://example.com/api/minecraft/message/chattodiscord";
|
||||||
private String configVerifyUrl = "https://example.com/api/minecraft/verifyuuid";
|
public static String configGameMessageUrl = "https://example.com/api/minecraft/message/gametodiscord";
|
||||||
|
public static String configVerifyUrl = "https://example.com/api/minecraft/verifyuuid";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onInitialize() {
|
public void onInitialize() {
|
||||||
@ -51,15 +42,17 @@ public class PolarcraftMod implements ModInitializer {
|
|||||||
|
|
||||||
ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> {
|
ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> {
|
||||||
ServerPlayerEntity player = (ServerPlayerEntity) handler.player;
|
ServerPlayerEntity player = (ServerPlayerEntity) handler.player;
|
||||||
onPlayerJoin(player);
|
|
||||||
|
verifyFunction.onPlayerJoin(player);
|
||||||
|
});
|
||||||
|
|
||||||
|
ServerPlayConnectionEvents.DISCONNECT.register((handler, server) -> {
|
||||||
|
ServerPlayerEntity player = (ServerPlayerEntity) handler.player;
|
||||||
|
messageFunctions.sendGameMessage(player.getUuid(), player.getDisplayName().getString() + " left the game");
|
||||||
});
|
});
|
||||||
|
|
||||||
ServerMessageEvents.CHAT_MESSAGE.register((message, sender, params) -> {
|
ServerMessageEvents.CHAT_MESSAGE.register((message, sender, params) -> {
|
||||||
onChatMessage(message, sender);
|
messageFunctions.sendChatMessage(message, sender);
|
||||||
});
|
|
||||||
|
|
||||||
ServerMessageEvents.GAME_MESSAGE.register((server, message, overlay) -> {
|
|
||||||
onGameMessage(server, message);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,7 +64,8 @@ public class PolarcraftMod implements ModInitializer {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
MyModConfig config = GSON.fromJson(FileUtils.readFileToString(CONFIG_FILE, StandardCharsets.UTF_8), MyModConfig.class);
|
MyModConfig config = GSON.fromJson(FileUtils.readFileToString(CONFIG_FILE, StandardCharsets.UTF_8), MyModConfig.class);
|
||||||
configWebhookUrl = config.webhookUrl;
|
configChatMessageUrl = config.chatMessageUrl;
|
||||||
|
configGameMessageUrl = config.gameMessageUrl;
|
||||||
configVerifyUrl = config.verifyUrl;
|
configVerifyUrl = config.verifyUrl;
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
@ -80,120 +74,21 @@ public class PolarcraftMod implements ModInitializer {
|
|||||||
|
|
||||||
private void saveConfig() {
|
private void saveConfig() {
|
||||||
try {
|
try {
|
||||||
FileUtils.writeStringToFile(CONFIG_FILE, GSON.toJson(new MyModConfig(configWebhookUrl, configVerifyUrl)), StandardCharsets.UTF_8);
|
FileUtils.writeStringToFile(CONFIG_FILE, GSON.toJson(new MyModConfig(configChatMessageUrl, configGameMessageUrl,configVerifyUrl)), StandardCharsets.UTF_8);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class MyModConfig {
|
public static class MyModConfig {
|
||||||
public String webhookUrl;
|
public String chatMessageUrl;
|
||||||
|
public String gameMessageUrl;
|
||||||
public String verifyUrl;
|
public String verifyUrl;
|
||||||
|
|
||||||
public MyModConfig(String webhookUrl, String verifyUrl) {
|
public MyModConfig(String chatMessageUrl, String gameMessageUrl,String verifyUrl) {
|
||||||
this.webhookUrl = webhookUrl;
|
this.chatMessageUrl = chatMessageUrl;
|
||||||
|
this.gameMessageUrl = gameMessageUrl;
|
||||||
this.verifyUrl = verifyUrl;
|
this.verifyUrl = verifyUrl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onChatMessage( SignedMessage message, ServerPlayerEntity sender) {
|
|
||||||
try {
|
|
||||||
// Create a URL object for the server endpoint
|
|
||||||
URL url = new URL(configWebhookUrl);
|
|
||||||
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
|
||||||
|
|
||||||
connection.setRequestMethod("POST");
|
|
||||||
connection.setRequestProperty("Content-Type", "application/json");
|
|
||||||
connection.setDoOutput(true);
|
|
||||||
|
|
||||||
String requestBody = "{\"content\":\"" + sender.getName().getString() + " > "+ message.getSignedContent() + "\"}";
|
|
||||||
|
|
||||||
OutputStream outputStream = connection.getOutputStream();
|
|
||||||
outputStream.write(requestBody.getBytes());
|
|
||||||
outputStream.flush();
|
|
||||||
outputStream.close();
|
|
||||||
|
|
||||||
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
|
|
||||||
String line;
|
|
||||||
StringBuilder response = new StringBuilder();
|
|
||||||
while ((line = reader.readLine()) != null) {
|
|
||||||
response.append(line);
|
|
||||||
}
|
|
||||||
reader.close();
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void onGameMessage( MinecraftServer server, Text message) {
|
|
||||||
try {
|
|
||||||
// Create a URL object for the server endpoint
|
|
||||||
URL url = new URL(configWebhookUrl);
|
|
||||||
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
|
||||||
|
|
||||||
connection.setRequestMethod("POST");
|
|
||||||
connection.setRequestProperty("Content-Type", "application/json");
|
|
||||||
connection.setDoOutput(true);
|
|
||||||
|
|
||||||
String requestBody = "{\"content\":\"" + "**" + message.getString() + "**" + "\"}";
|
|
||||||
|
|
||||||
OutputStream outputStream = connection.getOutputStream();
|
|
||||||
outputStream.write(requestBody.getBytes());
|
|
||||||
outputStream.flush();
|
|
||||||
outputStream.close();
|
|
||||||
|
|
||||||
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
|
|
||||||
String line;
|
|
||||||
StringBuilder response = new StringBuilder();
|
|
||||||
while ((line = reader.readLine()) != null) {
|
|
||||||
response.append(line);
|
|
||||||
}
|
|
||||||
reader.close();
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void onPlayerJoin(ServerPlayerEntity player) {
|
|
||||||
UUID uuid = player.getUuid();
|
|
||||||
|
|
||||||
try {
|
|
||||||
URL url = new URL(configVerifyUrl);
|
|
||||||
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
|
||||||
|
|
||||||
connection.setRequestMethod("POST");
|
|
||||||
connection.setRequestProperty("Content-Type", "application/json");
|
|
||||||
connection.setDoOutput(true);
|
|
||||||
|
|
||||||
String requestBody = "{\"uuid\":\"" + uuid + "\"}";
|
|
||||||
|
|
||||||
OutputStream outputStream = connection.getOutputStream();
|
|
||||||
outputStream.write(requestBody.getBytes());
|
|
||||||
outputStream.flush();
|
|
||||||
outputStream.close();
|
|
||||||
|
|
||||||
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
|
|
||||||
String line;
|
|
||||||
StringBuilder response = new StringBuilder();
|
|
||||||
while ((line = reader.readLine()) != null) {
|
|
||||||
response.append(line);
|
|
||||||
}
|
|
||||||
reader.close();
|
|
||||||
|
|
||||||
Gson gson = new Gson();
|
|
||||||
JsonElement element = gson.fromJson(response.toString(), JsonElement.class);
|
|
||||||
JsonObject jsonResponse = element.getAsJsonObject();
|
|
||||||
|
|
||||||
boolean verified = jsonResponse.get("verified").getAsBoolean();
|
|
||||||
|
|
||||||
if (!verified) {
|
|
||||||
int code = jsonResponse.get("code").getAsInt();
|
|
||||||
|
|
||||||
player.networkHandler.disconnect(Text.literal("Whitelist yourself by using this code: " + code));
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
|
||||||
player.networkHandler.disconnect(Text.literal("There was an error while verifing your account"));
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -1,15 +0,0 @@
|
|||||||
package com.xeovalyte.polarcraft.mixin;
|
|
||||||
|
|
||||||
import net.minecraft.server.MinecraftServer;
|
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
|
||||||
|
|
||||||
@Mixin(MinecraftServer.class)
|
|
||||||
public class ExampleMixin {
|
|
||||||
@Inject(at = @At("HEAD"), method = "loadWorld")
|
|
||||||
private void init(CallbackInfo info) {
|
|
||||||
// This code is injected into the start of MinecraftServer.loadWorld()V
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,31 @@
|
|||||||
|
package com.xeovalyte.polarcraft.mixin;
|
||||||
|
|
||||||
|
import com.xeovalyte.polarcraft.util.messageFunctions;
|
||||||
|
import net.minecraft.advancement.Advancement;
|
||||||
|
import net.minecraft.advancement.PlayerAdvancementTracker;
|
||||||
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
@Mixin(PlayerAdvancementTracker.class)
|
||||||
|
public class MixinPlayerAdvancementTracker {
|
||||||
|
@Shadow
|
||||||
|
private ServerPlayerEntity owner;
|
||||||
|
|
||||||
|
@Inject(method = "grantCriterion",
|
||||||
|
at = @At(
|
||||||
|
target = "Lnet/minecraft/server/PlayerManager;broadcast(Lnet/minecraft/text/Text;Z)V",
|
||||||
|
value = "INVOKE"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
private void grantCriterion(Advancement advancement, String criterionName, CallbackInfoReturnable<Boolean> cir) {
|
||||||
|
// messageFunctions.sendGameMessage(owner.getUuid(), " has completed the challenge [" + Objects.requireNonNull(advancement.getDisplay()).getTitle().getString() + "]");
|
||||||
|
messageFunctions.sendGameMessage(owner.getUuid(), owner.getDisplayName().getString() + " has completed the advancement [" + Objects.requireNonNull(advancement.getDisplay()).getTitle().getString() + "]");
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
package com.xeovalyte.polarcraft.mixin;
|
||||||
|
|
||||||
|
import com.xeovalyte.polarcraft.util.messageFunctions;
|
||||||
|
import net.minecraft.entity.damage.DamageSource;
|
||||||
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
|
import net.minecraft.text.Text;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
|
||||||
|
|
||||||
|
@Mixin(ServerPlayerEntity.class)
|
||||||
|
public class MixinPlayerEntity {
|
||||||
|
@Inject(method = "onDeath",
|
||||||
|
at = @At(
|
||||||
|
target = "Lnet/minecraft/server/network/ServerPlayNetworkHandler;sendPacket(Lnet/minecraft/network/packet/Packet;Lnet/minecraft/network/PacketCallbacks;)V",
|
||||||
|
value = "INVOKE",
|
||||||
|
ordinal = 0),
|
||||||
|
locals = LocalCapture.CAPTURE_FAILSOFT
|
||||||
|
)
|
||||||
|
private void onDeath(DamageSource damageSource, CallbackInfo ci, boolean bl, Text text){
|
||||||
|
ServerPlayerEntity serverPlayerEntity = (ServerPlayerEntity) (Object) this;
|
||||||
|
|
||||||
|
messageFunctions.sendGameMessage(serverPlayerEntity.getUuid(), text.getString());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,74 @@
|
|||||||
|
package com.xeovalyte.polarcraft.util;
|
||||||
|
|
||||||
|
import com.xeovalyte.polarcraft.PolarcraftMod;
|
||||||
|
|
||||||
|
import net.minecraft.network.message.SignedMessage;
|
||||||
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class messageFunctions {
|
||||||
|
public static void sendGameMessage(UUID uuid, String message) {
|
||||||
|
try {
|
||||||
|
// Create a URL object for the server endpoint
|
||||||
|
URL url = new URL(PolarcraftMod.configGameMessageUrl);
|
||||||
|
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
||||||
|
|
||||||
|
connection.setRequestMethod("POST");
|
||||||
|
connection.setRequestProperty("Content-Type", "application/json");
|
||||||
|
connection.setDoOutput(true);
|
||||||
|
|
||||||
|
String requestBody = "{\"content\":\"" + message + "\", \"uuid\":\"" + uuid + "\"}";
|
||||||
|
|
||||||
|
OutputStream outputStream = connection.getOutputStream();
|
||||||
|
outputStream.write(requestBody.getBytes());
|
||||||
|
outputStream.flush();
|
||||||
|
outputStream.close();
|
||||||
|
|
||||||
|
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
|
||||||
|
String line;
|
||||||
|
StringBuilder response = new StringBuilder();
|
||||||
|
while ((line = reader.readLine()) != null) {
|
||||||
|
response.append(line);
|
||||||
|
}
|
||||||
|
reader.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void sendChatMessage( SignedMessage message, ServerPlayerEntity sender) {
|
||||||
|
try {
|
||||||
|
// Create a URL object for the server endpoint
|
||||||
|
URL url = new URL(PolarcraftMod.configChatMessageUrl);
|
||||||
|
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
||||||
|
|
||||||
|
connection.setRequestMethod("POST");
|
||||||
|
connection.setRequestProperty("Content-Type", "application/json");
|
||||||
|
connection.setDoOutput(true);
|
||||||
|
|
||||||
|
String requestBody = "{\"content\":\"" + message.getSignedContent() + "\", \"uuid\":\"" + sender.getUuid() + "\"}";
|
||||||
|
|
||||||
|
OutputStream outputStream = connection.getOutputStream();
|
||||||
|
outputStream.write(requestBody.getBytes());
|
||||||
|
outputStream.flush();
|
||||||
|
outputStream.close();
|
||||||
|
|
||||||
|
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
|
||||||
|
String line;
|
||||||
|
StringBuilder response = new StringBuilder();
|
||||||
|
while ((line = reader.readLine()) != null) {
|
||||||
|
response.append(line);
|
||||||
|
}
|
||||||
|
reader.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,66 @@
|
|||||||
|
package com.xeovalyte.polarcraft.util;
|
||||||
|
|
||||||
|
import com.xeovalyte.polarcraft.PolarcraftMod;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
|
||||||
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
|
import net.minecraft.text.Text;
|
||||||
|
|
||||||
|
public class verifyFunction {
|
||||||
|
public static void onPlayerJoin(ServerPlayerEntity player) {
|
||||||
|
UUID uuid = player.getUuid();
|
||||||
|
|
||||||
|
try {
|
||||||
|
URL url = new URL(PolarcraftMod.configVerifyUrl);
|
||||||
|
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
||||||
|
|
||||||
|
connection.setRequestMethod("POST");
|
||||||
|
connection.setRequestProperty("Content-Type", "application/json");
|
||||||
|
connection.setDoOutput(true);
|
||||||
|
|
||||||
|
String requestBody = "{\"uuid\":\"" + uuid + "\"}";
|
||||||
|
|
||||||
|
OutputStream outputStream = connection.getOutputStream();
|
||||||
|
outputStream.write(requestBody.getBytes());
|
||||||
|
outputStream.flush();
|
||||||
|
outputStream.close();
|
||||||
|
|
||||||
|
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
|
||||||
|
String line;
|
||||||
|
StringBuilder response = new StringBuilder();
|
||||||
|
while ((line = reader.readLine()) != null) {
|
||||||
|
response.append(line);
|
||||||
|
}
|
||||||
|
reader.close();
|
||||||
|
|
||||||
|
Gson gson = new Gson();
|
||||||
|
JsonElement element = gson.fromJson(response.toString(), JsonElement.class);
|
||||||
|
JsonObject jsonResponse = element.getAsJsonObject();
|
||||||
|
|
||||||
|
boolean verified = jsonResponse.get("verified").getAsBoolean();
|
||||||
|
|
||||||
|
if (!verified) {
|
||||||
|
int code = jsonResponse.get("code").getAsInt();
|
||||||
|
|
||||||
|
player.networkHandler.disconnect(Text.literal("Whitelist yourself by using this code: " + code));
|
||||||
|
} else {
|
||||||
|
messageFunctions.sendGameMessage(player.getUuid(), player.getDisplayName().getString() + " joined the game");
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
player.networkHandler.disconnect(Text.literal("There was an error while verifing your account"));
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -13,18 +13,14 @@
|
|||||||
},
|
},
|
||||||
"license": "CC0-1.0",
|
"license": "CC0-1.0",
|
||||||
"icon": "assets/polarcraft-mod/icon.png",
|
"icon": "assets/polarcraft-mod/icon.png",
|
||||||
"environment": "*",
|
"environment": "server",
|
||||||
"entrypoints": {
|
"entrypoints": {
|
||||||
"main": [
|
"main": [
|
||||||
"com.xeovalyte.polarcraft.PolarcraftMod"
|
"com.xeovalyte.polarcraft.PolarcraftMod"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"mixins": [
|
"mixins": [
|
||||||
"polarcraft-mod.mixins.json",
|
"polarcraft-mod.mixins.json"
|
||||||
{
|
|
||||||
"config": "polarcraft-mod.client.mixins.json",
|
|
||||||
"environment": "client"
|
|
||||||
}
|
|
||||||
],
|
],
|
||||||
"depends": {
|
"depends": {
|
||||||
"fabricloader": ">=0.14.19",
|
"fabricloader": ">=0.14.19",
|
||||||
|
@ -3,7 +3,8 @@
|
|||||||
"package": "com.xeovalyte.polarcraft.mixin",
|
"package": "com.xeovalyte.polarcraft.mixin",
|
||||||
"compatibilityLevel": "JAVA_17",
|
"compatibilityLevel": "JAVA_17",
|
||||||
"mixins": [
|
"mixins": [
|
||||||
"ExampleMixin"
|
"MixinPlayerAdvancementTracker",
|
||||||
|
"MixinPlayerEntity"
|
||||||
],
|
],
|
||||||
"injectors": {
|
"injectors": {
|
||||||
"defaultRequire": 1
|
"defaultRequire": 1
|
||||||
|
180
web/components/team/Default.vue
Normal file
180
web/components/team/Default.vue
Normal file
@ -0,0 +1,180 @@
|
|||||||
|
<template>
|
||||||
|
<Modal v-if="modalOpen" title="Invite team member" @close="modalOpen = false" @submit="modalOpen = false">
|
||||||
|
<div>
|
||||||
|
<h2 class="text-lg font-bold text-primary">Users</h2>
|
||||||
|
<div class="h-48 space-y-3 overflow-y-auto">
|
||||||
|
<div v-for="unaffiliatedUser in unaffilatedUsers" :key="unaffiliatedUser._id.toString()" class="flex items-center rounded bg-neutral-700 px-3 py-1 text-gray-200">
|
||||||
|
{{ unaffiliatedUser.username }}
|
||||||
|
<Button v-if="!unaffiliatedUser.teamInvites.includes(user.team.id)" class="ml-auto" @click="inviteUser(unaffiliatedUser)">Invite</Button>
|
||||||
|
<Button v-else class="ml-auto" type="danger" @click="cancelInvite(unaffiliatedUser)">Cancel Invite</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Modal>
|
||||||
|
<Modal v-if="editTeamModal.open" title="Edit team" @close="editTeamModal.open = false" @submit="editTeam">
|
||||||
|
<Input v-model:value="editTeamModal.name" background-class="bg-neutral-800" class="w-full max-w-sm">Naam / Prefix</Input>
|
||||||
|
<Colorpicker v-model:value="editTeamModal.color" input-background-class="bg-neutral-800" class="w-full max-w-sm" />
|
||||||
|
</Modal>
|
||||||
|
<div class="mx-auto my-10 max-w-2xl">
|
||||||
|
<h2 class="mb-2 text-xl font-bold text-primary">Team Information</h2>
|
||||||
|
<div class="rounded border-[1px] border-primary px-5 py-2 text-primary">
|
||||||
|
<table class="w-full table-auto">
|
||||||
|
<tbody class="divide-y divide-gray-700">
|
||||||
|
<tr>
|
||||||
|
<td class="py-3">Name</td>
|
||||||
|
<td class="font-bold">{{ team.name }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="py-3">Color</td>
|
||||||
|
<td class="font-bold">{{ team.color }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="py-3">ID</td>
|
||||||
|
<td class="font-bold">{{ team._id }}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div class="mb-10 mt-5 flex justify-center gap-x-3">
|
||||||
|
<Button type="danger" @click="leaveTeam">Leave Team</Button>
|
||||||
|
<Button @click="openTeamModal">Edit Team</Button>
|
||||||
|
</div>
|
||||||
|
<h2 class="mb-2 text-xl font-bold text-primary">Team Members</h2>
|
||||||
|
<div class="space-y-5 rounded border-[1px] border-primary p-5 text-primary">
|
||||||
|
<div v-for="teamMember in teamMembers" :key="teamMember._id" class="flex h-12 items-center rounded bg-neutral-800 px-5 font-bold text-gray-200">
|
||||||
|
{{ teamMember.username }}
|
||||||
|
<span v-if="teamMember.team.admin" class="ml-3 text-sm text-gray-400">Admin</span>
|
||||||
|
<div v-if="user.team.admin" class="ml-auto">
|
||||||
|
<Button v-if="!teamMember.team.admin && teamMember._id !== user._id" @click="promoteUser(teamMember)">Promote</Button>
|
||||||
|
<Button v-if="teamMember.team.admin && teamMember._id !== user._id" @click="demoteUser(teamMember)">Demote</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-if="user.team.admin" class="rounded border-2 border-dashed border-neutral-500 bg-neutral-800 p-3 text-center font-bold text-gray-200 hover:cursor-pointer hover:bg-neutral-700" @click="modalOpen = true">
|
||||||
|
Invite new member
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
const user = useState('user');
|
||||||
|
const { data: team } = await useFetch('/api/team');
|
||||||
|
const { data: teamMembers } = await useFetch('/api/team/members');
|
||||||
|
const { data: unaffilatedUsers } = await useFetch('/api/team/unaffiliated')
|
||||||
|
|
||||||
|
const modalOpen = ref(false)
|
||||||
|
|
||||||
|
const editTeamModal = ref({
|
||||||
|
open: false,
|
||||||
|
name: '',
|
||||||
|
color: '',
|
||||||
|
})
|
||||||
|
|
||||||
|
const openTeamModal = () => {
|
||||||
|
editTeamModal.value.name = team.value.name
|
||||||
|
editTeamModal.value.color = team.value.color
|
||||||
|
editTeamModal.value.open = true
|
||||||
|
}
|
||||||
|
|
||||||
|
const leaveTeam = async () => {
|
||||||
|
try {
|
||||||
|
await $fetch('/api/team/leave');
|
||||||
|
|
||||||
|
user.value.team = null;
|
||||||
|
|
||||||
|
useToast().success('Successfully left team')
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e);
|
||||||
|
useToast().error(e.statusMessage)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const editTeam = async () => {
|
||||||
|
try {
|
||||||
|
await $fetch('/api/team/edit', {
|
||||||
|
method: 'POST',
|
||||||
|
body: {
|
||||||
|
name: editTeamModal.value.name,
|
||||||
|
color: editTeamModal.value.color,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
team.value.name = editTeamModal.value.name
|
||||||
|
team.value.color = editTeamModal.value.color
|
||||||
|
|
||||||
|
useToast().success('Successfully modified team')
|
||||||
|
|
||||||
|
editTeamModal.value.open = false
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e);
|
||||||
|
useToast().error(e.statusMessage)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const inviteUser = async (usr) => {
|
||||||
|
try {
|
||||||
|
await $fetch('/api/team/invite', {
|
||||||
|
method: 'POST',
|
||||||
|
body: { id: usr._id }
|
||||||
|
});
|
||||||
|
|
||||||
|
usr.teamInvites.push(user.value.team.id);
|
||||||
|
|
||||||
|
useToast().success(`Successfully invited ${usr.username}`)
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e);
|
||||||
|
useToast().error(e.statusMessage)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const cancelInvite = async (usr) => {
|
||||||
|
try {
|
||||||
|
await $fetch('/api/team/cancelinvite', {
|
||||||
|
method: 'POST',
|
||||||
|
body: { id: usr._id }
|
||||||
|
});
|
||||||
|
|
||||||
|
usr.teamInvites = usr.teamInvites.filter(a => a !== user.value.team.id);
|
||||||
|
|
||||||
|
useToast().success('Successfully cancelled invited')
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e);
|
||||||
|
useToast().error(e.statusMessage)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const promoteUser = async (usr) => {
|
||||||
|
try {
|
||||||
|
await $fetch('/api/team/promote', {
|
||||||
|
method: 'POST',
|
||||||
|
body: { userId: usr._id }
|
||||||
|
});
|
||||||
|
|
||||||
|
usr.team.admin = true
|
||||||
|
|
||||||
|
console.log(usr)
|
||||||
|
console.log(teamMembers)
|
||||||
|
|
||||||
|
useToast().success('Successfully promted user')
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e);
|
||||||
|
useToast().error(e.statusMessage)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const demoteUser = async (usr) => {
|
||||||
|
try {
|
||||||
|
await $fetch('/api/team/demote', {
|
||||||
|
method: 'POST',
|
||||||
|
body: { userId: usr._id }
|
||||||
|
});
|
||||||
|
|
||||||
|
usr.team.admin = false
|
||||||
|
|
||||||
|
useToast().success('Successfully demoted user')
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e);
|
||||||
|
useToast().error(e.statusMessage)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
@ -4,28 +4,83 @@
|
|||||||
</p>
|
</p>
|
||||||
<div class="mb-5 flex w-full justify-center gap-10">
|
<div class="mb-5 flex w-full justify-center gap-10">
|
||||||
<span
|
<span
|
||||||
class="font-bold text-primary hover:cursor-pointer" :class="{ 'underline underline-offset-4': !createTeam }"
|
class="font-bold text-primary hover:cursor-pointer" :class="{ 'underline underline-offset-4': !createTeam.show }"
|
||||||
@click="createTeam = false"
|
@click="createTeam.show = false"
|
||||||
>
|
>
|
||||||
Team Invites
|
Team Invites
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
class="font-bold text-primary hover:cursor-pointer" :class="{ 'underline underline-offset-4': createTeam }"
|
class="font-bold text-primary hover:cursor-pointer" :class="{ 'underline underline-offset-4': createTeam.show }"
|
||||||
@click="createTeam = true"
|
@click="createTeam.show = true"
|
||||||
>
|
>
|
||||||
Create Team
|
Create Team
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="!createTeam" class="text-center text-gray-300">
|
<div v-if="!createTeam.show" class="text-center text-gray-300">
|
||||||
You don't have any team invites
|
<h2 v-if="!user.teamInvites.length">You don't have any team invites</h2>
|
||||||
|
<div v-else class="mx-auto flex max-w-lg flex-col">
|
||||||
|
<div v-for="team in filteredTeams" :key="team._id" class="flex items-center rounded bg-neutral-800 px-3 py-1 text-left" @click="acceptInvite(team)">
|
||||||
|
<span>
|
||||||
|
{{ team.name }}
|
||||||
|
</span>
|
||||||
|
<Button class="ml-auto">Accept</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-else class="flex w-full flex-col items-center gap-5">
|
<div v-else class="flex w-full flex-col items-center gap-5">
|
||||||
<Input class="w-full max-w-sm">Naam / Prefix</Input>
|
<Input v-model:value="createTeam.name" class="w-full max-w-sm">Naam / Prefix</Input>
|
||||||
<Colorpicker class="w-full max-w-sm" />
|
<Colorpicker v-model:value="createTeam.color" class="w-full max-w-sm" />
|
||||||
<Button>Create Team</Button>
|
<Button @click="handleCreateTeam">Create Team</Button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
const createTeam = ref(false)
|
const user = useState('user')
|
||||||
|
|
||||||
|
const teams = await $fetch('/api/team/all')
|
||||||
|
|
||||||
|
const filteredTeams = computed(() => {
|
||||||
|
return teams.filter(a => user.value.teamInvites.includes(a._id));
|
||||||
|
})
|
||||||
|
|
||||||
|
const createTeam = ref({
|
||||||
|
show: false,
|
||||||
|
name: '',
|
||||||
|
color: '',
|
||||||
|
})
|
||||||
|
|
||||||
|
const acceptInvite = async (team) => {
|
||||||
|
try {
|
||||||
|
const response = await $fetch('/api/team/acceptinvite', {
|
||||||
|
method: 'POST',
|
||||||
|
body: { teamId: team._id }
|
||||||
|
})
|
||||||
|
|
||||||
|
console.log(response)
|
||||||
|
|
||||||
|
user.value.team = { id: response._id, admin: false }
|
||||||
|
|
||||||
|
useToast().success('Successfully joined team')
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e);
|
||||||
|
useToast().error(e.statusMessage)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleCreateTeam = async () => {
|
||||||
|
try {
|
||||||
|
const response = await $fetch('/api/team/create', {
|
||||||
|
method: 'POST',
|
||||||
|
body: { teamName: createTeam.value.name, teamColor: createTeam.value.color }
|
||||||
|
})
|
||||||
|
|
||||||
|
user.value.team = { id: response.insertedId.toString(), admin: true }
|
||||||
|
|
||||||
|
useToast().success('Successfully created team')
|
||||||
|
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e);
|
||||||
|
useToast().error(e.statusMessage)
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="h-full bg-neutral-900">
|
<div class="h-full bg-neutral-900">
|
||||||
<div class="hidden h-full grid-cols-desktoplayout grid-rows-desktoplayout sm:grid">
|
<div v-if="user" class="hidden h-full grid-cols-desktoplayout grid-rows-desktoplayout sm:grid">
|
||||||
<LayoutNavbar class="col-span-2" />
|
<LayoutNavbar class="col-span-2" />
|
||||||
<LayoutSidebar v-if="user.minecraft.uuid" class="" />
|
<LayoutSidebar v-if="user.minecraft.uuid" class="" />
|
||||||
<div class="overflow-y-auto px-10 pt-5" :class="{ 'col-span-2': !user.minecraft.uuid }">
|
<div class="overflow-y-auto px-10 pt-5" :class="{ 'col-span-2': !user.minecraft.uuid }">
|
||||||
<NuxtPage />
|
<NuxtPage />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="h-full sm:hidden">
|
<div v-if="user" class="h-full sm:hidden">
|
||||||
<div class="overflow-y-auto p-2">
|
<div class="overflow-y-auto p-2">
|
||||||
<NuxtPage />
|
<NuxtPage />
|
||||||
</div>
|
</div>
|
||||||
|
4
web/package-lock.json
generated
4
web/package-lock.json
generated
@ -3160,7 +3160,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@xeovalyte/nuxt-xvui": {
|
"node_modules/@xeovalyte/nuxt-xvui": {
|
||||||
"resolved": "git+https://gitea.xeovalyte.dev/xeovalyte/nuxt-xvui.git#e5bb7302f0626b39aa7b3a73bd4109b03702a9c7",
|
"resolved": "git+https://gitea.xeovalyte.dev/xeovalyte/nuxt-xvui.git#53b253beae85b014c2556291aaa9f8f94fc765d5",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@nuxt/eslint-config": "^0.1.1",
|
"@nuxt/eslint-config": "^0.1.1",
|
||||||
@ -15838,7 +15838,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@xeovalyte/nuxt-xvui": {
|
"@xeovalyte/nuxt-xvui": {
|
||||||
"version": "git+https://gitea.xeovalyte.dev/xeovalyte/nuxt-xvui.git#e5bb7302f0626b39aa7b3a73bd4109b03702a9c7",
|
"version": "git+https://gitea.xeovalyte.dev/xeovalyte/nuxt-xvui.git#53b253beae85b014c2556291aaa9f8f94fc765d5",
|
||||||
"from": "@xeovalyte/nuxt-xvui@git+https://gitea.xeovalyte.dev/xeovalyte/nuxt-xvui.git",
|
"from": "@xeovalyte/nuxt-xvui@git+https://gitea.xeovalyte.dev/xeovalyte/nuxt-xvui.git",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@nuxt/eslint-config": "^0.1.1",
|
"@nuxt/eslint-config": "^0.1.1",
|
||||||
|
@ -3,6 +3,15 @@
|
|||||||
<h1 class="text-2xl font-bold text-primary">
|
<h1 class="text-2xl font-bold text-primary">
|
||||||
Team
|
Team
|
||||||
</h1>
|
</h1>
|
||||||
<TeamNone />
|
<TeamNone v-if="!user.team" />
|
||||||
|
<TeamDefault v-else />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
const user = useState('user')
|
||||||
|
|
||||||
|
definePageMeta({
|
||||||
|
middleware: ["auth"]
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
@ -37,7 +37,7 @@ export default defineEventHandler(async (event) => {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
await coll.updateOne({ 'discord.id': userResult.id }, { $set: doc, $setOnInsert: { minecraft: { uuid: null, username: null }, team: null } }, { upsert: true })
|
await coll.updateOne({ 'discord.id': userResult.id }, { $set: doc, $setOnInsert: { minecraft: { uuid: null, username: null }, teamInvites: [] } }, { upsert: true })
|
||||||
|
|
||||||
const token = createToken(tokenResponseData.access_token, tokenResponseData.refresh_token, tokenResponseData.expires_in, userResult.id )
|
const token = createToken(tokenResponseData.access_token, tokenResponseData.refresh_token, tokenResponseData.expires_in, userResult.id )
|
||||||
|
|
||||||
|
18
web/server/api/team/acceptinvite.js
Normal file
18
web/server/api/team/acceptinvite.js
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import { ObjectId } from 'mongodb'
|
||||||
|
|
||||||
|
export default defineEventHandler(async (event) => {
|
||||||
|
const { teamId } = await readBody(event);
|
||||||
|
|
||||||
|
const user = await getAuth(event)
|
||||||
|
|
||||||
|
const teamsColl = db.collection('teams')
|
||||||
|
const usersColl = db.collection('users')
|
||||||
|
|
||||||
|
const team = await teamsColl.findOneAndUpdate({ _id: new ObjectId(teamId) }, { $inc: { count: 1 } })
|
||||||
|
|
||||||
|
if (!team.value) return createError({ statusCode: 500, statusMessage: 'Could not find team'})
|
||||||
|
|
||||||
|
await usersColl.updateOne({ _id: new ObjectId(user._id) }, { $set: { 'team.id': teamId, 'team.admin': false }})
|
||||||
|
|
||||||
|
return team
|
||||||
|
});
|
8
web/server/api/team/all.js
Normal file
8
web/server/api/team/all.js
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
export default defineEventHandler(async () => {
|
||||||
|
const teamsColl = db.collection('teams')
|
||||||
|
|
||||||
|
const cursor = teamsColl.find();
|
||||||
|
const teams = await cursor.toArray()
|
||||||
|
|
||||||
|
return teams
|
||||||
|
});
|
16
web/server/api/team/cancelinvite.js
Normal file
16
web/server/api/team/cancelinvite.js
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import { ObjectId } from 'mongodb'
|
||||||
|
|
||||||
|
export default defineEventHandler(async (event) => {
|
||||||
|
const { id } = await readBody(event);
|
||||||
|
|
||||||
|
const user = await getAuth(event)
|
||||||
|
|
||||||
|
const teamsColl = db.collection('teams')
|
||||||
|
const usersColl = db.collection('users')
|
||||||
|
|
||||||
|
const team = await teamsColl.findOne({ _id: new ObjectId(user.team.id) })
|
||||||
|
|
||||||
|
usersColl.updateOne({ _id: new ObjectId(id) }, { $pull: { teamInvites: team._id.toString() } })
|
||||||
|
|
||||||
|
return team
|
||||||
|
});
|
21
web/server/api/team/create.post.js
Normal file
21
web/server/api/team/create.post.js
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
export default defineEventHandler(async (event) => {
|
||||||
|
const { teamName, teamColor } = await readBody(event);
|
||||||
|
|
||||||
|
if (!teamName || !teamColor) return createError({ statusCode: 400, statusMessage: 'teamName and teamColor are required' })
|
||||||
|
if (!isHexColor(teamColor)) return createError({ statusCode: 400, statusMessage: 'Team color is not a valid hex code' })
|
||||||
|
|
||||||
|
const user = await getAuth(event)
|
||||||
|
|
||||||
|
if (user.team) return createError({ statusCode: 400, statusMessage: 'User already is in a team' })
|
||||||
|
|
||||||
|
const teamsColl = db.collection('teams')
|
||||||
|
const usersColl = db.collection('users')
|
||||||
|
|
||||||
|
if (await teamsColl.findOne({ name: teamName })) return createError({ statusCode: 400, statusMessage: 'Team name already exists' })
|
||||||
|
|
||||||
|
const response = await teamsColl.insertOne({ name: teamName, color: teamColor, count: 1 })
|
||||||
|
|
||||||
|
await usersColl.findOneAndUpdate({ 'discord.id': user.discord.id }, { $set: { 'team.id': response.insertedId.toString(), 'team.admin': true } })
|
||||||
|
|
||||||
|
return response;
|
||||||
|
});
|
14
web/server/api/team/demote.js
Normal file
14
web/server/api/team/demote.js
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import { ObjectId } from 'mongodb'
|
||||||
|
|
||||||
|
export default defineEventHandler(async (event) => {
|
||||||
|
const { userId } = await readBody(event)
|
||||||
|
|
||||||
|
const user = await getAuth(event)
|
||||||
|
|
||||||
|
if (!user.team.admin) return createError({ statusCode: 403, statusMessage: 'Forbidden' })
|
||||||
|
|
||||||
|
const usersColl = db.collection('users')
|
||||||
|
await usersColl.findOneAndUpdate({ _id: new ObjectId(userId) }, { $set: { 'team.admin': false } });
|
||||||
|
|
||||||
|
return { status: 'Success' }
|
||||||
|
});
|
19
web/server/api/team/edit.js
Normal file
19
web/server/api/team/edit.js
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import { ObjectId } from 'mongodb'
|
||||||
|
|
||||||
|
export default defineEventHandler(async (event) => {
|
||||||
|
const { name, color } = await readBody(event);
|
||||||
|
|
||||||
|
if (!isHexColor(color)) return createError({ statusCode: 400, statusMessage: 'Team color is not a valid hex code' })
|
||||||
|
|
||||||
|
const user = await getAuth(event)
|
||||||
|
|
||||||
|
const teamsColl = db.collection('teams')
|
||||||
|
|
||||||
|
const team = await teamsColl.findOne({ _id: new ObjectId(user.team.id) });
|
||||||
|
|
||||||
|
if (team.name !== name && await teamsColl.findOne({ name: name })) return createError({ statusCode: 400, statusMessage: 'Team name already exists' })
|
||||||
|
|
||||||
|
await teamsColl.updateOne({ _id: new ObjectId(user.team.id) }, { $set: { name: name, color: color } })
|
||||||
|
|
||||||
|
return team
|
||||||
|
});
|
10
web/server/api/team/index.js
Normal file
10
web/server/api/team/index.js
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import { ObjectId } from 'mongodb'
|
||||||
|
|
||||||
|
export default defineEventHandler(async (event) => {
|
||||||
|
const user = await getAuth(event)
|
||||||
|
|
||||||
|
const teamsColl = db.collection('teams')
|
||||||
|
const team = await teamsColl.findOne({ _id: new ObjectId(user.team.id) })
|
||||||
|
|
||||||
|
return team
|
||||||
|
});
|
20
web/server/api/team/invite.js
Normal file
20
web/server/api/team/invite.js
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import { ObjectId } from 'mongodb'
|
||||||
|
|
||||||
|
export default defineEventHandler(async (event) => {
|
||||||
|
const { id } = await readBody(event);
|
||||||
|
|
||||||
|
const user = await getAuth(event)
|
||||||
|
|
||||||
|
const teamsColl = db.collection('teams')
|
||||||
|
const usersColl = db.collection('users')
|
||||||
|
|
||||||
|
const team = await teamsColl.findOne({ _id: new ObjectId(user.team.id) })
|
||||||
|
|
||||||
|
const invitedUser = await usersColl.findOne({ _id: new ObjectId(id)});
|
||||||
|
|
||||||
|
if (invitedUser.team) return createError({ statusCode: 400, statusMessage: 'User already is in a team' })
|
||||||
|
|
||||||
|
usersColl.updateOne({ _id: new ObjectId(id) }, { $push: { teamInvites: team._id.toString() } })
|
||||||
|
|
||||||
|
return team
|
||||||
|
});
|
16
web/server/api/team/leave.js
Normal file
16
web/server/api/team/leave.js
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import { ObjectId } from 'mongodb'
|
||||||
|
|
||||||
|
export default defineEventHandler(async (event) => {
|
||||||
|
const user = await getAuth(event)
|
||||||
|
|
||||||
|
const teamsColl = db.collection('teams')
|
||||||
|
const team = await teamsColl.findOneAndUpdate({ _id: new ObjectId(user.team.id) }, { $inc: { count: -1 }})
|
||||||
|
|
||||||
|
const usersColl = db.collection('users')
|
||||||
|
await usersColl.findOneAndUpdate({ _id: new ObjectId(user._id) }, { $unset: { team: "" } })
|
||||||
|
|
||||||
|
if (team.value.count <= 1) {
|
||||||
|
await teamsColl.deleteOne({ _id: new ObjectId(user.team.id )})
|
||||||
|
}
|
||||||
|
return team
|
||||||
|
});
|
17
web/server/api/team/members.js
Normal file
17
web/server/api/team/members.js
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
export default defineEventHandler(async (event) => {
|
||||||
|
const user = await getAuth(event)
|
||||||
|
|
||||||
|
const usersColl = db.collection('users')
|
||||||
|
const cursor = usersColl.find({ 'team.id': user.team.id })
|
||||||
|
|
||||||
|
if((await usersColl.countDocuments({ 'team.id': user.team.id })) === 0) {
|
||||||
|
return createError({ statusCode: 500, statusMessage: 'No users were found' })
|
||||||
|
}
|
||||||
|
|
||||||
|
const users = [];
|
||||||
|
for await (const doc of cursor) {
|
||||||
|
users.push(doc)
|
||||||
|
}
|
||||||
|
|
||||||
|
return users;
|
||||||
|
});
|
14
web/server/api/team/promote.js
Normal file
14
web/server/api/team/promote.js
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import { ObjectId } from 'mongodb'
|
||||||
|
|
||||||
|
export default defineEventHandler(async (event) => {
|
||||||
|
const { userId } = await readBody(event)
|
||||||
|
|
||||||
|
const user = await getAuth(event)
|
||||||
|
|
||||||
|
if (!user.team.admin) return createError({ statusCode: 403, statusMessage: 'Forbidden' })
|
||||||
|
|
||||||
|
const usersColl = db.collection('users')
|
||||||
|
await usersColl.findOneAndUpdate({ _id: new ObjectId(userId) },{ $set: { 'team.admin': true } });
|
||||||
|
|
||||||
|
return { status: 'Success' }
|
||||||
|
});
|
7
web/server/api/team/unaffiliated.js
Normal file
7
web/server/api/team/unaffiliated.js
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
export default defineEventHandler(async (event) => {
|
||||||
|
const usersColl = db.collection('users')
|
||||||
|
const cursor = usersColl.find({ team: { $exists: false } })
|
||||||
|
const unaffiliatedUsers = await cursor.toArray()
|
||||||
|
|
||||||
|
return unaffiliatedUsers
|
||||||
|
});
|
4
web/server/utils/check.js
Normal file
4
web/server/utils/check.js
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
export const isHexColor = (str) => {
|
||||||
|
const pattern = /^#([0-9A-F]{3}){1,2}$/i;
|
||||||
|
return pattern.test(str);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user