Compare commits

..

114 Commits

Author SHA1 Message Date
330c132e3b Removed alternate current
All checks were successful
Build and Publish / Build and Publish Discord Bot (push) Successful in 1m11s
Build and Publish / Build and Publish Minecraft Mod (push) Successful in 2m22s
2023-11-17 19:16:12 +01:00
492034865b removed world border
Some checks failed
Build and Publish / Build and Publish Discord Bot (push) Failing after 3s
Build and Publish / Build and Publish Minecraft Mod (push) Successful in 1m33s
2023-10-03 14:47:52 +02:00
f2be21ef89 refresh
Some checks failed
Build and Publish / Build and Publish Discord Bot (push) Failing after 3s
Build and Publish / Build and Publish Minecraft Mod (push) Successful in 1m49s
2023-10-03 14:46:23 +02:00
e08dc0ef17 removed yawp
Some checks failed
Build and Publish / Build and Publish Discord Bot (push) Failing after 3s
Build and Publish / Build and Publish Minecraft Mod (push) Successful in 1m47s
2023-10-03 14:45:51 +02:00
2762f6e29f removed anti logout
Some checks failed
Build and Publish / Build and Publish Discord Bot (push) Failing after 3s
Build and Publish / Build and Publish Minecraft Mod (push) Successful in 1m52s
2023-10-03 14:43:40 +02:00
1612334e00 refresh packwiz
Some checks failed
Build and Publish / Build and Publish Discord Bot (push) Failing after 3s
Build and Publish / Build and Publish Minecraft Mod (push) Successful in 2m0s
2023-10-03 14:14:26 +02:00
f3075be1cf removed plasmo voice
Some checks failed
Build and Publish / Build and Publish Discord Bot (push) Failing after 3s
Build and Publish / Build and Publish Minecraft Mod (push) Successful in 1m40s
2023-10-03 14:13:49 +02:00
83adf33910 removed holograms
Some checks failed
Build and Publish / Build and Publish Discord Bot (push) Failing after 3s
Build and Publish / Build and Publish Minecraft Mod (push) Successful in 1m49s
2023-10-03 14:11:07 +02:00
853bf3141f Updated to 1.20.2
Some checks failed
Build and Publish / Build and Publish Discord Bot (push) Failing after 27s
Build and Publish / Build and Publish Minecraft Mod (push) Successful in 2m6s
2023-10-03 14:07:50 +02:00
e99ca2f302 revert b84ae5e2c1
Some checks failed
Build and Publish / Build and Publish Discord Bot (push) Failing after 0s
Build and Publish / Build and Publish Minecraft Mod (push) Failing after 0s
revert Updated modpack to 1.20.2
2023-10-01 10:55:37 +02:00
9a8c0599ed revert 9467119249
Some checks failed
Build and Publish / Build and Publish Discord Bot (push) Failing after 0s
Build and Publish / Build and Publish Minecraft Mod (push) Failing after 0s
revert Removed hologram
2023-10-01 10:55:21 +02:00
9467119249 Removed hologram
Some checks failed
Build and Publish / Build and Publish Discord Bot (push) Failing after 0s
Build and Publish / Build and Publish Minecraft Mod (push) Failing after 0s
2023-10-01 10:47:17 +02:00
b84ae5e2c1 Updated modpack to 1.20.2
Some checks failed
Build and Publish / Build and Publish Discord Bot (push) Failing after 0s
Build and Publish / Build and Publish Minecraft Mod (push) Failing after 0s
2023-10-01 09:36:34 +02:00
7cb5b563d7 Added anticombatlog
All checks were successful
Build and Publish / Build and Publish Discord Bot (push) Successful in 49s
Build and Publish / Build and Publish Minecraft Mod (push) Successful in 2m41s
2023-09-05 16:25:26 +02:00
9e60fa8c37 Add world border fix
All checks were successful
Build and Publish / Build and Publish Discord Bot (push) Successful in 12s
Build and Publish / Build and Publish Minecraft Mod (push) Successful in 1m50s
2023-08-27 20:54:40 +02:00
5914242316 Added slime mod
All checks were successful
Build and Publish / Build and Publish Discord Bot (push) Successful in 46s
Build and Publish / Build and Publish Minecraft Mod (push) Successful in 1m59s
2023-08-22 16:58:14 +02:00
18446f1dea added link
All checks were successful
Build and Publish / Build and Publish Discord Bot (push) Successful in 26s
Build and Publish / Build and Publish Minecraft Mod (push) Successful in 1m42s
2023-08-20 16:38:38 +02:00
d81879cec2 Added modpack
All checks were successful
Build and Publish / Build and Publish Discord Bot (push) Successful in 12s
Build and Publish / Build and Publish Minecraft Mod (push) Successful in 1m45s
2023-08-20 12:09:52 +02:00
5dc8e46080 Added Modpack install instructions
All checks were successful
Build and Publish / Build and Publish Discord Bot (push) Successful in 24s
Build and Publish / Build and Publish Minecraft Mod (push) Successful in 1m36s
2023-08-17 11:43:22 +02:00
1aac53deb8 Fixed spelling mistake
All checks were successful
Build and Publish / Build and Publish Discord Bot (push) Successful in 26s
Build and Publish / Build and Publish Minecraft Mod (push) Successful in 1m41s
2023-08-17 10:54:14 +02:00
0a5d94fd8c Small space issues
All checks were successful
Build and Publish / Build and Publish Discord Bot (push) Successful in 24s
Build and Publish / Build and Publish Minecraft Mod (push) Successful in 1m44s
2023-08-17 10:26:24 +02:00
5f0de3f326 Added nuke command
All checks were successful
Build and Publish / Build and Publish Discord Bot (push) Successful in 28s
Build and Publish / Build and Publish Minecraft Mod (push) Successful in 2m17s
2023-08-17 10:23:42 +02:00
ff29cc1c53 Update discordbot/.gitignore
All checks were successful
Build and Publish / Build and Publish Discord Bot (push) Successful in 24s
Build and Publish / Build and Publish Minecraft Mod (push) Successful in 1m36s
2023-08-15 10:29:29 +02:00
ce3507db62 Delete discordbot/database.sqlite
Some checks reported warnings
Build and Publish / Build and Publish Minecraft Mod (push) Has been cancelled
Build and Publish / Build and Publish Discord Bot (push) Has been cancelled
2023-08-15 10:29:18 +02:00
0739ac9376 Added messages
All checks were successful
Build and Publish / Build and Publish Discord Bot (push) Successful in 50s
Build and Publish / Build and Publish Minecraft Mod (push) Successful in 2m5s
2023-08-15 10:21:10 +02:00
765ab7f8d1 shadowed dependency
All checks were successful
Build and Publish / Build and Publish Discord Bot (push) Successful in 12s
Build and Publish / Build and Publish Minecraft Mod (push) Successful in 1m54s
2023-08-12 12:12:57 +02:00
624af4f5fd Update .gitea/workflows/release.yaml
All checks were successful
Build and Publish / Build and Publish Discord Bot (push) Successful in 11s
Build and Publish / Build and Publish Minecraft Mod (push) Successful in 1m40s
2023-08-12 11:39:20 +02:00
25a1d92e52 Update .gitea/workflows/release.yaml
Some checks reported warnings
Build and Publish / Build and Publish Discord Bot (push) Successful in 11s
Build and Publish / Build and Publish Minecraft Mod (push) Has been cancelled
2023-08-12 11:39:10 +02:00
e523385e5c Update .gitea/workflows/release.yaml
All checks were successful
Build and Publish / Build and Publish Minecraft Mod (push) Successful in 1m44s
Build and Publish / Build and Publish Discord Bot (push) Successful in 10s
2023-08-12 11:35:14 +02:00
9e4a91dd46 fixed ephemeral mistake
Some checks reported warnings
Build and Publish / Build and Publish Discord Bot (push) Successful in 25s
Build and Publish / Build and Publish Minecraft Mod (push) Has been cancelled
2023-08-12 11:34:34 +02:00
d9ae8e729a Update .gitea/workflows/release-nighty.yaml
All checks were successful
Build and Publish / Build and Publish Discord Bot (push) Successful in 26s
Build and Publish / Build and Publish Minecraft Mod (push) Successful in 1m46s
2023-08-12 11:27:02 +02:00
664eafa4cc Update discordbot/Dockerfile
Some checks reported warnings
Build and Publish / Build and Publish Discord Bot (push) Successful in 35s
Build and Publish / Build and Publish Minecraft Mod (push) Has been cancelled
2023-08-12 11:26:33 +02:00
1f810ca533 Update discordbot/Dockerfile
All checks were successful
Build and Publish / Build and Publish Discord Bot (push) Successful in 34s
Build and Publish / Build and Publish Minecraft Mod (push) Successful in 1m46s
2023-08-12 11:22:39 +02:00
64776ad8cf Update discordbot/Dockerfile
Some checks reported warnings
Build and Publish / Build and Publish Minecraft Mod (push) Has been cancelled
Build and Publish / Build and Publish Discord Bot (push) Has been cancelled
2023-08-12 11:22:23 +02:00
e8c2d1495d Update discordbot/Dockerfile
All checks were successful
Build and Publish / Build and Publish Discord Bot (push) Successful in 31s
Build and Publish / Build and Publish Minecraft Mod (push) Successful in 1m46s
2023-08-12 11:15:18 +02:00
8c41ad39c3 Update discordbot/Dockerfile
Some checks failed
Build and Publish / Build and Publish Discord Bot (push) Failing after 23s
Build and Publish / Build and Publish Minecraft Mod (push) Successful in 1m38s
2023-08-12 11:07:40 +02:00
f3c0f7d728 Delete discordbot/database.sqlite
All checks were successful
Build and Publish / Build and Publish Discord Bot (push) Successful in 29s
Build and Publish / Build and Publish Minecraft Mod (push) Successful in 1m38s
2023-08-12 11:05:14 +02:00
217781b4f0 Update .gitea/workflows/release-nighty.yaml
All checks were successful
Build and Publish / Build and Publish Discord Bot (push) Successful in 22s
Build and Publish / Build and Publish Minecraft Mod (push) Successful in 1m28s
2023-08-11 12:42:45 +02:00
b67befd3eb Update .gitea/workflows/release-nighty.yaml
All checks were successful
Build and Publish / Build and Publish Discord Bot (push) Successful in 21s
Build and Publish / Build and Publish Minecraft Mod (push) Successful in 1m30s
2023-08-11 12:37:04 +02:00
d1111732f3 Update .gitea/workflows/release-nighty.yaml
All checks were successful
Build and Publish / Build and Publish Discord Bot (push) Successful in 21s
Build and Publish / Build and Publish Minecraft Mod (push) Successful in 1m31s
2023-08-11 12:32:53 +02:00
3df664614f Update .gitea/workflows/release-nighty.yaml
Some checks failed
Build and Publish / Build and Publish Discord Bot (push) Successful in 24s
Build and Publish / Build and Publish Minecraft Mod (push) Failing after 1m33s
2023-08-11 12:26:09 +02:00
faf823ec37 Update .gitea/workflows/release-nighty.yaml
Some checks failed
Build and Publish / Build and Publish Discord Bot (push) Successful in 21s
Build and Publish / Build and Publish Minecraft Mod (push) Failing after 1m31s
2023-08-11 12:23:37 +02:00
ef355ecd48 Update .gitea/workflows/release-nighty.yaml
All checks were successful
Build and Publish / Build and Publish Discord Bot (push) Successful in 21s
Build and Publish / Build and Publish Minecraft Mod (push) Successful in 1m32s
2023-08-11 12:20:57 +02:00
3968a0e0c8 Update .gitea/workflows/release-nighty.yaml
Some checks failed
Build and Publish / Build and Publish Discord Bot (push) Successful in 21s
Build and Publish / Build and Publish Minecraft Mod (push) Failing after 37s
2023-08-11 12:19:03 +02:00
550542ae50 Update .gitea/workflows/release-nighty.yaml
All checks were successful
Build and Publish / Build and Publish Discord Bot (push) Successful in 21s
Build and Publish / Build and Publish Minecraft Mod (push) Successful in 8s
2023-08-11 12:12:30 +02:00
4c1e01b3c4 Add .gitea/workflows/release-nighty.yaml
All checks were successful
Build and Publish / Build and Publish Discord Bot (push) Successful in 26s
2023-08-11 12:11:00 +02:00
3459e1f733 Update .gitea/workflows/release.yaml 2023-08-11 12:01:53 +02:00
7ad3b82fb4 Update .gitea/workflows/release.yaml
All checks were successful
Build and Publish / Build and Publish Discord Bot (push) Successful in 23s
2023-08-11 11:55:07 +02:00
492248f01b Update .gitea/workflows/release.yaml
Some checks failed
Build and Publish / Build and Publish Discord Bot (push) Failing after 21s
2023-08-11 11:53:45 +02:00
4ec70b3601 Update .gitea/workflows/release.yaml
All checks were successful
Build and Publish / Build and Publish Discord Bot (push) Successful in 35s
2023-08-11 11:51:11 +02:00
e40d9eb14a changed docker auth type
Some checks failed
Build and Publish / Build and Publish Discord Bot (push) Failing after 20s
2023-08-11 11:48:41 +02:00
60a50c3bfb modified ci
Some checks failed
Build and Publish / Build and Publish Discord Bot (push) Failing after 46s
2023-08-11 11:46:17 +02:00
2dcbced91e added ci
Some checks failed
Build and Publish / Build and Publish Discord Bot (push) Failing after 1m10s
2023-08-11 11:43:14 +02:00
981de3d2e5 added assets 2023-08-11 11:18:21 +02:00
eddf87df4d Added a bunch of functions 2023-08-11 11:15:45 +02:00
6f24616c81 Added alot of functions 2023-08-11 11:14:59 +02:00
0f54fbf07e Added minecraft to discord messages 2023-08-05 12:21:30 +02:00
1e72ecdf53 added username system 2023-08-05 11:16:18 +02:00
e5644462b9 Added whitelist function 2023-08-04 19:27:29 +02:00
1b89c4440b Added verifyminecraft function 2023-08-04 17:05:49 +02:00
cf968f198a Added database 2023-08-03 12:06:31 +02:00
b68cb0b219 added basic functions 2023-08-02 14:16:30 +02:00
0c1cc63b9b initialized discord bot 2023-08-02 13:26:48 +02:00
fbc9238e97 added eslint typescript 2023-06-28 14:19:07 +02:00
d52431ffb5 Initialized discord bot version 2
Some checks failed
Build and Deploy / Deploy Web (push) Failing after 1s
Build and Deploy / Deploy Discord Bot (push) Failing after 1s
2023-06-27 19:38:28 +02:00
f5d9aefc0f removed modpack 2023-06-26 15:16:57 +02:00
7678a44945 feat: Added logout function 2023-06-26 15:16:24 +02:00
bbd329a4cf feat: Added Map page
Some checks failed
Build and Deploy / Deploy Web (push) Failing after 1s
Build and Deploy / Deploy Discord Bot (push) Failing after 1s
2023-06-25 17:48:22 +02:00
5685dd5fb7 feat: Added meta data 2023-06-24 13:47:40 +02:00
fbcd0d1bb9 feat: Added team page
Some checks failed
Build and Deploy / Deploy Web (push) Failing after 1s
Build and Deploy / Deploy Discord Bot (push) Failing after 1s
2023-06-24 13:27:33 +02:00
0588dd1c45 feat: Added set default functions and refresh discord data
Some checks failed
Build and Deploy / Deploy Web (push) Failing after 1s
Build and Deploy / Deploy Discord Bot (push) Failing after 0s
2023-06-15 16:55:23 +02:00
c433e25fba feat: Added intial dashboard and minecraft connection
Some checks failed
Build and Deploy / Deploy Web (push) Failing after 1s
Build and Deploy / Deploy Discord Bot (push) Failing after 1s
2023-06-13 16:29:47 +02:00
c8a4507253 feat: Added dashboard welcome message
Some checks failed
Build and Deploy / Deploy Web (push) Failing after 1s
Build and Deploy / Deploy Discord Bot (push) Failing after 1s
2023-06-12 16:48:38 +02:00
7bf7c8c8dc feat: Added sidebar 2023-06-12 15:56:09 +02:00
df3ff5f1c3 feat: Added update team url
All checks were successful
Build and Deploy / Deploy Web (push) Successful in 1m3s
Build and Deploy / Deploy Discord Bot (push) Successful in 44s
2023-06-08 15:23:40 +02:00
fabc504e06 feat: Added get all teams
All checks were successful
Build and Deploy / Deploy Web (push) Successful in 1m3s
Build and Deploy / Deploy Discord Bot (push) Successful in 48s
2023-06-07 22:32:34 +02:00
ea405ba6d5 fix: removed dark mod 2023-06-07 22:29:57 +02:00
d1f08e3dfa feat: Added team joining 2023-06-07 22:29:18 +02:00
70b0b86a23 feat: Added team invite creation 2023-06-06 22:28:26 +02:00
f9c13e5ada feat: Added team leave
All checks were successful
Build and Deploy / Deploy Web (push) Successful in 1m3s
Build and Deploy / Deploy Discord Bot (push) Successful in 43s
2023-06-06 18:22:36 +02:00
034e203c1e fix: Auto add user to new team 2023-06-06 16:35:25 +02:00
9510e8a407 feat: Added team creation, closes #22
All checks were successful
Build and Deploy / Deploy Web (push) Successful in 1m1s
Build and Deploy / Deploy Discord Bot (push) Successful in 42s
2023-06-06 14:29:05 +02:00
e68097d813 feat: Added username configuration, closes #19 2023-06-06 14:01:19 +02:00
3c5e20e18e fix: Fixed type 2023-06-06 13:50:10 +02:00
e28d2278cb feat: Added applyUsername function 2023-06-06 13:49:27 +02:00
89027590ca feat: Added applyUsername function
All checks were successful
Build and Deploy / Deploy Web (push) Successful in 1m3s
Build and Deploy / Deploy Discord Bot (push) Successful in 41s
2023-06-06 13:48:24 +02:00
ea7a3e3a8f fix: Migrated from transactions to writes, closes #30
All checks were successful
Build and Deploy / Deploy Web (push) Successful in 1m2s
Build and Deploy / Deploy Discord Bot (push) Successful in 42s
2023-06-06 10:37:30 +02:00
3eb4453d71 feat: Added minecraft linking system, closes #29
All checks were successful
Build and Deploy / Deploy Web (push) Successful in 1m5s
Build and Deploy / Deploy Discord Bot (push) Successful in 44s
2023-06-05 22:41:48 +02:00
d74a51db7f feat: Added verify account route, closes #28
All checks were successful
Build and Deploy / Deploy Web (push) Successful in 1m2s
Build and Deploy / Deploy Discord Bot (push) Successful in 44s
2023-06-05 16:05:03 +02:00
11a59d39af fix: Fixed jwt imports 2023-06-05 14:55:35 +02:00
12e92b8106 feat: Added get user by id, closes #18
All checks were successful
Build and Deploy / Deploy Web (push) Successful in 1m2s
Build and Deploy / Deploy Discord Bot (push) Successful in 44s
2023-06-05 10:17:35 +02:00
b17771755d feat: Added get all users. closes #16
All checks were successful
Build and Deploy / Deploy Web (push) Successful in 1m2s
Build and Deploy / Deploy Discord Bot (push) Successful in 42s
2023-06-05 09:34:22 +02:00
a0ea5ec191 fix: Removed user post #17
All checks were successful
Build and Deploy / Deploy Web (push) Successful in 1m14s
Build and Deploy / Deploy Discord Bot (push) Successful in 45s
2023-06-05 09:17:18 +02:00
08a24cae07 feat: Added login page 2023-06-04 22:47:48 +02:00
f360dcec8c feat: Added authentication sstem with discord 2023-06-04 22:06:28 +02:00
b25699b50b feat: Added @nuxthq/ui module 2023-06-04 10:26:36 +02:00
795c221453 added web version 2
Some checks failed
Build and Deploy / Deploy Web (push) Has been cancelled
Build and Deploy / Deploy Discord Bot (push) Has been cancelled
2023-06-01 22:06:11 +02:00
8121b9b975 Lots of improvements and changes
Some checks failed
Build and Deploy / Deploy Web (push) Has been cancelled
Build and Deploy / Deploy Discord Bot (push) Has been cancelled
2023-05-27 12:02:33 +02:00
98d73ea593 removed file
All checks were successful
Build and Deploy / Deploy Web (push) Successful in 1m2s
Build and Deploy / Deploy Discord Bot (push) Successful in 11m16s
2023-05-12 15:06:13 +02:00
54dee8ce88 changed build context
All checks were successful
Build and Deploy / Deploy Web (push) Successful in 1m15s
Build and Deploy / Deploy Discord Bot (push) Successful in 44s
2023-05-12 14:42:48 +02:00
80f4972d29 added manual docker file
Some checks failed
Build and Deploy / Deploy Web (push) Failing after 53s
Build and Deploy / Deploy Discord Bot (push) Failing after 35s
2023-05-12 14:41:28 +02:00
fd276bdb94 added ci workflow
Some checks failed
Build and Deploy / Deploy Web (push) Failing after 52s
Build and Deploy / Deploy Discord Bot (push) Failing after 28s
2023-05-12 14:36:29 +02:00
0c7e6d8ee1 improved communication system 2023-05-12 14:24:28 +02:00
d066915ec7 improved team system 2023-05-11 19:46:59 +02:00
51705f8651 Improved team system 2023-05-11 19:46:18 +02:00
cde8e6c827 removed ticket command in favor of discord forms 2023-05-09 16:30:49 +02:00
759c4e2bd1 Translated from English to Dutch 2023-05-09 16:01:19 +02:00
c668ca7f37 Added username switching 2023-05-09 15:23:31 +02:00
d2ab24ed64 Added Team System 2023-05-09 13:57:01 +02:00
10183ac56b run eslint 2023-05-06 13:14:01 +02:00
8d358e694e build chat system 2023-05-06 13:09:46 +02:00
5aa8dce299 updates 2023-05-03 11:36:20 +02:00
12320b6a09 improvements 2023-04-30 15:28:10 +02:00
99c7ef381d added whitelist system 2023-04-28 16:56:36 +02:00
136 changed files with 3719 additions and 25759 deletions

