Compare commits

...

118 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
cafa230433 added fabric mod 2023-04-27 21:26:54 +02:00
796b156e8d added beginning of whitelist system 2023-04-25 15:51:20 +02:00
fa0a9b8e58 created basic auth system 2023-04-23 17:16:53 +02:00
70f18f75df added authorization flow 2023-04-23 10:15:25 +02:00
125 changed files with 4411 additions and 22064 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 "es6": true
}, },
"parserOptions": { "parserOptions": {
"ecmaVersion": 2021 "ecmaVersion": 2021,
"sourceType": "module"
}, },
"rules": { "rules": {
"arrow-spacing": ["warn", { "before": true, "after": true }], "arrow-spacing": ["warn", { "before": true, "after": true }],

View File

@@ -1,2 +1,3 @@
.env .env
node_modules 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 { SlashCommandBuilder, PermissionFlagsBits } = require('discord.js');
const { simpleEmbed } = require('../functions/embeds.js');
module.exports = { module.exports = {
data: new SlashCommandBuilder() data: new SlashCommandBuilder()
@@ -10,15 +11,13 @@ module.exports = {
.setDescription('The amount of messages to clear') .setDescription('The amount of messages to clear')
.setRequired(true)), .setRequired(true)),
async execute({ interaction, createEmbed, client }) { async execute(interaction) {
const amount = interaction.options.getNumber('amount'); 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: [simpleEmbed(`Cleared **${amount}** messages`)], ephemeral: true });
await interaction.reply({ embeds: [createEmbed.basic(`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 { 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 fs = require('node:fs');
const path = require('node:path'); const path = require('node:path');
const dotenv = require('dotenv');
const createEmbed = require('./functions/createEmbed.js');
dotenv.config(); 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 // Configure database
const client = new Client({ intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildVoiceStates, GatewayIntentBits.GuildMembers] }); const sequelize = new Sequelize('polarcraft', 'user', process.env.DATABSE_PASSWORD, {
client.player = new Player(client); 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(); client.commands = new Collection();
const commandsPath = path.join(__dirname, 'commands'); const commandsPath = path.join(__dirname, 'commands');
@@ -33,12 +36,10 @@ for (const file of commandFiles) {
if ('data' in command && 'execute' in command) { if ('data' in command && 'execute' in command) {
client.commands.set(command.data.name, command); client.commands.set(command.data.name, command);
} else { } 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 eventsPath = path.join(__dirname, 'events');
const eventFiles = fs.readdirSync(eventsPath).filter(file => file.endsWith('.js')); 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 filePath = path.join(eventsPath, file);
const event = require(filePath); const event = require(filePath);
if (event.once) { if (event.once) {
client.once(event.name, (...args) => event.execute({ client, log, createEmbed }, ...args)); client.once(event.name, (...args) => event.execute(...args));
} else { } 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); 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;

40
mod/.gitignore vendored Normal file
View File

@@ -0,0 +1,40 @@
# gradle
.gradle/
build/
out/
classes/
# eclipse
*.launch
# idea
.idea/
*.iml
*.ipr
*.iws
# vscode
.settings/
.vscode/
bin/
.classpath
.project
# macos
*.DS_Store
# fabric
run/
# java
hs_err_*.log
replay_*.log
*.hprof
*.jfr

121
mod/LICENSE Normal file
View File

@@ -0,0 +1,121 @@
Creative Commons Legal Code
CC0 1.0 Universal
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
HEREUNDER.
Statement of Purpose
The laws of most jurisdictions throughout the world automatically confer
exclusive Copyright and Related Rights (defined below) upon the creator
and subsequent owner(s) (each and all, an "owner") of an original work of
authorship and/or a database (each, a "Work").
Certain owners wish to permanently relinquish those rights to a Work for
the purpose of contributing to a commons of creative, cultural and
scientific works ("Commons") that the public can reliably and without fear
of later claims of infringement build upon, modify, incorporate in other
works, reuse and redistribute as freely as possible in any form whatsoever
and for any purposes, including without limitation commercial purposes.
These owners may contribute to the Commons to promote the ideal of a free
culture and the further production of creative, cultural and scientific
works, or to gain reputation or greater distribution for their Work in
part through the use and efforts of others.
For these and/or other purposes and motivations, and without any
expectation of additional consideration or compensation, the person
associating CC0 with a Work (the "Affirmer"), to the extent that he or she
is an owner of Copyright and Related Rights in the Work, voluntarily
elects to apply CC0 to the Work and publicly distribute the Work under its
terms, with knowledge of his or her Copyright and Related Rights in the
Work and the meaning and intended legal effect of CC0 on those rights.
1. Copyright and Related Rights. A Work made available under CC0 may be
protected by copyright and related or neighboring rights ("Copyright and
Related Rights"). Copyright and Related Rights include, but are not
limited to, the following:
i. the right to reproduce, adapt, distribute, perform, display,
communicate, and translate a Work;
ii. moral rights retained by the original author(s) and/or performer(s);
iii. publicity and privacy rights pertaining to a person's image or
likeness depicted in a Work;
iv. rights protecting against unfair competition in regards to a Work,
subject to the limitations in paragraph 4(a), below;
v. rights protecting the extraction, dissemination, use and reuse of data
in a Work;
vi. database rights (such as those arising under Directive 96/9/EC of the
European Parliament and of the Council of 11 March 1996 on the legal
protection of databases, and under any national implementation
thereof, including any amended or successor version of such
directive); and
vii. other similar, equivalent or corresponding rights throughout the
world based on applicable law or treaty, and any national
implementations thereof.
2. Waiver. To the greatest extent permitted by, but not in contravention
of, applicable law, Affirmer hereby overtly, fully, permanently,
irrevocably and unconditionally waives, abandons, and surrenders all of
Affirmer's Copyright and Related Rights and associated claims and causes
of action, whether now known or unknown (including existing as well as
future claims and causes of action), in the Work (i) in all territories
worldwide, (ii) for the maximum duration provided by applicable law or
treaty (including future time extensions), (iii) in any current or future
medium and for any number of copies, and (iv) for any purpose whatsoever,
including without limitation commercial, advertising or promotional
purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
member of the public at large and to the detriment of Affirmer's heirs and
successors, fully intending that such Waiver shall not be subject to
revocation, rescission, cancellation, termination, or any other legal or
equitable action to disrupt the quiet enjoyment of the Work by the public
as contemplated by Affirmer's express Statement of Purpose.
3. Public License Fallback. Should any part of the Waiver for any reason
be judged legally invalid or ineffective under applicable law, then the
Waiver shall be preserved to the maximum extent permitted taking into
account Affirmer's express Statement of Purpose. In addition, to the
extent the Waiver is so judged Affirmer hereby grants to each affected
person a royalty-free, non transferable, non sublicensable, non exclusive,
irrevocable and unconditional license to exercise Affirmer's Copyright and
Related Rights in the Work (i) in all territories worldwide, (ii) for the
maximum duration provided by applicable law or treaty (including future
time extensions), (iii) in any current or future medium and for any number
of copies, and (iv) for any purpose whatsoever, including without
limitation commercial, advertising or promotional purposes (the
"License"). The License shall be deemed effective as of the date CC0 was
applied by Affirmer to the Work. Should any part of the License for any
reason be judged legally invalid or ineffective under applicable law, such
partial invalidity or ineffectiveness shall not invalidate the remainder
of the License, and in such case Affirmer hereby affirms that he or she
will not (i) exercise any of his or her remaining Copyright and Related
Rights in the Work or (ii) assert any associated claims and causes of
action with respect to the Work, in either case contrary to Affirmer's
express Statement of Purpose.
4. Limitations and Disclaimers.
a. No trademark or patent rights held by Affirmer are waived, abandoned,
surrendered, licensed or otherwise affected by this document.
b. Affirmer offers the Work as-is and makes no representations or
warranties of any kind concerning the Work, express, implied,
statutory or otherwise, including without limitation warranties of
title, merchantability, fitness for a particular purpose, non
infringement, or the absence of latent or other defects, accuracy, or
the present or absence of errors, whether or not discoverable, all to
the greatest extent permissible under applicable law.
c. Affirmer disclaims responsibility for clearing rights of other persons
that may apply to the Work or any use thereof, including without
limitation any person's Copyright and Related Rights in the Work.
Further, Affirmer disclaims responsibility for obtaining any necessary
consents, permissions or other rights required for any use of the
Work.
d. Affirmer understands and acknowledges that Creative Commons is not a
party to this document and has no duty or obligation with respect to
this CC0 or use of the Work.

103
mod/build.gradle Normal file
View File

@@ -0,0 +1,103 @@
plugins {
id 'fabric-loom' version '1.3-SNAPSHOT'
id 'maven-publish'
id 'com.github.johnrengelman.shadow' version '7.0.0'
}
version = project.mod_version
group = project.maven_group
base {
archivesName = project.archives_base_name
}
repositories {
// Add repositories to retrieve artifacts from in here.
// You should only use this when depending on other mods because
// Loom adds the essential maven repositories to download Minecraft and libraries from automatically.
// See https://docs.gradle.org/current/userguide/declaring_repositories.html
// for more information about repositories.
}
loom {
splitEnvironmentSourceSets()
mods {
"polarcraft-mod" {
sourceSet sourceSets.main
}
}
}
dependencies {
// To change the versions see the gradle.properties file
minecraft "com.mojang:minecraft:${project.minecraft_version}"
mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2"
modImplementation "net.fabricmc:fabric-loader:${project.loader_version}"
// Fabric API. This is technically optional, but you probably want it anyway.
modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}"
// Uncomment the following line to enable the deprecated Fabric API modules.
// 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 {
inputs.property "version", project.version
filesMatching("fabric.mod.json") {
expand "version": project.version
}
}
tasks.withType(JavaCompile).configureEach {
it.options.release = 17
}
java {
// Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task
// if it is present.
// If you remove this line, sources will not be generated.
withSourcesJar()
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
jar {
from("LICENSE") {
rename { "${it}_${project.archivesBaseName}"}
}
}
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 {
mavenJava(MavenPublication) {
from components.java
}
}
// See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing.
repositories {
// Add repositories to publish to here.
// Notice: This block does NOT have the same function as the block in the top level.
// The repositories here will be used for publishing your artifact, not for
// retrieving dependencies.
}
}

17
mod/gradle.properties Normal file
View File

@@ -0,0 +1,17 @@
# Done to increase the memory available to gradle.
org.gradle.jvmargs=-Xmx1G
org.gradle.parallel=true
# Fabric Properties
# check these on https://fabricmc.net/develop
minecraft_version=1.20.2
yarn_mappings=1.20.2+build.2
loader_version=0.14.22
# Mod Properties
mod_version=1.0.0
maven_group=com.xeovalyte.polarcraft
archives_base_name=polarcraft-mod
# Dependencies
fabric_version=0.89.3+1.20.2

BIN
mod/gradle/wrapper/gradle-wrapper.jar vendored Normal file

Binary file not shown.

View File

@@ -0,0 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip
networkTimeout=10000
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

245
mod/gradlew vendored Executable file
View File

@@ -0,0 +1,245 @@
#!/bin/sh
#
# Copyright © 2015-2021 the original authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
#
# Gradle start up script for POSIX generated by Gradle.
#
# Important for running:
#
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
# noncompliant, but you have some other compliant shell such as ksh or
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
# ksh Gradle
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
# * functions;
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit».
#
# Important for patching:
#
# (2) This script targets any POSIX shell, so it avoids extensions provided
# by Bash, Ksh, etc; in particular arrays are avoided.
#
# The "traditional" practice of packing multiple parameters into a
# space-separated string is a well documented source of bugs and security
# problems, so this is (mostly) avoided, by progressively accumulating
# options in "$@", and eventually passing that to Java.
#
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
# see the in-line comments for details.
#
# There are tweaks for specific operating systems such as AIX, CygWin,
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
#
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
app_path=$0
# Need this for daisy-chained symlinks.
while
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
[ -h "$app_path" ]
do
ls=$( ls -ld "$app_path" )
link=${ls#*' -> '}
case $link in #(
/*) app_path=$link ;; #(
*) app_path=$APP_HOME$link ;;
esac
done
# This is normally unused
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
warn () {
echo "$*"
} >&2
die () {
echo
echo "$*"
echo
exit 1
} >&2
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "$( uname )" in #(
CYGWIN* ) cygwin=true ;; #(
Darwin* ) darwin=true ;; #(
MSYS* | MINGW* ) msys=true ;; #(
NONSTOP* ) nonstop=true ;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD=$JAVA_HOME/jre/sh/java
else
JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD=java
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
fi
# Collect all arguments for the java command, stacking in reverse order:
# * args from the command line
# * the main class name
# * -classpath
# * -D...appname settings
# * --module-path (only if needed)
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
# For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
JAVACMD=$( cygpath --unix "$JAVACMD" )
# Now convert the arguments - kludge to limit ourselves to /bin/sh
for arg do
if
case $arg in #(
-*) false ;; # don't mess with options #(
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
[ -e "$t" ] ;; #(
*) false ;;
esac
then
arg=$( cygpath --path --ignore --mixed "$arg" )
fi
# Roll the args list around exactly as many times as the number of
# args, so each arg winds up back in the position where it started, but
# possibly modified.
#
# NB: a `for` loop captures its iteration list before it begins, so
# changing the positional parameters here affects neither the number of
# iterations, nor the values presented in `arg`.
shift # remove old arg
set -- "$@" "$arg" # push replacement arg
done
fi
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Collect all arguments for the java command;
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
# shell script including quotes and variable substitutions, so put them in
# double quotes to make sure that they get re-expanded; and
# * put everything else in single quotes, so that it's not re-expanded.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \
org.gradle.wrapper.GradleWrapperMain \
"$@"
# Stop when "xargs" is not available.
if ! command -v xargs >/dev/null 2>&1
then
die "xargs is not available"
fi
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
#
# In Bash we could simply go:
#
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
# set -- "${ARGS[@]}" "$@"
#
# but POSIX shell has neither arrays nor command substitution, so instead we
# post-process each arg (as a line of input to sed) to backslash-escape any
# character that might be a shell metacharacter, then use eval to reverse
# that process (while maintaining the separation between arguments), and wrap
# the whole thing up as a single "set" statement.
#
# This will of course break if any of these variables contains a newline or
# an unmatched quote.
#
eval "set -- $(
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
xargs -n1 |
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
tr '\n' ' '
)" '"$@"'
exec "$JAVACMD" "$@"

92
mod/gradlew.bat vendored Normal file
View File

@@ -0,0 +1,92 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%"=="" set DIRNAME=.
@rem This is normally unused
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if %ERRORLEVEL% equ 0 goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
set EXIT_CODE=%ERRORLEVEL%
if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

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

10
mod/settings.gradle Normal file
View File

@@ -0,0 +1,10 @@
pluginManagement {
repositories {
maven {
name = 'Fabric'
url = 'https://maven.fabricmc.net/'
}
mavenCentral()
gradlePluginPortal()
}
}

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 453 B

View File

@@ -0,0 +1,34 @@
{
"schemaVersion": 1,
"id": "polarcraft-mod",
"version": "${version}",
"name": "Polarcraft Mod",
"description": "This is an example description! Tell everyone what your mod is about!",
"authors": [
"Me!"
],
"contact": {
"homepage": "https://fabricmc.net/",
"sources": "https://github.com/FabricMC/fabric-example-mod"
},
"license": "CC0-1.0",
"icon": "assets/polarcraft-mod/icon.png",
"environment": "server",
"entrypoints": {
"main": [
"com.xeovalyte.polarcraft.PolarcraftMod"
]
},
"mixins": [
"polarcraft-mod.mixins.json"
],
"depends": {
"fabricloader": ">=0.14.19",
"minecraft": ">=1.20.1",
"java": ">=17",
"fabric-api": "*"
},
"suggests": {
"another-mod": "*"
}
}

View File

@@ -0,0 +1,11 @@
{
"required": true,
"package": "com.xeovalyte.polarcraft.mixin",
"compatibilityLevel": "JAVA_17",
"mixins": [
"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" hash-format = "sha256"
[[files]]
file = "mods/alternate-current.pw.toml"
hash = "fda319290cfe268fdc7c6c6ca8dcad24e51c1de98442f23f2a41d657b26fc8d0"
metafile = true
[[files]] [[files]]
file = "mods/anti-xray.pw.toml" file = "mods/anti-xray.pw.toml"
hash = "d8833b2961beb076df826ac3a34634260fa9828923a9a327da882065fa3b2f84" hash = "f0e3f0178d1f8da2487cbb0cea687f441b84109e9f1030e2974d88fe10210aab"
metafile = true metafile = true
[[files]] [[files]]
file = "mods/banhammer.pw.toml" 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 metafile = true
[[files]] [[files]]
file = "mods/debugify.pw.toml" file = "mods/debugify.pw.toml"
hash = "d02024521821336e40652c36c675ee520b4137ed73953e98f21bcf8a55f6a583" hash = "ebc95d8dac761549f43c49938b8d1a0044a43af4484f492959de83a2bdc9e267"
metafile = true metafile = true
[[files]] [[files]]
file = "mods/fabric-api.pw.toml" file = "mods/fabric-api.pw.toml"
hash = "e87a52fb14288a8c503c76a40a18fb901de532b2805e84799c63d6202b3ce037" hash = "d2b04b985ed22bb26338837b0547f08a41b82b23c3136f1fff9582b1748b7954"
metafile = true metafile = true
[[files]] [[files]]
file = "mods/fabric-language-kotlin.pw.toml" file = "mods/fabric-language-kotlin.pw.toml"
hash = "0fe83c99b29c952f464c7bfba9cc86cc4f834bef7834821433fe23ce3dd230e6" hash = "6f95b9e670d557f852a798489d7b5ec48ed8ddc7e8e1809ff06d4b187d17aac9"
metafile = true
[[files]]
file = "mods/fastback.pw.toml"
hash = "5b7e58e98cafdc851a3f86d9044b8a69a0d719c98fd9a64ab8a492b791861c81"
metafile = true metafile = true
[[files]] [[files]]
file = "mods/fastload.pw.toml" file = "mods/fastload.pw.toml"
hash = "9ab7092cb7e27bec8bb02d195e8f0c6a207b3f1383da7179a57ebd3328778a24" hash = "0e72ac12907f4fb5a499a459cc2c64f9225a0c77ee59e76c9360ff0d3479aea2"
metafile = true metafile = true
[[files]] [[files]]
file = "mods/ferrite-core.pw.toml" file = "mods/ferrite-core.pw.toml"
hash = "4c1b893d87c51588985c483fe33193ca03cf3673de998eef6eeb850d8928e7ab" hash = "03e174cf691b52da20bd973b955fae6f3720d3d2120f9d6cc1de5fdf3180013c"
metafile = true metafile = true
[[files]] [[files]]
file = "mods/headindex.pw.toml" file = "mods/forge-config-api-port.pw.toml"
hash = "48e4d5004d63bf599c62daf73c36f7bfaccd770c7cc8645c2d03e5cddede167d" hash = "e00070f0db00ebcd304f8f68fd44e59ceaedbc8c27743c9c195134aae57c5fde"
metafile = true metafile = true
[[files]] [[files]]
file = "mods/invview.pw.toml" 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 metafile = true
[[files]] [[files]]
file = "mods/ledger.pw.toml" file = "mods/ledger.pw.toml"
hash = "badf7e1fb371f1cdac13ce547794339a58c64d87793ce4d5bf4151f99d5e2e00" hash = "e988cb120a107e8d0a3ad501beda973e1b247b290421667a67d95fce146e5dcc"
metafile = true metafile = true
[[files]] [[files]]
file = "mods/lithium.pw.toml" file = "mods/lithium.pw.toml"
hash = "feaedf6b6d73530c0289d9c7aa4149823343d2a7f9893f7b81e8c7c003763f31" hash = "ed27ecb297016accc41e9894b6e11d6c46b455211e358afa6218ce629ef56978"
metafile = true
[[files]]
file = "mods/maintenancemode.pw.toml"
hash = "ed2ff97cf59a6c5b9f4e509edbc8c48944bb3c98795f6738c8dfec353cbe350d"
metafile = true metafile = true
[[files]] [[files]]
file = "mods/memoryleakfix.pw.toml" file = "mods/memoryleakfix.pw.toml"
hash = "5b43c0fc6904ad4480c8ed596411c6e24172f8320ccd63de97b4ce2e7e0f90a5" hash = "8e42842f48b3227733bafced612212eee2298f567ca599ac6a55b9878ae661da"
metafile = true
[[files]]
file = "mods/minimotd.pw.toml"
hash = "c24df3c6860014bab5f2b5998b26a34e93461679b1c22e88c4eebfe992b5d756"
metafile = true metafile = true
[[files]] [[files]]
file = "mods/no-chat-reports.pw.toml" file = "mods/no-chat-reports.pw.toml"
hash = "df11b66e152011f96cc5a4dbf35d2dec99c4373cb19a8c1c761368170d425cf4" hash = "293f06651cc903947ae422f5e612c73d66154453ad1390bda63920370671b968"
metafile = true metafile = true
[[files]] [[files]]
file = "mods/smoothboot-fabric.pw.toml" file = "mods/ordered-player-list.pw.toml"
hash = "971e8b0bef16bd6ce88c7f940b30fdc1debff7b715058f4d331d54beb58a4314" 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 metafile = true
[[files]] [[files]]
file = "mods/spark.pw.toml" file = "mods/spark.pw.toml"
hash = "9f7ce104c709103550148f4ff79acd17f9f93901224166445de1052b681c09da" hash = "1f922cadccd8b79e824e78d5e2e691e65127e7a500723121a6a6ccc6a1060289"
metafile = true
[[files]]
file = "mods/starlight.pw.toml"
hash = "0a78a506125c0edc97d2292d26c6eab310106c60a5a4e64d73ff67bb619f5a4c"
metafile = true metafile = true
[[files]] [[files]]
file = "mods/styled-chat.pw.toml" file = "mods/styled-chat.pw.toml"
hash = "1555d923f1277dfd8c1c55bf1ad8fa109718b717ee2f528fdaa80978e25e74e3" hash = "06f08304d7ce0221440ece1277be678c17dceb80ff982d19eaa9599345e92328"
metafile = true metafile = true
[[files]] [[files]]
file = "mods/styledplayerlist.pw.toml" file = "mods/styledplayerlist.pw.toml"
hash = "77b0faa9fdcbaf2d0b11358b34a659fd99e00dd5a7f150e0ad69a38259df81a7" hash = "8a3e2e84597cef453b7f1c46e09764139db8c0915c662c2df9e738bc3efb14b3"
metafile = true metafile = true
[[files]] [[files]]
file = "mods/thorium.pw.toml" file = "mods/vanish.pw.toml"
hash = "61e2a941621007c901c96fe1474b3c07f208712fa6130151771d5235b6cc8adb" 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 metafile = true
[[files]] [[files]]
file = "mods/yacl.pw.toml" file = "mods/yacl.pw.toml"
hash = "c66028d555a347562589645179fe8834bd04d48b78c9a667f20b4178211dfbb3" hash = "46d3f8c4c1bfc8f92858d7e405aed9d1a23e554a783f8977662cbeca06eda5f2"
metafile = true 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" 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" side = "server"
[download] [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-format = "sha1"
hash = "a7cdba2fd9a2801cba56e74bedf6c6ee63a461a1" hash = "9af6c8fe101e9a44500661078386c20cb68c92a4"
[update] [update]
[update.modrinth] [update.modrinth]
mod-id = "sml2FMaA" mod-id = "sml2FMaA"
version = "WPaK6kfx" version = "asevPA28"

View File

@@ -1,13 +1,13 @@
name = "BanHammer" name = "BanHammer"
filename = "banhammer-0.6.3+1.19.3.jar" filename = "banhammer-0.8.0+1.20.2.jar"
side = "server" side = "server"
[download] [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-format = "sha1"
hash = "8c2bcb4aa5b8aeec6066d96f5675225cb625820a" hash = "c7e5c4f334063eedad673cee228d35106ff5bfbf"
[update] [update]
[update.modrinth] [update.modrinth]
mod-id = "Wpqg0ciI" 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" name = "Debugify"
filename = "Debugify-1.19.3+1.1.jar" filename = "Debugify-1.20.2+1.0.jar"
side = "both" side = "both"
[download] [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-format = "sha1"
hash = "d7f9cbf11bb36ef360de2b898a5a5e224eaef9e3" hash = "5afa015e026de8acb4622e6e1429221e0b26e05e"
[update] [update]
[update.modrinth] [update.modrinth]
mod-id = "QwxR6Gcd" mod-id = "QwxR6Gcd"
version = "fgjgGIfI" version = "ZSI78Xd3"

View File

@@ -1,13 +1,13 @@
name = "Fabric API" 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" side = "both"
[download] [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-format = "sha1"
hash = "119d1710004834d83f34d2b8519aebedba981979" hash = "de8d59b597ee5bbf1434e495c0cbc3772b1a414a"
[update] [update]
[update.modrinth] [update.modrinth]
mod-id = "P7dR8mSH" mod-id = "P7dR8mSH"
version = "1ld37x4U" version = "Hi8quJUM"

View File

@@ -1,13 +1,13 @@
name = "Fabric Language Kotlin" 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" side = "both"
[download] [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-format = "sha1"
hash = "12f265ea91e73ac2c74c6f66d446671122bbb1c8" hash = "c708f3f4e94f0f66e72c6e96858368f0512c3b38"
[update] [update]
[update.modrinth] [update.modrinth]
mod-id = "Ha28R6CL" 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" name = "Fastload"
filename = "Fastload+1.19.3-2.6.11.jar" filename = "Fastload+1.18.2-1.20-3.4.0.jar"
side = "both" side = "both"
[download] [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-format = "sha1"
hash = "a796a3d17378e943a45caf576e9749aaa157d174" hash = "b57e4d594031638b0dc076a3b6e501f417700577"
[update] [update]
[update.modrinth] [update.modrinth]
mod-id = "kCpssoSb" mod-id = "kCpssoSb"
version = "GCH0zDV1" version = "ys9T20o4"

View File

@@ -1,13 +1,13 @@
name = "FerriteCore" name = "FerriteCore"
filename = "ferritecore-5.1.0-fabric.jar" filename = "ferritecore-6.0.0-fabric.jar"
side = "both" side = "both"
[download] [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-format = "sha1"
hash = "4c45e0e8981374d6c98304c3de90e813eb930673" hash = "5a57ea73c3c7c0cc300d69611a9cad93baf8e9ab"
[update] [update]
[update.modrinth] [update.modrinth]
mod-id = "uXXizFIs" 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" name = "Inv View"
filename = "InvView-1.4.10-1.19.3+.jar" filename = "InvView-1.4.12-1.20+.jar"
side = "both" side = "both"
[download] [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-format = "sha1"
hash = "99dd21d6aab9c65d9b1135bce9c912e6bfd48feb" hash = "f6775526021843c16dc7847bbf0b8dbcca434454"
[update] [update]
[update.modrinth] [update.modrinth]
mod-id = "jrDKjZP7" 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" name = "Ledger"
filename = "ledger-1.2.6.jar" filename = "ledger-1.2.9.jar"
side = "server" side = "server"
[download] [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-format = "sha1"
hash = "636857df039d3cec623843844abb72c670590d61" hash = "8b67c3f918dc655bada6fec3cffcb76628a21a96"
[update] [update]
[update.modrinth] [update.modrinth]
mod-id = "LVN9ygNV" mod-id = "LVN9ygNV"
version = "ykSbFGkA" version = "8WSkA7qO"

View File

@@ -1,13 +1,13 @@
name = "Lithium" name = "Lithium"
filename = "lithium-fabric-mc1.19.3-0.10.4.jar" filename = "lithium-fabric-mc1.20.2-0.12.0.jar"
side = "both" side = "both"
[download] [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-format = "sha1"
hash = "a1b521e18f7857a2fd327c7bebeed3128418e3c9" hash = "9b713d4909582d900274dcd7ca01abd195b53520"
[update] [update]
[update.modrinth] [update.modrinth]
mod-id = "gvQqBUqZ" 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" name = "Memory Leak Fix"
filename = "memoryleakfix-1.19.3-0.7.0.jar" filename = "memoryleakfix-fabric-1.17+-1.1.2.jar"
side = "both" side = "both"
[download] [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-format = "sha1"
hash = "9fae1093c64b47d6b97ee825ed3d9b725490700c" hash = "b0eecb140bd124c781469aa0f48bc888072b4ac5"
[update] [update]
[update.modrinth] [update.modrinth]
mod-id = "NRjRiSSD" 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" 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" side = "both"
[download] [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-format = "sha1"
hash = "2eaa80b4480ca6c0d8b1180fdb742ebcb43ac300" hash = "cb77c14bfc458066eda3c7962c3286e0f973725e"
[update] [update]
[update.modrinth] [update.modrinth]
mod-id = "qQyHxfxd" 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"

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