View File

@@ -0,0 +1,55 @@
name: Build and Publish
on:
push:
branches:
- 'dev'
jobs:
Build and Publish Discord Bot:
runs-on: ubuntu-latest
container:
image: catthehacker/ubuntu:act-latest
steps:
- uses: actions/checkout@v3
- uses: docker/login-action@v2
with:
registry: gitea.xeovalyte.dev
username: ${{ gitea.actor }}
password: ${{ secrets.DOCKER_PASSWORD }}
- uses: docker/build-push-action@master
with:
context: ./discordbot
push: true
tags: gitea.xeovalyte.dev/xeovalyte/polarcraft:nightly
Build and Publish Minecraft Mod:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up JDK
uses: actions/setup-java@v1
with:
java-version: 17
- name: Grant execute permission for gradlew
working-directory: ./mod
run: chmod +x gradlew
- name: Build with Gradle
working-directory: ./mod
run: ./gradlew build
- name: Upload Artifacts
uses: actions/upload-artifact@v3
with:
name: polarcraft-mod.jar
path: |
mod/build/libs/*.jar
!mod/build/libs/*-sources.jar
!mod/build/libs/*-dev.jar

View File

@@ -0,0 +1,53 @@
name: Build and Publish
on:
push:
branches:
- 'main'
jobs:
Build and Publish Discord Bot:
runs-on: ubuntu-latest
container:
image: catthehacker/ubuntu:act-latest
steps:
- uses: actions/checkout@v3
- uses: docker/login-action@v2
with:
registry: gitea.xeovalyte.dev
username: ${{ gitea.actor }}
password: ${{ secrets.DOCKER_PASSWORD }}
- uses: docker/build-push-action@master
with:
context: ./discordbot
push: true
tags: gitea.xeovalyte.dev/xeovalyte/polarcraft:latest
Build and Publish Minecraft Mod:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up JDK
uses: actions/setup-java@v1
with:
java-version: 17
- name: Grant execute permission for gradlew
working-directory: ./mod
run: chmod +x gradlew
- name: Build with Gradle
working-directory: ./mod
run: ./gradlew build
- name: Upload Artifacts
uses: actions/upload-artifact@v3
with:
name: polarcraft-mod.jar
path: |
mod/build/libs/*.jar
!mod/build/libs/*-sources.jar
!mod/build/libs/*-dev.jar

BIN
assets/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 663 KiB

BIN
assets/logo-zoomed-dev.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 601 KiB

BIN
assets/logo-zoomed.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 899 KiB

BIN
assets/logo-zoomed.xcf Normal file

Binary file not shown.

BIN
assets/logo.blend Normal file

Binary file not shown.

BIN
assets/logo.blend1 Normal file

Binary file not shown.

BIN
assets/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 984 KiB

BIN
assets/server-icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

View File

@@ -1,173 +0,0 @@
const { SlashCommandBuilder } = require('discord.js');
const { QueryType } = require('discord-player');
module.exports = {
data: new SlashCommandBuilder()
.setName('music')
.setDescription('Play and configure music')
.addSubcommand(subcommand => subcommand
.setName('play')
.setDescription('Play music')
.addStringOption(option => option
.setName('link-or-query')
.setDescription('The song or link you want to play')
.setRequired(true)))
.addSubcommand(subcommand => subcommand
.setName('skip')
.setDescription('Skip current song'))
.addSubcommand(subcommand => subcommand
.setName('stop')
.setDescription('Stop current queue'))
.addSubcommand(subcommand => subcommand
.setName('pause')
.setDescription('Pause the current song'))
.addSubcommand(subcommand => subcommand
.setName('shuffle')
.setDescription('Shuffle the queue'))
.addSubcommand(subcommand => subcommand
.setName('resume')
.setDescription('Resume the current song'))
.addSubcommand(subcommand => subcommand
.setName('filter')
.setDescription('Apply a filter')
.addStringOption(option => option
.setName('type')
.setDescription('Type of filter')
.setRequired(true)
.addChoices(
{ name: 'Bassboost', value: 'bassboost_low' },
{ name: 'Nightcore', value: 'nightcore' },
)))
.addSubcommand(subcommand => subcommand
.setName('volume')
.setDescription('Set volume')
.addNumberOption(option => option
.setName('percentage')
.setDescription('The percentage of the volume between 1 and 100')
.setRequired(true))),
async execute({ interaction, createEmbed, client }) {
if (!interaction.member.voice.channelId) return await interaction.reply({ embeds: [createEmbed.basic('You are not in a voice channel!')], ephemeral: true });
if (interaction.guild.members.me.voice.channelId && interaction.member.voice.channelId !== interaction.guild.members.me.voice.channelId) {
return await interaction.reply({ embeds: [createEmbed.basic('You are not in my voice channel!')], ephemeral: true });
}
if (interaction.options.getSubcommand() === 'play') {
const query = interaction.options.getString('link-or-query');
const queue = client.player.createQueue(interaction.guild, {
ytdlOptions: {
filter: 'audioonly',
highWaterMark: 1 << 30,
dlChunkSize: 0,
},
metadata: {
channel: interaction.channel,
},
});
// verify vc connection
try {
if (!queue.connection) await queue.connect(interaction.member.voice.channel);
} catch {
queue.destroy();
return await interaction.reply({ embeds: [createEmbed.basic('Could not join your voice channel!')], ephemeral: true });
}
await interaction.reply({ embeds: [createEmbed.basic('Searching...')], ephemeral: true });
const searchResult = await client.player.search(query, {
requestedBy: interaction.user,
searchEngine: QueryType.AUTO,
});
if (!searchResult || !searchResult.tracks[0]) return await interaction.editReply({ embeds: [createEmbed.basic(`Track or playlist **${query}** not found!`)], ephemeral: true });
searchResult.playlist ? queue.addTracks(searchResult.tracks) : queue.addTrack(searchResult.tracks[0]);
if (!queue.playing) await queue.play();
if (!searchResult.playlist) await interaction.editReply({ embeds: [createEmbed.basic(`Adding track **${searchResult.tracks[0].title}**`)], ephemeral: false });
else await interaction.editReply({ embeds: [createEmbed.basic(`Adding **${searchResult.playlist.tracks.length}** tracks from playlist **${searchResult.playlist.title}**`)], ephemeral: false });
} else if (interaction.options.getSubcommand() === 'skip') {
const queue = client.player.getQueue(interaction.guild);
if (!queue || !queue.playing) return await interaction.reply({ embeds: [createEmbed.basic('No music is being played')] });
const currentTrack = queue.nowPlaying();
const success = queue.skip();
await interaction.reply({ embeds: [createEmbed.basic(success ? `Skipped **${currentTrack.title}**` : 'Something went wrong')] });
} else if (interaction.options.getSubcommand() === 'volume') {
const vol = interaction.options.getNumber('percentage');
const queue = client.player.getQueue(interaction.guild);
if (!queue || !queue.playing) return await interaction.reply({ embeds: [createEmbed.basic('No music is being played')] });
if (vol < 1 || vol > 100) return interaction.reply({ embeds: [createEmbed.basic('Volume must be between 1 and 100')] });
const success = queue.setVolume(vol);
await interaction.reply({ embeds: [createEmbed.basic(success ? `Volume set to **${vol}%**` : 'Something went wrong')] });
} else if (interaction.options.getSubcommand() === 'stop') {
const queue = client.player.getQueue(interaction.guild);
if (!queue || !queue.playing) return await interaction.reply({ embeds: [createEmbed.basic('No music is being played')] });
queue.destroy();
await interaction.reply({ embeds: [createEmbed.basic('Stopped the player')] });
} else if (interaction.options.getSubcommand() === 'pause') {
const queue = client.player.getQueue(interaction.guild);
if (!queue || !queue.playing) return await interaction.reply({ embeds: [createEmbed.basic('No music is being played')] });
queue.setPaused(true);
await interaction.reply({ embeds: [createEmbed.basic('Paused the player')] });
} else if (interaction.options.getSubcommand() === 'resume') {
const queue = client.player.getQueue(interaction.guild);
if (!queue || !queue.playing) return await interaction.reply({ embeds: [createEmbed.basic('No music is being played')] });
queue.setPaused(false);
await interaction.reply({ embeds: [createEmbed.basic('Resumed the player')] });
} else if (interaction.options.getSubcommand() === 'filter') {
const filter = interaction.options.getString('type');
const queue = client.player.getQueue(interaction.guild);
if (!queue || !queue.playing) return await interaction.reply({ embeds: [createEmbed.basic('No music is being played')] });
if (filter === 'bassboost_low') {
await queue.setFilters({
bassboost_low: !queue.getFiltersEnabled().includes('bassboost_low'),
normalizer2: !queue.getFiltersEnabled().includes('bassboost_low'),
});
}
if (filter === 'nightcore') {
await queue.setFilters({
nightcore: !queue.getFiltersEnabled().includes('nightcore'),
});
}
await interaction.reply({ embeds: [createEmbed.basic(queue.getFiltersEnabled().includes(filter) ? `Applied **${filter}** filter` : `Removed **${filter}** filter`)] });
} else if (interaction.options.getSubcommand() === 'shuffle') {
const queue = client.player.getQueue(interaction.guild);
if (!queue || !queue.playing) return await interaction.reply({ embeds: [createEmbed.basic('No music is being played')] });
const success = queue.shuffle();
await interaction.reply({ embeds: [createEmbed.basic(success ? 'The queue has been shuffled' : 'Something went wrong')] });
}
},
};

View File

@@ -1,12 +0,0 @@
const { SlashCommandBuilder } = require('discord.js');
module.exports = {
data: new SlashCommandBuilder()
.setName('ping')
.setDescription('Replies with Pong!'),
async execute({ interaction, createEmbed, client }) {
const reply = await interaction.reply({ embeds: [createEmbed.basic(`Websocket heartbeat: **${client.ws.ping}ms**\n Roundtrip latency: **Pinging...**`)], fetchReply: true, ephemeral: true });
interaction.editReply({ embeds: [createEmbed.basic(`Websocket heartbeat: **${client.ws.ping}ms**\n Roundtrip latency: **${reply.createdTimestamp - interaction.createdTimestamp}ms**`)], emphemeral: true });
},
};

View File

@@ -1,121 +0,0 @@
const { SlashCommandBuilder, PermissionsBitField, ChannelType, ButtonStyle, ButtonBuilder, ActionRowBuilder } = require('discord.js');
module.exports = {
data: new SlashCommandBuilder()
.setName('ticket')
.setDescription('Create a ticket!')
.addStringOption(option => option
.setName('category')
.setDescription('The category of the ticket')
.setRequired(true)
.addChoices(
{ name: 'Technical Problem', value: 'tech-problem' },
{ name: 'Griefing or Harm', value: 'grief-or-harm' },
{ name: 'Suggestion', value: 'suggestion' },
{ name: 'Other', value: 'other' },
)),
async execute({ interaction, createEmbed }) {
await interaction.reply({ embeds: [createEmbed.basic('Creating ticket channel...')], fetchReply: true, ephemeral: true });
const category = interaction.options.getString('category');
let ticketChannel;
if (category === 'grief-or-harm') {
ticketChannel = await interaction.member.guild.channels.create({
name: `ticket-${interaction.user.username}`,
type: ChannelType.GuildText,
parent: process.env.TICKET_CATEGORY_ID,
permissionOverwrites: [
{
id: interaction.guild.id,
deny: [PermissionsBitField.Flags.ViewChannel],
},
{
id: process.env.MODERATOR_ROLE_ID,
allow: [PermissionsBitField.Flags.ViewChannel],
},
{
id: interaction.user.id,
allow: [PermissionsBitField.Flags.ViewChannel],
},
],
});
} else if (category === 'tech-problem') {
ticketChannel = await interaction.member.guild.channels.create({
name: `ticket-${interaction.user.username}`,
type: ChannelType.GuildText,
parent: process.env.TICKET_CATEGORY_ID,
permissionOverwrites: [
{
id: interaction.guild.id,
deny: [PermissionsBitField.Flags.ViewChannel],
},
{
id: process.env.CONTRIBUTER_ROLE_ID,
allow: [PermissionsBitField.Flags.ViewChannel],
},
{
id: interaction.user.id,
allow: [PermissionsBitField.Flags.ViewChannel],
},
],
});
} else {
ticketChannel = await interaction.member.guild.channels.create({
name: `ticket-${interaction.user.username}`,
type: ChannelType.GuildText,
parent: process.env.TICKET_CATEGORY_ID,
permissionOverwrites: [
{
id: interaction.guild.id,
deny: [PermissionsBitField.Flags.ViewChannel],
},
{
id: interaction.user.id,
allow: [PermissionsBitField.Flags.ViewChannel],
},
],
});
}
const closeRow = new ActionRowBuilder()
.addComponents(
new ButtonBuilder()
.setCustomId('close')
.setLabel('Close Ticket')
.setStyle(ButtonStyle.Danger),
);
const cancelRow = new ActionRowBuilder()
.addComponents(
new ButtonBuilder()
.setCustomId('cancel')
.setLabel('Cancel')
.setStyle(ButtonStyle.Danger),
);
const ticketMessage = await ticketChannel.send({ embeds: [createEmbed.basic(`${interaction.user} created a ticket with the category **${category}**`)], components: [closeRow] });
const collector = ticketMessage.createMessageComponentCollector();
let ticketCancelMessage;
let timeout;
collector.on('collect', async i => {
if (i.customId === 'close') {
ticketCancelMessage = await ticketChannel.send({ embeds: [createEmbed.basic('Closing ticket in 10 seconds...')] });
await ticketMessage.createMessageComponentCollector();
await i.update({ components: [cancelRow] });
timeout = setTimeout(() => ticketChannel.delete(), 10000);
} else {
clearTimeout(timeout);
await ticketCancelMessage.edit({ embeds: [createEmbed.basic('Ticket closing has been stopped')] });
await i.update({ components: [closeRow] });
}
});
interaction.editReply({ embeds: [createEmbed.basic(`${ticketChannel} has been created`)], emphemeral: true });
},
};

View File

@@ -1,17 +0,0 @@
const { Events, EmbedBuilder } = require('discord.js');
module.exports = {
name: Events.GuildMemberAdd,
async execute({ client, log }, member) {
log.Info(`${member.user.username} has joined`);
const newMemberEmbed = new EmbedBuilder()
.setTitle(`${member.user.username} has joined!`)
.setDescription(`Welcome ${member} to the **Polarcraft** Discord server!`)
.setColor(process.env.EMBED_COLOR)
.setThumbnail(member.user.avatarURL());
const channel = await client.channels.cache.get(process.env.LOG_CHANNEL_ID);
channel.send({ embeds: [newMemberEmbed] });
},
};

View File

@@ -1,15 +0,0 @@
const { Events, EmbedBuilder } = require('discord.js');
module.exports = {
name: Events.GuildMemberRemove,
async execute({ client, log }, member) {
log.Info(`${member.user.username} has left`);
const newMemberEmbed = new EmbedBuilder()
.setTitle(`${member.user.username} has left!`)
.setColor(process.env.EMBED_COLOR);
const channel = await client.channels.cache.get(process.env.LOG_CHANNEL_ID);
channel.send({ embeds: [newMemberEmbed] });
},
};

View File

@@ -1,26 +0,0 @@
const { Events } = require('discord.js');
module.exports = {
name: Events.InteractionCreate,
async execute({ log, createEmbed, client }, interaction) {
if (interaction.isChatInputCommand()) {
const command = interaction.client.commands.get(interaction.commandName);
if (!command) {
return log.Error(`No command matching ${interaction.commandName} was found`);
} else {
log.Info(`${interaction.user.username} executed command ${interaction.commandName}`);
}
try {
await command.execute({ interaction, log, createEmbed, client });
} catch (error) {
log.Error(error);
await interaction.reply({ content: 'There was an error while executing this command!', ephemeral: true });
}
}
},
};

View File

@@ -1,11 +0,0 @@
const { Events } = require('discord.js');
module.exports = {
name: Events.ClientReady,
once: true,
execute({ client, log }) {
log.Info(`Ready! Logged in as ${client.user.tag}`);
require('../functions/registerCommands.js').registerCommands(log);
},
};

View File

@@ -1,12 +0,0 @@
const { EmbedBuilder } = require('discord.js');
const dotenv = require('dotenv');
dotenv.config();
const basic = (description) => {
return new EmbedBuilder()
.setColor(process.env.EMBED_COLOR)
.setDescription(description);
};
module.exports = { basic };

View File

@@ -1,31 +0,0 @@
const { EmbedBuilder } = require('discord.js');
const registerEvents = ({ createEmbed, client }) => {
client.player.on('trackStart', (queue, track) => {
const nowPlayingEmbed = new EmbedBuilder()
.setTitle('Now Playing')
.setColor(process.env.EMBED_COLOR)
.setDescription(`[${track.title}](${track.url})`)
.addFields(
{ name: 'Requested By', value: `${track.requestedBy}`, inline: true },
{ name: 'Duration', value: track.duration, inline: true },
{ name: 'Queue', value: `${queue.tracks.length} song(s)`, inline: true },
{ name: 'Author', value: track.author, inline: true },
{ name: 'Source', value: track.source, inline: true },
{ name: 'Volume', value: `${queue.options.initialVolume}%`, inline: true },
{ name: 'Filters', value: queue.getFiltersEnabled().join('\n') || 'No filters active', inline: false },
)
.setThumbnail(track.thumbnail)
.setTimestamp();
queue.metadata.channel.send({ embeds: [nowPlayingEmbed] });
});
client.player.on('error', (queue, error) => {
console.log(error);
});
};
module.exports = { registerEvents };

View File

@@ -1,48 +0,0 @@
const { REST, Routes } = require('discord.js');
const fs = require('node:fs');
const dotenv = require('dotenv');
dotenv.config();
const registerCommands = (log) => {
const commands = [];
// Grab all the command files from the commands directory you created earlier
const commandFiles = fs.readdirSync('./commands').filter(file => file.endsWith('.js'));
// Grab the SlashCommandBuilder#toJSON() output of each command's data for deployment
for (const file of commandFiles) {
const command = require(`../commands/${file}`);
commands.push(command.data.toJSON());
}
// Construct and prepare an instance of the REST module
const rest = new REST({ version: '10' }).setToken(process.env.DISCORD_TOKEN);
// and deploy your commands!
(async () => {
try {
log.Info(`Started refreshing ${commands.length} application (/) commands.`);
// The put method is used to fully refresh all commands in the guild with the current set
let data = null;
if (process.env.GUILD_ID !== 'production') {
data = await rest.put(
Routes.applicationGuildCommands(process.env.CLIENT_ID, process.env.GUILD_ID),
{ body: commands },
);
} else {
data = await rest.put(
Routes.applicationGuildCommands(process.env.CLIENT_ID),
{ body: commands },
);
}
log.Info(`Successfully reloaded ${data.length} application (/) commands.`);
} catch (error) {
// And of course, make sure you catch and log any errors!
log.Error(error);
}
})();
};
module.exports = { registerCommands };

View File

@@ -1,22 +0,0 @@
{
"type": "commonjs",
"name": "discord-bot",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"@discord-player/extractor": "^3.0.2",
"@discordjs/opus": "^0.8.0",
"chalk": "^4.1.2",
"discord-player": "^5.3.2",
"discord.js": "^14.7.1",
"distube": "^4.0.4",
"dotenv": "^16.0.3",
"eslint": "^8.29.0"
}
}

View File

@@ -5,7 +5,8 @@
"es6": true
},
"parserOptions": {
"ecmaVersion": 2021
"ecmaVersion": 2021,
"sourceType": "module"
},
"rules": {
"arrow-spacing": ["warn", { "before": true, "after": true }],

View File

@@ -1,2 +1,3 @@
.env
node_modules
database.sqlite

13
discordbot/Dockerfile Normal file
View File

@@ -0,0 +1,13 @@
FROM node:18-alpine
WORKDIR /usr/src/app
COPY . .
RUN apk update && apk upgrade
RUN apk add --no-cache sqlite
RUN npm install
RUN npm install --save sqlite3
CMD ["node", "index.js"]

View File

@@ -0,0 +1,29 @@
const { SlashCommandBuilder } = require('discord.js');
const { simpleEmbed } = require('../functions/embeds.js');
const { Users } = require('../functions/models.js');
module.exports = {
data: new SlashCommandBuilder()
.setName('adduser')
.setDescription('Add a user to the system')
.addUserOption(option => option
.setName('user')
.setDescription('The user to add')),
async execute(interaction) {
const user = interaction.options.getUser('user') ? interaction.options.getUser('user') : interaction.user;
try {
await Users.create({
id: user.id,
rawUsername: user.globalName,
});
await interaction.reply({ embeds: [simpleEmbed('Added user to the system')], ephemeral: true });
} catch (error) {
console.error(error);
await interaction.reply({ embeds: [simpleEmbed('There was an error while adding the user')], ephemeral: true });
}
},
};

View File

@@ -0,0 +1,49 @@
const { SlashCommandBuilder } = require('discord.js');
const { simpleEmbed } = require('../functions/embeds.js');
const { Users } = require('../functions/models.js');
const { client } = require('../index.js');
module.exports = {
data: new SlashCommandBuilder()
.setName('ban')
.setDescription('Ban a user')
.setDefaultMemberPermissions(0)
.addUserOption(option => option
.setName('user')
.setDescription('The user to ban')
.setRequired(true))
.addStringOption(option => option
.setName('reason')
.setDescription('Why ban the user')
.setRequired(true)),
async execute(interaction) {
const member = interaction.options.getMember('user');
const reason = interaction.options.getString('reason');
try {
await member.ban({ reason });
} catch (error) {
console.error(error);
return await interaction.reply({ embeds: [simpleEmbed(`Error while banning ${member}`)], ephemeral: true });
}
const userInstance = await Users.findOne({ where: { id: member.id } });
if (!userInstance) return await interaction.reply({ embeds: [simpleEmbed('Error while getting user information')], ephemeral: true });
if (userInstance.minecraftUuid) {
await fetch(process.env.MINECRAFT_HOST + '/console', {
method: 'POST',
headers: {
'content-type': 'text/plain',
},
body: `ban ${userInstance.minecraftUuid} ${reason}`,
});
}
const channel = client.channels.cache.get(process.env.MOD_LOG_CHANNEL_ID);
await channel.send({ embeds: [simpleEmbed(`${interaction.user} banned ${member}, reason: **${reason}**`)] });
await interaction.reply({ embeds: [simpleEmbed(`Banned ${member}`)], ephemeral: true });
},
};

View File

@@ -1,4 +1,5 @@
const { SlashCommandBuilder, PermissionFlagsBits } = require('discord.js');
const { simpleEmbed } = require('../functions/embeds.js');
module.exports = {
data: new SlashCommandBuilder()
@@ -10,15 +11,13 @@ module.exports = {
.setDescription('The amount of messages to clear')
.setRequired(true)),
async execute({ interaction, createEmbed, client }) {
async execute(interaction) {
const amount = interaction.options.getNumber('amount');
if (amount < 1 || amount > 100) return await interaction.reply({ embeds: [createEmbed.basic('The amount must be between 1-100')] });
if (amount < 1 || amount > 100) return await interaction.reply({ embeds: [simpleEmbed('The amount must be between 1-100')] });
const channel = client.channels.cache.get(interaction.channelId);
interaction.channel.bulkDelete(amount, true);
channel.bulkDelete(amount);
await interaction.reply({ embeds: [createEmbed.basic(`Cleared **${amount}** messages`)], ephemeral: true });
await interaction.reply({ embeds: [simpleEmbed(`Cleared **${amount}** messages`)], ephemeral: true });
},
};

View File

@@ -0,0 +1,11 @@
const { SlashCommandBuilder } = require('discord.js');
const { simpleEmbed } = require('../functions/embeds.js');
module.exports = {
data: new SlashCommandBuilder()
.setName('dennis')
.setDescription('Dennis.'),
async execute(interaction) {
await interaction.reply({ embeds: [simpleEmbed('Dennis is koel')], ephemeral: true });
},
};

View File

@@ -0,0 +1,62 @@
const { SlashCommandBuilder, EmbedBuilder } = require('discord.js');
module.exports = {
data: new SlashCommandBuilder()
.setName('message')
.setDescription('Send a default game message')
.setDefaultMemberPermissions(0)
.addStringOption(option => option
.setName('option')
.setDescription('Which message to send')
.setRequired(true)
.addChoices(
{ name: 'welcome', value: 'welcome' },
{ name: 'moderators', value: 'moderators' },
)),
async execute(interaction) {
const option = interaction.options.getString('option');
if (option === 'welcome') {
const embed0 = new EmbedBuilder()
.setTitle('Rules')
.setColor(process.env.EMBED_COLOR)
.setDescription('De regels zijn dit seizoen niet concreet. Zorg ervoor dat de ervaring voor iedereen leuk is en blijft. Een grapje maken mag, maar verpest niet iemand anders zijn ervaring.');
const embed1 = new EmbedBuilder()
.setTitle('Commands')
.setColor(process.env.EMBED_COLOR)
.addFields(
{ name: 'Whitelist', value: 'Join de Minecraft server en vul de gekregen code in door de `/whitelist` commando uit te voeren in discord. Door het commando `/removewhitelist` uit te voeren verwijder je jezelf van de whitelist.\n\u200B' },
{ name: 'Team', value: '**Team maken:** Voer het commando `/team create` uit in discord. Kleur kan je uitzoeken op deze website: [HTML Color Codes](https://htmlcolorcodes.com/color-picker/)\n\n**Inviten:** Voer het commando `/team invite <user>` uit in discord. Deze persoon zal een invite krijgen en deze accepteren of weigeren.\n\n**Leave:** Voer het commando `/team leave` uit om het team te verlaten.\n\u200B' },
{ name: 'Username', value: 'Door het commando `/setusername <type>` uit te voeren kan gekozen worden tussen de Minecraft of Discord username. Deze username zal op Discord en Minecraft weergegeven worden.\n\u200B' },
{ name: 'Minecraft', value: 'Door het commando `/map <hide/show>` uit te voeren in Minecraft kan gekozen om zichtbaar te zijn op [deze map](https://polarcraft.xeovalyte.com/) of niet' },
);
const embed2 = new EmbedBuilder()
.setTitle('Polarcraft Modpack')
.setColor(process.env.EMBED_COLOR)
.addFields({ name: 'Installeer Instructies', value: `
**1.** Installeer de [Modrinth launcher](https://modrinth.com/app) en log in\n
**2.** Klik op het zoek icoon op de linker balk en zoek voor "Polarcraft Modpack"\n
**3.** Klik vervolgens op "install"\n
**4.** Klaar! Klik op "Play" om Minecraft op te starten\n
` })
.setDescription('De Polarcraft Modpack is niet nodig, maar wel handig. In deze modpack zitten mods voor betere performance en Proximity chat mod. Als je er voor kiest om deze modpack niet te gebruiken is het leuk om zelf de [Plasmo Voice](https://modrinth.com/plugin/plasmo-voice) mod te installeren.');
const embed3 = new EmbedBuilder()
.setTitle('Links')
.setColor(process.env.EMBED_COLOR)
.setDescription('-> IP: polarcraft.xeovalyte.com\n-> [Minecraft Map](https://polarcraft.xeovalyte.com)\n-> [Polarcraft Modpack](https://modrinth.com/modpack/polarcraft-modpack)');
await interaction.reply({ embeds: [embed0, embed1, embed2, embed3] });
} else if (option === 'moderators') {
const embed = new EmbedBuilder()
.setTitle('Commands')
.setColor(process.env.EMBED_COLOR)
.setDescription('`/suspend <user> <time> <reason>` Dit commando zorgt ervoor dat een persoon tijdelijk niks kan doen. Gebruik dit als er bijvoorbeeld gegriefd wordt\n\n`/nuke` Dit commando zet de server in maintenance mode waardoor niemand meer kan joinen');
await interaction.reply({ embeds: [embed] });
}
},
};

View File

@@ -0,0 +1,21 @@
const { SlashCommandBuilder } = require('discord.js');
const { simpleEmbed } = require('../functions/embeds.js');
module.exports = {
data: new SlashCommandBuilder()
.setName('nuke')
.setDescription('Put the server in maintenance mode')
.setDefaultMemberPermissions(0),
async execute(interaction) {
await fetch(process.env.MINECRAFT_HOST + '/console', {
method: 'POST',
headers: {
'content-type': 'text/plain',
},
body: 'maintenance on',
});
await interaction.reply({ embeds: [simpleEmbed('Nuked server!')], ephemeral: true });
},
};

View File

@@ -0,0 +1,14 @@
const { SlashCommandBuilder } = require('discord.js');
const { simpleEmbed } = require('../functions/embeds.js');
const { client } = require('../index.js');
module.exports = {
data: new SlashCommandBuilder()
.setName('ping')
.setDescription('Replies with Pong!'),
async execute(interaction) {
const reply = await interaction.reply({ embeds: [simpleEmbed(`Websocket heartbeat: **${client.ws.ping}ms**\n Roundtrip latency: **Pinging...**`)], fetchReply: true, ephemeral: true });
interaction.editReply({ embeds: [simpleEmbed(`Websocket heartbeat: **${client.ws.ping}ms**\n Roundtrip latency: **${reply.createdTimestamp - interaction.createdTimestamp}ms**`)], ephemeral: true });
},
};

View File

@@ -0,0 +1,31 @@
const { SlashCommandBuilder } = require('discord.js');
const { simpleEmbed } = require('../functions/embeds.js');
const { Minecraft, Users } = require('../functions/models.js');
const { applyUsername } = require('../functions/utils.js');
module.exports = {
data: new SlashCommandBuilder()
.setName('removewhitelist')
.setDescription('Remove yourself from the whitelist'),
async execute(interaction) {
try {
const user = await Users.findOne({ where: { id: interaction.user.id } });
if (!user.minecraftUuid) return await interaction.reply({ embeds: [simpleEmbed('You are not whitelisted')], ephemeral: true });
await Minecraft.destroy({ where: { uuid: user.minecraftUuid } });
await applyUsername(user, interaction.member);
const role = await interaction.guild.roles.fetch(process.env.MINECRAFT_ROLE_ID);
await interaction.member.roles.remove(role);
await interaction.reply({ embeds: [simpleEmbed('Successfully removed you from the whitelist')], ephemeral: true });
} catch (error) {
console.error(error);
await interaction.reply({ embeds: [simpleEmbed('There was an error while removing you from the whitelist')], ephemeral: true });
}
},
};

View File

@@ -0,0 +1,38 @@
const { SlashCommandBuilder } = require('discord.js');
const { simpleEmbed } = require('../functions/embeds.js');
const { Users } = require('../functions/models.js');
const { applyUsername } = require('../functions/utils.js');
module.exports = {
data: new SlashCommandBuilder()
.setName('setusername')
.setDescription('Choose between Discord or Minecraft username')
.addStringOption(option => option
.setName('type')
.setDescription('Discord or Minecraft')
.setRequired(true)
.addChoices(
{ name: 'Discord', value: 'discord' },
{ name: 'Minecraft', value: 'minecraft' },
)),
async execute(interaction) {
const usernameType = interaction.options.getString('type');
try {
const user = await Users.findOne({ where: { id: interaction.user.id } });
user.useMinecraftUsername = usernameType === 'minecraft' ? true : false;
await user.save();
await applyUsername(user, interaction.member);
await interaction.reply({ embeds: [simpleEmbed('Successfully changed your username type')], ephemeral: true });
} catch (error) {
console.error(error);
await interaction.reply({ embeds: [simpleEmbed('There was an error while changing your username type')], ephemeral: true });
}
},
};

View File

@@ -0,0 +1,49 @@
const { SlashCommandBuilder } = require('discord.js');
const { simpleEmbed } = require('../functions/embeds.js');
const { Users } = require('../functions/models.js');
const { client } = require('../index.js');
module.exports = {
data: new SlashCommandBuilder()
.setName('suspend')
.setDescription('Suspend a user')
.setDefaultMemberPermissions(0)
.addUserOption(option => option
.setName('user')
.setDescription('The user to suspend')
.setRequired(true))
.addNumberOption(option => option
.setName('time')
.setDescription('The amount of time to suspend the user in minutes')
.setRequired(true))
.addStringOption(option => option
.setName('reason')
.setDescription('Why suspend the user')
.setRequired(true)),
async execute(interaction) {
const time = interaction.options.getNumber('time');
const member = interaction.options.getMember('user');
const reason = interaction.options.getString('reason');
await member.timeout(time * 60 * 1000, reason);
const user = await Users.findOne({ where: { id: member.id } });
if (!user) return await interaction.reply({ embeds: [simpleEmbed('Error while getting user information')], ephemeral: true });
if (user.minecraftUuid) {
await fetch(process.env.MINECRAFT_HOST + '/console', {
method: 'POST',
headers: {
'content-type': 'text/plain',
},
body: `tempban ${user.minecraftUuid} ${time}m ${reason}`,
});
}
const channel = client.channels.cache.get(process.env.MOD_LOG_CHANNEL_ID);
await channel.send({ embeds: [simpleEmbed(`${interaction.user} suspended ${member} for **${time}** minutes, reason: **${reason}**`)] });
await interaction.reply({ embeds: [simpleEmbed(`Suspended ${member} for **${time}** minutes`)], ephemeral: true });
},
};

208
discordbot/commands/team.js Normal file
View File

@@ -0,0 +1,208 @@
const { SlashCommandBuilder, ModalBuilder, TextInputStyle, TextInputBuilder, ActionRowBuilder, ChannelType, PermissionsBitField, ButtonBuilder, ButtonStyle, ComponentType } = require('discord.js');
const { simpleEmbed } = require('../functions/embeds.js');
const { Users, Team } = require('../functions/models.js');
const { applyUsername } = require('../functions/utils.js');
const { client } = require('../index.js');
module.exports = {
data: new SlashCommandBuilder()
.setName('team')
.setDescription('Team command')
.addSubcommand(subcommand => subcommand
.setName('create')
.setDescription('Create a team'))
.addSubcommand(subcommand => subcommand
.setName('invite')
.setDescription('Invite an user')
.addUserOption(option => option
.setName('user')
.setDescription('The user to invite')
.setRequired(true)))
.addSubcommand(subcommand => subcommand
.setName('leave')
.setDescription('Leave your team')),
async execute(interaction) {
const user = await Users.findOne({ where: { id: interaction.user.id } });
if (!user) return await interaction.reply({ embeds: [simpleEmbed('Error while getting user information')], ephemeral: true });
if (interaction.options.getSubcommand() === 'create') {
if (user.teamId) return await interaction.reply({ embeds: [simpleEmbed('You are already in a team')], ephemeral: true });
const modal = new ModalBuilder()
.setCustomId('teamCreate')
.setTitle('Create team');
const nameInput = new TextInputBuilder()
.setCustomId('nameInput')
.setLabel('Team name')
.setMinLength(3)
.setMaxLength(16)
.setStyle(TextInputStyle.Short);
const colorInput = new TextInputBuilder()
.setCustomId('colorInput')
.setLabel('Team color (hex)')
.setStyle(TextInputStyle.Short)
.setPlaceholder('#00ff00');
const firstActionRow = new ActionRowBuilder().addComponents(nameInput);
const secondActionRow = new ActionRowBuilder().addComponents(colorInput);
modal.addComponents(firstActionRow, secondActionRow);
await interaction.showModal(modal);
try {
const filter = (filterInteraction) => filterInteraction.customId === 'teamCreate';
const modalInteraction = await interaction.awaitModalSubmit({ filter, time: 10 * 60 * 1000 });
const teamName = modalInteraction.fields.getTextInputValue('nameInput');
const teamColor = modalInteraction.fields.getTextInputValue('colorInput');
if (!/^[a-zA-Z0-9]+$/.test(teamName)) return await modalInteraction.reply({ embeds: [simpleEmbed('Team name can only include alphanumeric characters')], ephemeral: true });
if (!/^#([0-9A-Fa-f]{3}|[0-9A-Fa-f]{6})$/.test(teamColor)) return await modalInteraction.reply({ embeds: [simpleEmbed('Team color must be a valid hex code. [Color Picker](https://htmlcolorcodes.com/color-picker/)')], ephemeral: true });
const guild = await client.guilds.fetch(process.env.GUILD_ID);
const category = await guild.channels.fetch(process.env.TEAM_CATEGORY_ID);
const textChannel = await guild.channels.create({
name: teamName,
type: ChannelType.GuildText,
parent: category,
permissionOverwrites: [
{
id: guild.id,
deny: [PermissionsBitField.Flags.ViewChannel],
},
{
id: interaction.member.id,
allow: [PermissionsBitField.Flags.ViewChannel],
},
],
});
const voiceChannel = await guild.channels.create({
name: teamName,
type: ChannelType.GuildVoice,
parent: category,
permissionOverwrites: [
{
id: guild.id,
deny: [PermissionsBitField.Flags.ViewChannel],
},
{
id: interaction.member.id,
allow: [PermissionsBitField.Flags.ViewChannel],
},
],
});
const team = await Team.create({
name: teamName,
color: teamColor,
textChannelId: textChannel.id,
voiceChannelId: voiceChannel.id,
});
await team.addMembers([ user ]);
await applyUsername(user, interaction.member);
await modalInteraction.reply({ embeds: [simpleEmbed(`Successfully created team **${teamName}**`)], ephemeral: true });
} catch (error) {
console.error(error);
}
} else if (interaction.options.getSubcommand() === 'leave') {
if (!user.teamId) return await interaction.reply({ embeds: [simpleEmbed('You are not in a team')], ephemeral: true });
const team = await user.getTeam();
await team.removeMember(user);
const guild = await client.guilds.fetch(process.env.GUILD_ID);
const textChannel = await guild.channels.fetch(team.textChannelId);
const voiceChannel = await guild.channels.fetch(team.voiceChannelId);
if (await team.countMembers() <= 0) {
await textChannel.delete();
await voiceChannel.delete();
await team.destroy();
} else {
await textChannel.permissionOverwrites.delete(interaction.member);
await voiceChannel.permissionOverwrites.delete(interaction.member);
}
await applyUsername(user, interaction.member);
await interaction.reply({ embeds: [simpleEmbed('Successfully left team')], ephemeral: true });
} else if (interaction.options.getSubcommand() === 'invite') {
if (!user.teamId) return await interaction.reply({ embeds: [simpleEmbed('You are not in a team')], ephemeral: true });
const invitedUser = interaction.options.getUser('user');
if (interaction.user.id === invitedUser.id) return await interaction.reply({ embeds: [simpleEmbed('You cannot invite yourself')], ephemeral: true });
const invitedUserInstance = await Users.findOne({ where: { id: invitedUser.id } });
if (invitedUserInstance.teamId) return await interaction.reply({ embeds: [simpleEmbed('The user you are trying already is in a team')], ephemeral: true });
const team = await user.getTeam();
const acceptButton = new ButtonBuilder()
.setCustomId('accept')
.setLabel('Accept')
.setStyle(ButtonStyle.Success);
const denyButton = new ButtonBuilder()
.setCustomId('deny')
.setLabel('Deny')
.setStyle(ButtonStyle.Danger);
const row = new ActionRowBuilder()
.addComponents(acceptButton, denyButton);
const inviteMessage = await invitedUser.send({
embeds: [simpleEmbed(`**${user.rawUsername}** invited you to join team **${team.name}**`)],
components: [row],
});
await interaction.reply({ embeds: [simpleEmbed(`Successfully invited ${invitedUser} to your team`)], ephemeral: true });
const collector = inviteMessage.createMessageComponentCollector({ componentType: ComponentType.Button, time: 60 * 60 * 1000 });
collector.on('collect', async i => {
try {
if (i.customId === 'accept') {
await invitedUserInstance.reload();
if (invitedUserInstance.teamId) return await i.message.edit({ embeds: [simpleEmbed('You are already in a team')], components: [] });
await team.addMember(i.user.id);
const guild = await client.guilds.fetch(process.env.GUILD_ID);
const member = await guild.members.fetch(i.user.id);
const textChannel = await guild.channels.fetch(team.textChannelId);
const voiceChannel = await guild.channels.fetch(team.voiceChannelId);
await textChannel.permissionOverwrites.edit(member, { ViewChannel: true });
await voiceChannel.permissionOverwrites.edit(member, { ViewChannel: true });
await applyUsername(invitedUserInstance, member);
await i.message.edit({ embeds: [simpleEmbed(`Successfully joined team **${team.name}**`)], components: [] });
} else if (i.customId === 'deny') {
await i.message.edit({ embeds: [simpleEmbed(`Successfully denied the request to join team **${team.name}**`)], components: [] });
}
} catch (error) {
console.error(error);
}
});
collector.on('end', async () => {
inviteMessage.edit({ embeds: [simpleEmbed('Confirmation not received within 1 hour, cancelling')], components: [] });
});
}
},
};

View File

@@ -0,0 +1,51 @@
const { SlashCommandBuilder } = require('discord.js');
const { simpleEmbed } = require('../functions/embeds.js');
const { Minecraft, Users } = require('../functions/models.js');
const { applyUsername } = require('../functions/utils.js');
module.exports = {
data: new SlashCommandBuilder()
.setName('whitelist')
.setDescription('Whitelist yourself on the Minecraft server')
.addStringOption(option => option
.setName('code')
.setDescription('6 digit code from Minecraft')
.setRequired(true)),
async execute(interaction) {
const code = interaction.options.getString('code');
if (code.length !== 6) return await interaction.reply({ embeds: [simpleEmbed('The code must be 6 digits long')], ephemeral: true });
const user = await Users.findOne({ where: { id: interaction.user.id } });
if (!user) return await interaction.reply({ embeds: [simpleEmbed('There was an error while finding the user')], ephemeral: true });
if (user.minecraftUuid) return await interaction.reply({ embeds: [simpleEmbed('You are already whitelisted')], ephemeral: true });
try {
const minecraftCol = await Minecraft.findOne({ where: { code: code } });
if (!minecraftCol) return await interaction.reply({ embeds: [simpleEmbed('The code was not linked with a Minecraft account')], ephemeral: true });
if (minecraftCol.whitelisted) return await interaction.reply({ embeds: [simpleEmbed('Minecraft account already whitelisted')], ephemeral: true });
minecraftCol.whitelisted = true;
delete minecraftCol.code;
user.minecraftUuid = minecraftCol.uuid;
await minecraftCol.save();
await user.save();
await applyUsername(user, interaction.member);
const role = await interaction.guild.roles.fetch(process.env.MINECRAFT_ROLE_ID);
await interaction.member.roles.add(role);
await interaction.reply({ embeds: [simpleEmbed('You are successfully whitelisted')], ephemeral: true });
} catch (error) {
console.error(error);
}
},
};

View File

@@ -0,0 +1,26 @@
const { Events, EmbedBuilder } = require('discord.js');
const { client } = require('../index.js');
const { Users } = require('../functions/models');
module.exports = {
name: Events.GuildMemberAdd,
async execute(member) {
const addMemberEmbed = new EmbedBuilder()
.setTitle(`${member.user.globalName} has joined!`)
.setDescription(`Welcome ${member} to the **Polarcraft** Discord server!`)
.setColor(process.env.EMBED_COLOR)
.setThumbnail(member.user.avatarURL());
const channel = client.channels.cache.get(process.env.LOG_CHANNEL_ID);
await channel.send({ embeds: [addMemberEmbed] });
try {
await Users.create({
id: member.user.id,
});
} catch (error) {
if (error.name === 'SequelizeUniqueConstraintError') return;
console.error(error);
}
},
};

View File

@@ -0,0 +1,14 @@
const { Events, EmbedBuilder } = require('discord.js');
const { client } = require('../index.js');
module.exports = {
name: Events.GuildMemberRemove,
async execute(member) {
const removeMemberEmbed = new EmbedBuilder()
.setTitle(`${member.user.globalName} has left!`)
.setColor(process.env.EMBED_COLOR);
const channel = client.channels.cache.get(process.env.LOG_CHANNEL_ID);
channel.send({ embeds: [removeMemberEmbed] });
},
};

View File

@@ -0,0 +1,25 @@
const { Events } = require('discord.js');
const { simpleEmbed } = require('../functions/embeds.js');
module.exports = {
name: Events.InteractionCreate,
async execute(interaction) {
if (interaction.isChatInputCommand() || interaction.isUserContextMenuCommand()) {
const command = interaction.client.commands.get(interaction.commandName);
if (!command) {
console.error(`No command matching ${interaction.commandName} was found.`);
return;
}
try {
await command.execute(interaction);
} catch (error) {
await interaction.reply({ embeds: [simpleEmbed('There was an error while executing the command')], ephemeral: true });
console.error(`Error executing ${interaction.commandName}`);
console.error(error);
}
}
},
};

View File

@@ -0,0 +1,35 @@
const { Events } = require('discord.js');
const { Users } = require('../functions/models.js');
module.exports = {
name: Events.MessageCreate,
async execute(message) {
if (message.channelId === process.env.MINECRAFT_CHANNEL_ID && !message.author.bot) {
try {
const user = await Users.findOne({ where: { id: message.author.id } });
if (!user) return;
const team = await user.getTeam();
let tellraw;
if (!team) {
tellraw = `tellraw @a ["",{"text":"DC","color":"gray"},{"text":" ${user.rawUsername} > ${message.content}"}]`;
} else {
tellraw = `tellraw @a ["",{"text":"DC ","color":"dark_gray"},{"text":"[","color":"gray"},{"text":"${team.name}","color":"${team.color}"},{"text":"]","color":"gray"},{"text":" ${user.rawUsername} "},{"text":"> ${message.content}"}]`;
}
await fetch(process.env.MINECRAFT_HOST + '/console', {
method: 'POST',
headers: {
'content-type': 'text/plain',
},
body: tellraw,
});
} catch (error) {
console.error(error);
}
}
},
};

View File

@@ -0,0 +1,17 @@
const { Events } = require('discord.js');
const deployCommands = require('../functions/deployCommands');
const { Users, Team, Minecraft } = require('../functions/models');
module.exports = {
name: Events.ClientReady,
once: true,
execute(client) {
Users.sync();
Team.sync();
Minecraft.sync();
console.log(`Ready! Logged in as ${client.user.tag}`);
deployCommands();
},
};

View File

@@ -0,0 +1,45 @@
const { REST, Routes } = require('discord.js');
const fs = require('node:fs');
const path = require('node:path');
module.exports = function deployCommands() {
const commands = [];
const commandsPath = path.join(__dirname, '../commands');
const commandFiles = fs.readdirSync(commandsPath).filter(file => file.endsWith('.js'));
for (const file of commandFiles) {
const filePath = path.join(commandsPath, file);
const command = require(filePath);
if ('data' in command && 'execute' in command) {
commands.push(command.data.toJSON());
} else {
console.log(`[WARNING] The command at ${filePath} is missing a required "data" or "execute" property.`);
}
}
const rest = new REST().setToken(process.env.DISCORD_TOKEN);
(async () => {
try {
console.log(`Started refreshing ${commands.length} application (/) commands.`);
let data;
if (process.env.GUILD_ID === 'production') {
data = await rest.put(
Routes.applicationCommands(process.env.DISCORD_APPLICATION_ID),
{ body: commands },
);
} else {
data = await rest.put(
Routes.applicationGuildCommands(process.env.DISCORD_APPLICATION_ID, process.env.GUILD_ID),
{ body: commands },
);
}
console.log(`Successfully reloaded ${data.length} application (/) commands.`);
} catch (error) {
console.error(error);
}
})();
};

View File

@@ -0,0 +1,9 @@
const { EmbedBuilder } = require('discord.js');
const simpleEmbed = (content) => {
return new EmbedBuilder()
.setColor(process.env.EMBED_COLOR)
.setDescription(content);
};
module.exports = { simpleEmbed };

View File

@@ -0,0 +1,73 @@
const { PartialWebhookMixin } = require('discord.js');
const { sequelize } = require('../index');
const Sequelize = require('sequelize');
const Users = sequelize.define('users', {
id: {
type: Sequelize.STRING,
primaryKey: true,
unique: true,
},
useMinecraftUsername: {
type: Sequelize.BOOLEAN,
defaultValue: false,
},
rawUsername: {
type: Sequelize.STRING,
},
moderator: {
type: Sequelize.BOOLEAN,
defaultValue: false,
},
admin: {
type: Sequelize.BOOLEAN,
defaultValue: false,
},
});
const Team = sequelize.define('teams', {
name: {
type: Sequelize.STRING,
unique: true,
validate: {
len: [3, 16],
isAlphanumeric: true,
},
},
color: {
type: Sequelize.STRING,
validate: {
is: /^#?([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/,
},
},
textChannelId: {
type: Sequelize.STRING,
},
voiceChannelId: {
type: Sequelize.STRING,
},
});
const Minecraft = sequelize.define('minecraft', {
uuid: {
type: Sequelize.UUID,
unique: true,
primaryKey: true,
},
whitelisted: {
type: Sequelize.BOOLEAN,
defaultValue: false,
},
code: {
type: Sequelize.STRING,
unique: true,
},
});
Minecraft.hasOne(Users);
Users.belongsTo(Minecraft);
Team.hasMany(Users, { as: 'members' });
Users.belongsTo(Team);
module.exports = { Users, Team, Minecraft };

View File

@@ -0,0 +1,29 @@
const applyUsername = async (user, member) => {
await user.reload();
let rawUsername = member.user.globalName;
if (user.useMinecraftUsername && user.minecraftUuid) {
const response = await fetch(`https://sessionserver.mojang.com/session/minecraft/profile/${user.minecraftUuid}`);
const minecraftProfile = await response.json();
rawUsername = minecraftProfile.name;
}
user.rawUsername = rawUsername;
const username = await getUsername(user);
await user.save();
await member.setNickname(username.slice(0, 32));
return username;
};
const getUsername = async (user) => {
const team = await user.getTeam();
return team ? user.rawUsername + ' [' + team.name + ']' : user.rawUsername;
};
module.exports = { applyUsername, getUsername };

View File

@@ -1,26 +1,29 @@
const chalk = require('chalk');
const { Client, GatewayIntentBits, Collection } = require('discord.js');
const { Player } = require('discord-player');
const express = require('express');
const Sequelize = require('sequelize');
const dotenv = require('dotenv');
const fs = require('node:fs');
const path = require('node:path');
const dotenv = require('dotenv');
const createEmbed = require('./functions/createEmbed.js');
dotenv.config();
const log = {
Info: (message) => console.log(chalk.blue('INFO'), message),
Error: (message) => console.log(chalk.red('ERROR'), message),
Warn: (message) => console.log(chalk.hex('#FFA500'), message),
};
// Register client and music events
const client = new Client({ intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildVoiceStates, GatewayIntentBits.GuildMembers] });
client.player = new Player(client);
// Configure database
const sequelize = new Sequelize('polarcraft', 'user', process.env.DATABSE_PASSWORD, {
host: 'localhost',
dialect: 'sqlite',
logging: false,
// SQLite only
storage: 'database.sqlite',
});
require('./functions/player.js').registerEvents({ client, createEmbed });
exports.sequelize = sequelize;
// Configure Discord
const client = new Client({ intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildVoiceStates, GatewayIntentBits.GuildMembers, GatewayIntentBits.GuildMessages, GatewayIntentBits.MessageContent] });
exports.client = client;
// Command handling
client.commands = new Collection();
const commandsPath = path.join(__dirname, 'commands');
@@ -33,12 +36,10 @@ for (const file of commandFiles) {
if ('data' in command && 'execute' in command) {
client.commands.set(command.data.name, command);
} else {
log.Warn(`The command at ${filePath} is missing a required "data" or "execute" property.`);
console.log(`[WARNING] The command at ${filePath} is missing a required "data" or "execute" property.`);
}
}
// Event handling
const eventsPath = path.join(__dirname, 'events');
const eventFiles = fs.readdirSync(eventsPath).filter(file => file.endsWith('.js'));
@@ -46,10 +47,26 @@ for (const file of eventFiles) {
const filePath = path.join(eventsPath, file);
const event = require(filePath);
if (event.once) {
client.once(event.name, (...args) => event.execute({ client, log, createEmbed }, ...args));
client.once(event.name, (...args) => event.execute(...args));
} else {
client.on(event.name, (...args) => event.execute({ client, log, createEmbed }, ...args));
client.on(event.name, (...args) => event.execute(...args));
}
}
// Configure express
const app = express();
app.use(express.json());
const verifyMinecraftRoute = require('./routes/verifyminecraft');
const messageRoute = require('./routes/message');
app.use('/verifyminecraft', verifyMinecraftRoute);
app.use('/message', messageRoute);
app.listen('3000', () => {
console.log('Express app is running');
});
client.login(process.env.DISCORD_TOKEN);

File diff suppressed because it is too large Load Diff

21
discordbot/package.json Normal file
View File

@@ -0,0 +1,21 @@
{
"name": "discordbot",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Xeovalyte",
"license": "ISC",
"dependencies": {
"discord.js": "^14.12.1",
"dotenv": "^16.3.1",
"express": "^4.18.2",
"sequelize": "^6.32.1",
"sqlite3": "^5.1.6"
},
"devDependencies": {
"eslint": "^8.46.0"
}
}

View File

@@ -0,0 +1,56 @@
const express = require('express');
const { WebhookClient, EmbedBuilder } = require('discord.js');
const { getUsername } = require('../functions/utils.js');
const { Users } = require('../functions/models.js');
const router = express.Router();
const webhookClient = new WebhookClient({ url: process.env.MINECRAFT_WEBHOOK_URL });
router.post('/player', async (req, res) => {
const { content, uuid } = req.body;
if (!uuid || !content) return res.status(400).send({ errorMessage: 'uuid and content are required' });
try {
const user = await Users.findOne({ where: { minecraftUUID: uuid } });
const username = await getUsername(user);
webhookClient.send({
content,
username,
avatarURL: 'https://api.mineatar.io/face/' + uuid + '?scale=8',
});
res.send({ status: 'ok' });
} catch (error) {
console.log(error);
res.status(500).send({ errorMessage: 'Error while sending player message' });
}
});
router.post('/game', async (req, res) => {
const { content, uuid } = req.body;
if (!uuid || !content) return res.status(400).send({ errorMessage: 'uuid and content are required' });
try {
const messageEmbed = new EmbedBuilder()
.setColor(process.env.EMBED_COLOR)
.setAuthor({ name: content, iconURL: 'https://api.mineatar.io/face/' + uuid + '?scale=8' });
webhookClient.send({
embeds: [messageEmbed],
username: 'Server',
});
res.send({ status: 'ok' });
} catch (error) {
console.log(error);
res.status(500).send({ errorMessage: 'Error while sending player message' });
}
});
module.exports = router;

View File

@@ -0,0 +1,47 @@
const express = require('express');
const { Minecraft, Users } = require('../functions/models.js');
const router = express.Router();
router.post('/', async (req, res) => {
const { uuid } = req.body;
if (!uuid) return res.status(400).send({ errorMessage: 'UUID is required' });
try {
const user = await Users.findOne({ where: { minecraftUUID: uuid } });
if (!user) {
const minecraftCol = await Minecraft.findOrCreate({
where: { uuid },
defaults: {
code: generateCode().toString(),
},
});
return res.send({ code: minecraftCol[0].code, whitelisted: minecraftCol[0].whitelisted });
}
const team = await user.getTeam();
let username;
if (!team) {
username = user.rawUsername;
} else {
username = '<gray>[</gray>' + `<color:${team.color}>${team.name}</color>` + '<gray>] </gray>' + user.rawUsername;
}
res.send({ whitelisted: true, username, rawUsername: user.rawUsername });
} catch (error) {
console.log(error);
res.status(500).send({ errorMessage: 'Error while verifing minecraft uuid' });
}
});
const generateCode = () => {
return Math.floor(100000 + Math.random() * 900000);
};
module.exports = router;

View File

@@ -1,6 +1,7 @@
plugins {
id 'fabric-loom' version '1.1-SNAPSHOT'
id 'fabric-loom' version '1.3-SNAPSHOT'
id 'maven-publish'
id 'com.github.johnrengelman.shadow' version '7.0.0'
}
version = project.mod_version
@@ -24,7 +25,6 @@ loom {
mods {
"polarcraft-mod" {
sourceSet sourceSets.main
sourceSet sourceSets.client
}
}
@@ -43,6 +43,7 @@ dependencies {
// These are included in the Fabric API production distribution and allow you to update your mod to the latest modules at a later more convenient time.
// modImplementation "net.fabricmc.fabric-api:fabric-api-deprecated:${project.fabric_version}"
shadow(implementation("com.sparkjava:spark-core:2.9.4"))
}
processResources {
@@ -73,6 +74,17 @@ jar {
}
}
shadowJar {
configurations = [project.configurations.shadow]
archiveClassifier.set("dev")
relocate "net.objecthunter", "de.siphalor.spiceoffabric.shadow.net.objecthunter"
}
remapJar {
dependsOn(shadowJar)
inputFile = tasks.shadowJar.archiveFile
}
// configure the maven publication
publishing {
publications {

View File

@@ -4,9 +4,9 @@ org.gradle.parallel=true
# Fabric Properties
# check these on https://fabricmc.net/develop
minecraft_version=1.19.4
yarn_mappings=1.19.4+build.2
loader_version=0.14.19
minecraft_version=1.20.2
yarn_mappings=1.20.2+build.2
loader_version=0.14.22
# Mod Properties
mod_version=1.0.0
@@ -14,4 +14,4 @@ maven_group=com.xeovalyte.polarcraft
archives_base_name=polarcraft-mod
# Dependencies
fabric_version=0.79.0+1.19.4
fabric_version=0.89.3+1.20.2

View File

@@ -0,0 +1,121 @@
package com.xeovalyte.polarcraft;
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.slf4j.Logger;
import org.slf4j.LoggerFactory;
import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents;
import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.network.ServerPlayerEntity;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.io.File;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import static spark.Spark.*;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
import net.fabricmc.fabric.api.message.v1.ServerMessageEvents;
public class PolarcraftMod implements ModInitializer {
// This logger is used to write text to the console and the log file.
// It is considered best practice to use your mod id as the logger's name.
// That way, it's clear which mod wrote info, warnings, and errors.
public static final Logger LOGGER = LoggerFactory.getLogger("polarcraft-mod");
private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
private static final File CONFIG_FILE = new File(FabricLoader.getInstance().getConfigDir().toFile(), "polarcraft.json");
public static String configChatMessageUrl = "https://example.com/message/player";
public static String configGameMessageUrl = "https://example.com/message/game";
public static String configVerifyUrl = "https://example.com/verifyminecraft";
@Override
public void onInitialize() {
// This code runs as soon as Minecraft is in a mod-load-ready state.
// However, some things (like resources) may still be uninitialized.
// Proceed with mild caution.
loadConfig();
ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> {
ServerPlayerEntity player = (ServerPlayerEntity) handler.player;
verifyFunction.onPlayerJoin(player, server);
});
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) -> {
messageFunctions.sendChatMessage(message, sender);
});
ServerLifecycleEvents.SERVER_STARTED.register((MinecraftServer server) -> {
port(8080); // Choose a suitable port for your web server
// Define the /console POST endpoint
post("/console", (req, res) -> {
String command = req.body(); // Get the command from the request body
// Validate and sanitize the command if needed
// Execute the console command in the Minecraft environment
executeConsoleCommand(command, server);
res.status(200);
return "Command executed successfully.";
});
});
}
private static void executeConsoleCommand(String command, MinecraftServer server) {
// Code to execute the console command within the Minecraft environment.
server.getCommandManager().executeWithPrefix(server.getCommandSource(), command);
}
private void loadConfig() {
if (!CONFIG_FILE.exists()) {
saveConfig();
return;
}
try {
MyModConfig config = GSON.fromJson(FileUtils.readFileToString(CONFIG_FILE, StandardCharsets.UTF_8), MyModConfig.class);
configChatMessageUrl = config.chatMessageUrl;
configGameMessageUrl = config.gameMessageUrl;
configVerifyUrl = config.verifyUrl;
} catch (IOException e) {
e.printStackTrace();
}
}
private void saveConfig() {
try {
FileUtils.writeStringToFile(CONFIG_FILE, GSON.toJson(new MyModConfig(configChatMessageUrl, configGameMessageUrl, configVerifyUrl)), StandardCharsets.UTF_8);
} catch (IOException e) {
e.printStackTrace();
}
}
public static class MyModConfig {
public String chatMessageUrl;
public String gameMessageUrl;
public String verifyUrl;
public MyModConfig(String chatMessageUrl, String gameMessageUrl,String verifyUrl) {
this.chatMessageUrl = chatMessageUrl;
this.gameMessageUrl = gameMessageUrl;
this.verifyUrl = verifyUrl;
}
}
}

View File

@@ -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() + "]");
}
}

View File

@@ -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());
}
}

View File

@@ -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();
}
}
}

View File

@@ -0,0 +1,69 @@
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.MinecraftServer;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.Text;
public class verifyFunction {
public static void onPlayerJoin(ServerPlayerEntity player, MinecraftServer server) {
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 whitelisted = jsonResponse.get("whitelisted").getAsBoolean();
if (!whitelisted) {
int code = jsonResponse.get("code").getAsInt();
player.networkHandler.disconnect(Text.literal("Whitelist yourself by using the /whitelist command in Discord with this code: " + code));
} else {
server.getCommandManager().executeWithPrefix(server.getCommandSource(), "/lp user " + player.getUuid() + " meta set display " + "\"" + jsonResponse.get("username").getAsString() + "\"");
messageFunctions.sendGameMessage(player.getUuid(), jsonResponse.get("rawUsername").getAsString() + " joined the game");
}
} catch (IOException e) {
player.networkHandler.disconnect(Text.literal("There was an error while verifing your account"));
e.printStackTrace();
}
}
}

View File

@@ -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.
}
}

View File

@@ -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
}
}

View File

@@ -1,11 +0,0 @@
{
"required": true,
"package": "com.xeovalyte.polarcraft.mixin.client",
"compatibilityLevel": "JAVA_17",
"client": [
"ExampleClientMixin"
],
"injectors": {
"defaultRequire": 1
}
}

View File

@@ -1,24 +1,28 @@
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.slf4j.Logger;
import org.slf4j.LoggerFactory;
import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents;
import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.Text;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.io.File;
import java.util.UUID;
import com.google.gson.stream.JsonReader;
import java.io.StringReader;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import static spark.Spark.*;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
import net.fabricmc.fabric.api.message.v1.ServerMessageEvents;
public class PolarcraftMod implements ModInitializer {
// This logger is used to write text to the console and the log file.
@@ -26,68 +30,92 @@ public class PolarcraftMod implements ModInitializer {
// That way, it's clear which mod wrote info, warnings, and errors.
public static final Logger LOGGER = LoggerFactory.getLogger("polarcraft-mod");
private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
private static final File CONFIG_FILE = new File(FabricLoader.getInstance().getConfigDir().toFile(), "polarcraft.json");
public static String configChatMessageUrl = "https://example.com/message/player";
public static String configGameMessageUrl = "https://example.com/message/game";
public static String configVerifyUrl = "https://example.com/verifyminecraft";
@Override
public void onInitialize() {
// This code runs as soon as Minecraft is in a mod-load-ready state.
// However, some things (like resources) may still be uninitialized.
// Proceed with mild caution.
loadConfig();
ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> {
ServerPlayerEntity player = (ServerPlayerEntity) handler.player;
LOGGER.info("Player {} joined the game.", player.getUuidAsString());
onPlayerJoin(player);
verifyFunction.onPlayerJoin(player, server);
});
LOGGER.info("Hello Fabric world!");
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) -> {
messageFunctions.sendChatMessage(message, sender);
});
ServerLifecycleEvents.SERVER_STARTED.register((MinecraftServer server) -> {
port(8080); // Choose a suitable port for your web server
// Define the /console POST endpoint
post("/console", (req, res) -> {
String command = req.body(); // Get the command from the request body
// Validate and sanitize the command if needed
// Execute the console command in the Minecraft environment
executeConsoleCommand(command, server);
res.status(200);
return "Command executed successfully.";
});
});
}
private void onPlayerJoin(ServerPlayerEntity player) {
UUID uuid = player.getUuid();
private static void executeConsoleCommand(String command, MinecraftServer server) {
// Code to execute the console command within the Minecraft environment.
server.getCommandManager().executeWithPrefix(server.getCommandSource(), command);
}
private void loadConfig() {
if (!CONFIG_FILE.exists()) {
saveConfig();
return;
}
try {
// Create the POST request
URL url = new URL("http://localhost:3000/api/minecraft/verifyuuid");
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestMethod("POST");
con.setRequestProperty("Content-Type", "application/json");
con.setDoOutput(true);
// Write the request body
String jsonInputString = "{\"uuid\":\"" + uuid + "\"}";
con.getOutputStream().write(jsonInputString.getBytes());
// Read the response
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
StringBuilder responseBuilder = new StringBuilder();
String responseLine;
while ((responseLine = in.readLine()) != null) {
responseBuilder.append(responseLine);
}
String responseBody = responseBuilder.toString();
// Parse the response as a JSON object
JsonReader jsonReader = new JsonReader(new StringReader(responseBody));
jsonReader.beginObject();
boolean verified = false;
int code = -1;
while (jsonReader.hasNext()) {
String key = jsonReader.nextName();
if (key.equals("verified")) {
verified = jsonReader.nextBoolean();
} else if (key.equals("code")) {
code = jsonReader.nextInt();
} else {
jsonReader.skipValue();
}
}
jsonReader.endObject();
// Kick the player if verified is true
if (!verified) {
player.networkHandler.disconnect(Text.literal("Whitelist yourself by using this code: " + code));
}
MyModConfig config = GSON.fromJson(FileUtils.readFileToString(CONFIG_FILE, StandardCharsets.UTF_8), MyModConfig.class);
configChatMessageUrl = config.chatMessageUrl;
configGameMessageUrl = config.gameMessageUrl;
configVerifyUrl = config.verifyUrl;
} catch (IOException e) {
player.networkHandler.disconnect(Text.literal("There was an error while verifing your account"));
e.printStackTrace();
}
}
private void saveConfig() {
try {
FileUtils.writeStringToFile(CONFIG_FILE, GSON.toJson(new MyModConfig(configChatMessageUrl, configGameMessageUrl, configVerifyUrl)), StandardCharsets.UTF_8);
} catch (IOException e) {
e.printStackTrace();
}
}
public static class MyModConfig {
public String chatMessageUrl;
public String gameMessageUrl;
public String verifyUrl;
public MyModConfig(String chatMessageUrl, String gameMessageUrl,String verifyUrl) {
this.chatMessageUrl = chatMessageUrl;
this.gameMessageUrl = gameMessageUrl;
this.verifyUrl = verifyUrl;
}
}
}

View File

@@ -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
}
}

View File

@@ -0,0 +1,22 @@
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;
@Mixin(ServerPlayerEntity.class)
public class MixinPlayerEntity {
@Inject(method = "onDeath", at = @At("HEAD"))
private void onDeath(DamageSource damageSource, CallbackInfo ci){
ServerPlayerEntity serverPlayerEntity = (ServerPlayerEntity) (Object) this;
Text deathMessage = damageSource.getDeathMessage(serverPlayerEntity);
messageFunctions.sendGameMessage(serverPlayerEntity.getUuid(), deathMessage.getString());
}
}

View File

@@ -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();
}
}
}

View File

@@ -0,0 +1,69 @@
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.MinecraftServer;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.Text;
public class verifyFunction {
public static void onPlayerJoin(ServerPlayerEntity player, MinecraftServer server) {
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 whitelisted = jsonResponse.get("whitelisted").getAsBoolean();
if (!whitelisted) {
int code = jsonResponse.get("code").getAsInt();
player.networkHandler.disconnect(Text.literal("Whitelist yourself by using the /whitelist command in Discord with this code: " + code));
} else {
server.getCommandManager().executeWithPrefix(server.getCommandSource(), "/lp user " + player.getUuid() + " meta set display " + "\"" + jsonResponse.get("username").getAsString() + "\"");
messageFunctions.sendGameMessage(player.getUuid(), jsonResponse.get("rawUsername").getAsString() + " joined the game");
}
} catch (IOException e) {
player.networkHandler.disconnect(Text.literal("There was an error while verifing your account"));
e.printStackTrace();
}
}
}

View File

@@ -13,22 +13,18 @@
},
"license": "CC0-1.0",
"icon": "assets/polarcraft-mod/icon.png",
"environment": "*",
"environment": "server",
"entrypoints": {
"main": [
"com.xeovalyte.polarcraft.PolarcraftMod"
]
},
"mixins": [
"polarcraft-mod.mixins.json",
{
"config": "polarcraft-mod.client.mixins.json",
"environment": "client"
}
"polarcraft-mod.mixins.json"
],
"depends": {
"fabricloader": ">=0.14.19",
"minecraft": "~1.19.4",
"minecraft": ">=1.20.1",
"java": ">=17",
"fabric-api": "*"
},

View File

@@ -3,7 +3,7 @@
"package": "com.xeovalyte.polarcraft.mixin",
"compatibilityLevel": "JAVA_17",
"mixins": [
"ExampleMixin"
"MixinPlayerEntity"
],
"injectors": {
"defaultRequire": 1

2
modpack-server/.gitattributes vendored Normal file
View File

@@ -0,0 +1,2 @@
# Disable Git line ending conversion, to prevent packwiz index hashes changing when committing from Windows
* -text

5
modpack-server/.gitignore vendored Normal file
View File

@@ -0,0 +1,5 @@
# Exclude exported CurseForge zip files
*.zip
# Exclude exported Modrinth modpacks
*.mrpack

View File

@@ -1,101 +1,171 @@
hash-format = "sha256"
[[files]]
file = "mods/alternate-current.pw.toml"
hash = "fda319290cfe268fdc7c6c6ca8dcad24e51c1de98442f23f2a41d657b26fc8d0"
metafile = true
[[files]]
file = "mods/anti-xray.pw.toml"
hash = "d8833b2961beb076df826ac3a34634260fa9828923a9a327da882065fa3b2f84"
hash = "f0e3f0178d1f8da2487cbb0cea687f441b84109e9f1030e2974d88fe10210aab"
metafile = true
[[files]]
file = "mods/banhammer.pw.toml"
hash = "40a4d80590660eadaa6002f006f0738136fa35583686ea1fb163f98c63d72bac"
hash = "1126dd7cb63d5e4086d74d0fe521156ab9ee0f2d53cd75f3926ffcf256c32953"
metafile = true
[[files]]
file = "mods/c2me-fabric.pw.toml"
hash = "9ab9f1ada10bc693019cdfea96fa09bcbaa3f27c8350e2e23fc45927f838cd9b"
metafile = true
[[files]]
file = "mods/carpet.pw.toml"
hash = "bc125da2af00e14613ca7d6582bbfff0ce63632dac134da4e9cfcf2d724bd856"
metafile = true
[[files]]
file = "mods/chunky.pw.toml"
hash = "c176a0f84b0c3c03423e68b988cd43f51a6b1cf13a844574b19e003324533da0"
metafile = true
[[files]]
file = "mods/debugify.pw.toml"
hash = "d02024521821336e40652c36c675ee520b4137ed73953e98f21bcf8a55f6a583"
hash = "ebc95d8dac761549f43c49938b8d1a0044a43af4484f492959de83a2bdc9e267"
metafile = true
[[files]]
file = "mods/fabric-api.pw.toml"
hash = "e87a52fb14288a8c503c76a40a18fb901de532b2805e84799c63d6202b3ce037"
hash = "d2b04b985ed22bb26338837b0547f08a41b82b23c3136f1fff9582b1748b7954"
metafile = true
[[files]]
file = "mods/fabric-language-kotlin.pw.toml"
hash = "0fe83c99b29c952f464c7bfba9cc86cc4f834bef7834821433fe23ce3dd230e6"
hash = "6f95b9e670d557f852a798489d7b5ec48ed8ddc7e8e1809ff06d4b187d17aac9"
metafile = true
[[files]]
file = "mods/fastback.pw.toml"
hash = "5b7e58e98cafdc851a3f86d9044b8a69a0d719c98fd9a64ab8a492b791861c81"
metafile = true
[[files]]
file = "mods/fastload.pw.toml"
hash = "9ab7092cb7e27bec8bb02d195e8f0c6a207b3f1383da7179a57ebd3328778a24"
hash = "0e72ac12907f4fb5a499a459cc2c64f9225a0c77ee59e76c9360ff0d3479aea2"
metafile = true
[[files]]
file = "mods/ferrite-core.pw.toml"
hash = "4c1b893d87c51588985c483fe33193ca03cf3673de998eef6eeb850d8928e7ab"
hash = "03e174cf691b52da20bd973b955fae6f3720d3d2120f9d6cc1de5fdf3180013c"
metafile = true
[[files]]
file = "mods/headindex.pw.toml"
hash = "48e4d5004d63bf599c62daf73c36f7bfaccd770c7cc8645c2d03e5cddede167d"
file = "mods/forge-config-api-port.pw.toml"
hash = "e00070f0db00ebcd304f8f68fd44e59ceaedbc8c27743c9c195134aae57c5fde"
metafile = true
[[files]]
file = "mods/invview.pw.toml"
hash = "fc6c71feb98476fa7cc0c683a52993bc751772171372fde95b0d823da0c6a2b7"
hash = "9c440b128787446aceeac944eb692793dd24e4596c23d0adfd64a76706ca774d"
metafile = true
[[files]]
file = "mods/krypton.pw.toml"
hash = "f999930809222b57898da25a30aad2135b02894f42c0e1d2832c4670272fbd1d"
metafile = true
[[files]]
file = "mods/lazydfu.pw.toml"
hash = "b4ca05b39b85c27cd97ccb65d5fb832f5e9fd7ee5710542a3e69dfa30a97ea7d"
metafile = true
[[files]]
file = "mods/ledger-databases.pw.toml"
hash = "d8c5d10864c6ee4a5ffdcf775ef6325fb88e6441db9c5c7874be1a6f1d714250"
metafile = true
[[files]]
file = "mods/ledger.pw.toml"
hash = "badf7e1fb371f1cdac13ce547794339a58c64d87793ce4d5bf4151f99d5e2e00"
hash = "e988cb120a107e8d0a3ad501beda973e1b247b290421667a67d95fce146e5dcc"
metafile = true
[[files]]
file = "mods/lithium.pw.toml"
hash = "feaedf6b6d73530c0289d9c7aa4149823343d2a7f9893f7b81e8c7c003763f31"
hash = "ed27ecb297016accc41e9894b6e11d6c46b455211e358afa6218ce629ef56978"
metafile = true
[[files]]
file = "mods/maintenancemode.pw.toml"
hash = "ed2ff97cf59a6c5b9f4e509edbc8c48944bb3c98795f6738c8dfec353cbe350d"
metafile = true
[[files]]
file = "mods/memoryleakfix.pw.toml"
hash = "5b43c0fc6904ad4480c8ed596411c6e24172f8320ccd63de97b4ce2e7e0f90a5"
hash = "8e42842f48b3227733bafced612212eee2298f567ca599ac6a55b9878ae661da"
metafile = true
[[files]]
file = "mods/minimotd.pw.toml"
hash = "c24df3c6860014bab5f2b5998b26a34e93461679b1c22e88c4eebfe992b5d756"
metafile = true
[[files]]
file = "mods/no-chat-reports.pw.toml"
hash = "df11b66e152011f96cc5a4dbf35d2dec99c4373cb19a8c1c761368170d425cf4"
hash = "293f06651cc903947ae422f5e612c73d66154453ad1390bda63920370671b968"
metafile = true
[[files]]
file = "mods/smoothboot-fabric.pw.toml"
hash = "971e8b0bef16bd6ce88c7f940b30fdc1debff7b715058f4d331d54beb58a4314"
file = "mods/ordered-player-list.pw.toml"
hash = "261eb8ac6dcc730afd8643a6486d6b013bbbe2f1200dacc88d7c495e4a588aa5"
metafile = true
[[files]]
file = "mods/pl3xmap.pw.toml"
hash = "53febdce710c35a2c12fe58a55a4d97ee50b0e4cc9ae8bf56e0d436b31602c3b"
metafile = true
[[files]]
file = "mods/servercore.pw.toml"
hash = "17b4cf782db225c145f5c2ababe1042deb0fed021f410d42691829673fa916c3"
metafile = true
[[files]]
file = "mods/slime.pw.toml"
hash = "cbd8c0b34192c5db74644840e2954be757698c805ed95bfb8007253c9783fab0"
metafile = true
[[files]]
file = "mods/spark.pw.toml"
hash = "9f7ce104c709103550148f4ff79acd17f9f93901224166445de1052b681c09da"
hash = "1f922cadccd8b79e824e78d5e2e691e65127e7a500723121a6a6ccc6a1060289"
metafile = true
[[files]]
file = "mods/starlight.pw.toml"
hash = "0a78a506125c0edc97d2292d26c6eab310106c60a5a4e64d73ff67bb619f5a4c"
metafile = true
[[files]]
file = "mods/styled-chat.pw.toml"
hash = "1555d923f1277dfd8c1c55bf1ad8fa109718b717ee2f528fdaa80978e25e74e3"
hash = "06f08304d7ce0221440ece1277be678c17dceb80ff982d19eaa9599345e92328"
metafile = true
[[files]]
file = "mods/styledplayerlist.pw.toml"
hash = "77b0faa9fdcbaf2d0b11358b34a659fd99e00dd5a7f150e0ad69a38259df81a7"
hash = "8a3e2e84597cef453b7f1c46e09764139db8c0915c662c2df9e738bc3efb14b3"
metafile = true
[[files]]
file = "mods/thorium.pw.toml"
hash = "61e2a941621007c901c96fe1474b3c07f208712fa6130151771d5235b6cc8adb"
file = "mods/vanish.pw.toml"
hash = "95886b6bc392072bf3ff366a19dc913745ec24fd86639012c49d50c13ca71cd1"
metafile = true
[[files]]
file = "mods/vmp-fabric.pw.toml"
hash = "4acfdcf28a7214490664892807bdb6c2d73b8d09295677e5629e5c896c3f9fbb"
metafile = true
[[files]]
file = "mods/worldedit.pw.toml"
hash = "a9ef701727ae9dd5baab92af7474cc57e34111b5858941fd5a96c89cacc6a30b"
metafile = true
[[files]]
file = "mods/yacl.pw.toml"
hash = "c66028d555a347562589645179fe8834bd04d48b78c9a667f20b4178211dfbb3"
hash = "46d3f8c4c1bfc8f92858d7e405aed9d1a23e554a783f8977662cbeca06eda5f2"
metafile = true

View File

@@ -1,13 +0,0 @@
name = "Alternate Current"
filename = "alternate-current-mc1.19-1.4.0.jar"
side = "server"
[download]
url = "https://cdn.modrinth.com/data/r0v8vy1s/versions/mc1.19-1.4.0/alternate-current-mc1.19-1.4.0.jar"
hash-format = "sha1"
hash = "108344ed05830948e6ab1414efa4f7ab34e6dba9"
[update]
[update.modrinth]
mod-id = "r0v8vy1s"
version = "4QElEqe4"

View File

@@ -1,13 +1,13 @@
name = "AntiXray"
filename = "anti-xray-1.3.0-Fabric-1.19.3.jar"
filename = "anti-xray-1.3.1-Fabric-1.20.2.jar"
side = "server"
[download]
url = "https://cdn.modrinth.com/data/sml2FMaA/versions/WPaK6kfx/anti-xray-1.3.0-Fabric-1.19.3.jar"
url = "https://cdn.modrinth.com/data/sml2FMaA/versions/asevPA28/anti-xray-1.3.1-Fabric-1.20.2.jar"
hash-format = "sha1"
hash = "a7cdba2fd9a2801cba56e74bedf6c6ee63a461a1"
hash = "9af6c8fe101e9a44500661078386c20cb68c92a4"
[update]
[update.modrinth]
mod-id = "sml2FMaA"
version = "WPaK6kfx"
version = "asevPA28"

View File

@@ -1,13 +1,13 @@
name = "BanHammer"
filename = "banhammer-0.6.3+1.19.3.jar"
filename = "banhammer-0.8.0+1.20.2.jar"
side = "server"
[download]
url = "https://cdn.modrinth.com/data/Wpqg0ciI/versions/LFwC8Fix/banhammer-0.6.3%2B1.19.3.jar"
url = "https://cdn.modrinth.com/data/Wpqg0ciI/versions/Ia1ERLRG/banhammer-0.8.0%2B1.20.2.jar"
hash-format = "sha1"
hash = "8c2bcb4aa5b8aeec6066d96f5675225cb625820a"
hash = "c7e5c4f334063eedad673cee228d35106ff5bfbf"
[update]
[update.modrinth]
mod-id = "Wpqg0ciI"
version = "LFwC8Fix"
version = "Ia1ERLRG"

View File

@@ -0,0 +1,13 @@
name = "Concurrent Chunk Management Engine (Fabric)"
filename = "c2me-fabric-mc1.20.2-0.2.0+alpha.10.126.jar"
side = "both"
[download]
url = "https://cdn.modrinth.com/data/VSNURh3q/versions/ilKwGRiJ/c2me-fabric-mc1.20.2-0.2.0%2Balpha.10.126.jar"
hash-format = "sha1"
hash = "fef69c623f5bfc6c10c86f2790a7c1ac2da3cf32"
[update]
[update.modrinth]
mod-id = "VSNURh3q"
version = "ilKwGRiJ"

View File

@@ -0,0 +1,13 @@
name = "Carpet"
filename = "fabric-carpet-1.20.2-1.4.119+v230928.jar"
side = "both"
[download]
url = "https://cdn.modrinth.com/data/TQTTVgYE/versions/iGHB3B1y/fabric-carpet-1.20.2-1.4.119%2Bv230928.jar"
hash-format = "sha1"
hash = "bfda47816a14ed51f646802ba97ead8e08e4eaa5"
[update]
[update.modrinth]
mod-id = "TQTTVgYE"
version = "iGHB3B1y"

View File

@@ -0,0 +1,13 @@
name = "Chunky"
filename = "Chunky-1.3.92.jar"
side = "both"
[download]
url = "https://cdn.modrinth.com/data/fALzjamp/versions/t8SbUchF/Chunky-1.3.92.jar"
hash-format = "sha1"
hash = "91f8daeeaab0f3114016fb1d45822179701862bf"
[update]
[update.modrinth]
mod-id = "fALzjamp"
version = "t8SbUchF"

View File

@@ -1,13 +1,13 @@
name = "Debugify"
filename = "Debugify-1.19.3+1.1.jar"
filename = "Debugify-1.20.2+1.0.jar"
side = "both"
[download]
url = "https://cdn.modrinth.com/data/QwxR6Gcd/versions/fgjgGIfI/Debugify-1.19.3%2B1.1.jar"
url = "https://cdn.modrinth.com/data/QwxR6Gcd/versions/ZSI78Xd3/Debugify-1.20.2%2B1.0.jar"
hash-format = "sha1"
hash = "d7f9cbf11bb36ef360de2b898a5a5e224eaef9e3"
hash = "5afa015e026de8acb4622e6e1429221e0b26e05e"
[update]
[update.modrinth]
mod-id = "QwxR6Gcd"
version = "fgjgGIfI"
version = "ZSI78Xd3"

View File

@@ -1,13 +1,13 @@
name = "Fabric API"
filename = "fabric-api-0.74.0+1.19.3.jar"
filename = "fabric-api-0.89.3+1.20.2.jar"
side = "both"
[download]
url = "https://cdn.modrinth.com/data/P7dR8mSH/versions/1ld37x4U/fabric-api-0.74.0%2B1.19.3.jar"
url = "https://cdn.modrinth.com/data/P7dR8mSH/versions/Hi8quJUM/fabric-api-0.89.3%2B1.20.2.jar"
hash-format = "sha1"
hash = "119d1710004834d83f34d2b8519aebedba981979"
hash = "de8d59b597ee5bbf1434e495c0cbc3772b1a414a"
[update]
[update.modrinth]
mod-id = "P7dR8mSH"
version = "1ld37x4U"
version = "Hi8quJUM"

View File

@@ -1,13 +1,13 @@
name = "Fabric Language Kotlin"
filename = "fabric-language-kotlin-1.9.1+kotlin.1.8.10.jar"
filename = "fabric-language-kotlin-1.10.10+kotlin.1.9.10.jar"
side = "both"
[download]
url = "https://cdn.modrinth.com/data/Ha28R6CL/versions/lgFl3olb/fabric-language-kotlin-1.9.1%2Bkotlin.1.8.10.jar"
url = "https://cdn.modrinth.com/data/Ha28R6CL/versions/48ri5y9r/fabric-language-kotlin-1.10.10%2Bkotlin.1.9.10.jar"
hash-format = "sha1"
hash = "12f265ea91e73ac2c74c6f66d446671122bbb1c8"
hash = "c708f3f4e94f0f66e72c6e96858368f0512c3b38"
[update]
[update.modrinth]
mod-id = "Ha28R6CL"
version = "lgFl3olb"
version = "48ri5y9r"

View File

@@ -0,0 +1,13 @@
name = "Fast Backups"
filename = "fastback-0.16.1+1.20.2-fabric.jar"
side = "both"
[download]
url = "https://cdn.modrinth.com/data/ZHKrK8Rp/versions/yuRPpkVE/fastback-0.16.1%2B1.20.2-fabric.jar"
hash-format = "sha1"
hash = "13f07b16c9311da033fe38ae93ef34cc0d19c7c4"
[update]
[update.modrinth]
mod-id = "ZHKrK8Rp"
version = "yuRPpkVE"

View File

@@ -1,13 +1,13 @@
name = "Fastload"
filename = "Fastload+1.19.3-2.6.11.jar"
filename = "Fastload+1.18.2-1.20-3.4.0.jar"
side = "both"
[download]
url = "https://cdn.modrinth.com/data/kCpssoSb/versions/GCH0zDV1/Fastload%2B1.19.3-2.6.11.jar"
url = "https://cdn.modrinth.com/data/kCpssoSb/versions/ys9T20o4/Fastload%2B1.18.2-1.20-3.4.0.jar"
hash-format = "sha1"
hash = "a796a3d17378e943a45caf576e9749aaa157d174"
hash = "b57e4d594031638b0dc076a3b6e501f417700577"
[update]
[update.modrinth]
mod-id = "kCpssoSb"
version = "GCH0zDV1"
version = "ys9T20o4"

View File

@@ -1,13 +1,13 @@
name = "FerriteCore"
filename = "ferritecore-5.1.0-fabric.jar"
filename = "ferritecore-6.0.0-fabric.jar"
side = "both"
[download]
url = "https://cdn.modrinth.com/data/uXXizFIs/versions/GHcKib6J/ferritecore-5.1.0-fabric.jar"
url = "https://cdn.modrinth.com/data/uXXizFIs/versions/FCnCG6PS/ferritecore-6.0.0-fabric.jar"
hash-format = "sha1"
hash = "4c45e0e8981374d6c98304c3de90e813eb930673"
hash = "5a57ea73c3c7c0cc300d69611a9cad93baf8e9ab"
[update]
[update.modrinth]
mod-id = "uXXizFIs"
version = "GHcKib6J"
version = "FCnCG6PS"

View File

@@ -0,0 +1,13 @@
name = "Forge Config API Port"
filename = "ForgeConfigAPIPort-v9.0.0-1.20.2-Fabric.jar"
side = "both"
[download]
url = "https://cdn.modrinth.com/data/ohNO6lps/versions/f5d9VI72/ForgeConfigAPIPort-v9.0.0-1.20.2-Fabric.jar"
hash-format = "sha1"
hash = "e9471a5836daab325aaa9bd08759705f8de94545"
[update]
[update.modrinth]
mod-id = "ohNO6lps"
version = "f5d9VI72"

View File

@@ -1,13 +0,0 @@
name = "Head Index"
filename = "headindex-1.1.1.jar"
side = "both"
[download]
url = "https://cdn.modrinth.com/data/mEPmyd7J/versions/smDwseAG/headindex-1.1.1.jar"
hash-format = "sha1"
hash = "0f6ed3d568acd55fcdb4814bdfb4256031254fac"
[update]
[update.modrinth]
mod-id = "mEPmyd7J"
version = "smDwseAG"

View File

@@ -1,13 +1,13 @@
name = "Inv View"
filename = "InvView-1.4.10-1.19.3+.jar"
filename = "InvView-1.4.12-1.20+.jar"
side = "both"
[download]
url = "https://cdn.modrinth.com/data/jrDKjZP7/versions/rv8bhw5X/InvView-1.4.10-1.19.3%2B.jar"
url = "https://cdn.modrinth.com/data/jrDKjZP7/versions/mQnjqDOd/InvView-1.4.12-1.20%2B.jar"
hash-format = "sha1"
hash = "99dd21d6aab9c65d9b1135bce9c912e6bfd48feb"
hash = "f6775526021843c16dc7847bbf0b8dbcca434454"
[update]
[update.modrinth]
mod-id = "jrDKjZP7"
version = "rv8bhw5X"
version = "mQnjqDOd"

View File

@@ -0,0 +1,13 @@
name = "Krypton"
filename = "krypton-0.2.4.jar"
side = "both"
[download]
url = "https://cdn.modrinth.com/data/fQEb0iXm/versions/cQ60Ouax/krypton-0.2.4.jar"
hash-format = "sha1"
hash = "cffdf89a438b83215ddbac2a29c56a2cd68b7d57"
[update]
[update.modrinth]
mod-id = "fQEb0iXm"
version = "cQ60Ouax"

View File

@@ -0,0 +1,13 @@
name = "LazyDFU"
filename = "lazydfu-0.1.3.jar"
side = "both"
[download]
url = "https://cdn.modrinth.com/data/hvFnDODi/versions/0.1.3/lazydfu-0.1.3.jar"
hash-format = "sha1"
hash = "0dfa8b03ed408fb7fdada29e01cfebba02af1049"
[update]
[update.modrinth]
mod-id = "hvFnDODi"
version = "4SHylIO9"

View File

@@ -0,0 +1,13 @@
name = "Ledger Databases"
filename = "ledger-databases-1.1.1.jar"
side = "both"
[download]
hash-format = "sha1"
hash = "d806fed8fea5f3f5a3dc892d605bd6720c86f43e"
mode = "metadata:curseforge"
[update]
[update.curseforge]
file-id = 3834676
project-id = 529404

View File

@@ -1,13 +1,13 @@
name = "Ledger"
filename = "ledger-1.2.6.jar"
filename = "ledger-1.2.9.jar"
side = "server"
[download]
url = "https://cdn.modrinth.com/data/LVN9ygNV/versions/ykSbFGkA/ledger-1.2.6.jar"
url = "https://cdn.modrinth.com/data/LVN9ygNV/versions/8WSkA7qO/ledger-1.2.9.jar"
hash-format = "sha1"
hash = "636857df039d3cec623843844abb72c670590d61"
hash = "8b67c3f918dc655bada6fec3cffcb76628a21a96"
[update]
[update.modrinth]
mod-id = "LVN9ygNV"
version = "ykSbFGkA"
version = "8WSkA7qO"

View File

@@ -1,13 +1,13 @@
name = "Lithium"
filename = "lithium-fabric-mc1.19.3-0.10.4.jar"
filename = "lithium-fabric-mc1.20.2-0.12.0.jar"
side = "both"
[download]
url = "https://cdn.modrinth.com/data/gvQqBUqZ/versions/XS6vJwop/lithium-fabric-mc1.19.3-0.10.4.jar"
url = "https://cdn.modrinth.com/data/gvQqBUqZ/versions/qdzL5Hkg/lithium-fabric-mc1.20.2-0.12.0.jar"
hash-format = "sha1"
hash = "a1b521e18f7857a2fd327c7bebeed3128418e3c9"
hash = "9b713d4909582d900274dcd7ca01abd195b53520"
[update]
[update.modrinth]
mod-id = "gvQqBUqZ"
version = "XS6vJwop"
version = "qdzL5Hkg"

View File

@@ -0,0 +1,13 @@
name = "Maintenance Mode"
filename = "mmode-fabric-1.20-1.1.1.jar"
side = "server"
[download]
url = "https://cdn.modrinth.com/data/QOkEkSap/versions/TT7eUrpf/mmode-fabric-1.20-1.1.1.jar"
hash-format = "sha1"
hash = "da772889aaff617e9d85fd1ff4637663219f38c3"
[update]
[update.modrinth]
mod-id = "QOkEkSap"
version = "TT7eUrpf"

View File

@@ -1,13 +1,13 @@
name = "Memory Leak Fix"
filename = "memoryleakfix-1.19.3-0.7.0.jar"
filename = "memoryleakfix-fabric-1.17+-1.1.2.jar"
side = "both"
[download]
url = "https://cdn.modrinth.com/data/NRjRiSSD/versions/YtNQP5gX/memoryleakfix-1.19.3-0.7.0.jar"
url = "https://cdn.modrinth.com/data/NRjRiSSD/versions/dGlflhb6/memoryleakfix-fabric-1.17%2B-1.1.2.jar"
hash-format = "sha1"
hash = "9fae1093c64b47d6b97ee825ed3d9b725490700c"
hash = "b0eecb140bd124c781469aa0f48bc888072b4ac5"
[update]
[update.modrinth]
mod-id = "NRjRiSSD"
version = "YtNQP5gX"
version = "dGlflhb6"

View File

@@ -0,0 +1,13 @@
name = "MiniMOTD"
filename = "minimotd-fabric-mc1.20.2-2.0.14.jar"
side = "server"
[download]
url = "https://cdn.modrinth.com/data/16vhQOQN/versions/3stGUvKr/minimotd-fabric-mc1.20.2-2.0.14.jar"
hash-format = "sha1"
hash = "060e0cfdcbe2d7fcf35373ec01cf0a3d468dd28b"
[update]
[update.modrinth]
mod-id = "16vhQOQN"
version = "3stGUvKr"

View File

@@ -1,13 +1,13 @@
name = "No Chat Reports"
filename = "NoChatReports-FABRIC-1.19.3-v2.0.0.jar"
filename = "NoChatReports-FABRIC-1.20.2-v2.3.1.jar"
side = "both"
[download]
url = "https://cdn.modrinth.com/data/qQyHxfxd/versions/uVt4LKvF/NoChatReports-FABRIC-1.19.3-v2.0.0.jar"
url = "https://cdn.modrinth.com/data/qQyHxfxd/versions/xQyq2W5g/NoChatReports-FABRIC-1.20.2-v2.3.1.jar"
hash-format = "sha1"
hash = "2eaa80b4480ca6c0d8b1180fdb742ebcb43ac300"
hash = "cb77c14bfc458066eda3c7962c3286e0f973725e"
[update]
[update.modrinth]
mod-id = "qQyHxfxd"
version = "uVt4LKvF"
version = "xQyq2W5g"

View File

@@ -0,0 +1,13 @@
name = "Ordered Player List"
filename = "orderedplayerlist-0.1.3+1.20.2.jar"
side = "server"
[download]
url = "https://cdn.modrinth.com/data/IX99VLW9/versions/DL7rAiJr/orderedplayerlist-0.1.3%2B1.20.2.jar"
hash-format = "sha1"
hash = "2902406910f397bcd8236d51b7b54f9f74c4ba5c"
[update]
[update.modrinth]
mod-id = "IX99VLW9"
version = "DL7rAiJr"

View File

@@ -0,0 +1,13 @@
name = "Pl3xMap"
filename = "Pl3xMap-1.20.2-470.jar"
side = "both"
[download]
url = "https://cdn.modrinth.com/data/YMXhf1UJ/versions/XrSXxwyn/Pl3xMap-1.20.2-470.jar"
hash-format = "sha1"
hash = "1e7b36c914c49f5febd86426ca528556d22479bd"
[update]
[update.modrinth]
mod-id = "YMXhf1UJ"
version = "XrSXxwyn"

View File

@@ -0,0 +1,13 @@
name = "ServerCore"
filename = "servercore-fabric-1.3.8+1.20.2.jar"
side = "both"
[download]
url = "https://cdn.modrinth.com/data/4WWQxlQP/versions/LrB49Mln/servercore-fabric-1.3.8%2B1.20.2.jar"
hash-format = "sha1"
hash = "e99fb454665cd298f44bfb5b415b4b54c02224f9"
[update]
[update.modrinth]
mod-id = "4WWQxlQP"
version = "LrB49Mln"

View File

@@ -0,0 +1,13 @@
name = "Slime"
filename = "slime-1.6.jar"
side = "both"
[download]
url = "https://cdn.modrinth.com/data/qpnMRvwM/versions/sQ9J9gE1/slime-1.6.jar"
hash-format = "sha1"
hash = "ace6e6b4538eaae4e9142023c67b1d5a83928d62"
[update]
[update.modrinth]
mod-id = "qpnMRvwM"
version = "sQ9J9gE1"

View File

@@ -1,13 +0,0 @@
name = "Smooth Boot (Fabric)"
filename = "smoothboot-fabric-1.19-1.7.1.jar"
side = "both"
[download]
url = "https://cdn.modrinth.com/data/FWumhS4T/versions/1.19-1.7.1/smoothboot-fabric-1.19-1.7.1.jar"
hash-format = "sha1"
hash = "8414cbce145a5f48102e6cc811dfd1459afe44f3"
[update]
[update.modrinth]
mod-id = "FWumhS4T"
version = "r8xRVPEI"

View File

@@ -1,13 +1,13 @@
name = "spark"
filename = "spark-1.10.29-fabric.jar"
filename = "spark-1.10.54-fabric.jar"
side = "both"
[download]
url = "https://cdn.modrinth.com/data/l6YH9Als/versions/1K3xO8TS/spark-1.10.29-fabric.jar"
url = "https://cdn.modrinth.com/data/l6YH9Als/versions/tCU9VuzX/spark-1.10.54-fabric.jar"
hash-format = "sha1"
hash = "680b8ed890e05ed0811065a381a7924d536e0508"
hash = "cc6d6dd27e2d6612e848330b5525026709590239"
[update]
[update.modrinth]
mod-id = "l6YH9Als"
version = "1K3xO8TS"
version = "tCU9VuzX"

Some files were not shown because too many files have changed in this diff Show More