Skip to content

Commit bf104d7

Browse files
committed
Bump version to 1.5.0 and add crash monitoring for real-time Discord announcements on world crashes
1 parent cae9a95 commit bf104d7

5 files changed

Lines changed: 100 additions & 2 deletions

File tree

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ plugins {
1818
boolean ci = System.getenv("CI") == "true"
1919

2020
group = 'one.armelin'
21-
version = '1.4.4'
21+
version = '1.5.0'
2222

2323
def decomp(fileCollection) {
2424
def jarFile = fileCollection.singleFile

src/main/java/one/armelin/distale/Configuration.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,24 @@ Crash message (Not implemented yet)
175175
Available placeholders:
176176
%crashdescription% | Crash description""")
177177
public String crashMessage = "**Server crashed:** %crashdescription%";
178+
179+
@Comment(value = """
180+
Hytale -> Discord
181+
World crash message
182+
Available placeholders:
183+
%worldname% | World name
184+
%crashdescription% | Crash description""")
185+
public String worldCrashMessage = "**World %worldname% crashed:** %crashdescription%";
186+
187+
@Comment(value = """
188+
Hytale -> Discord
189+
World crash message
190+
Available placeholders:
191+
%worldname% | World name
192+
%crashdescription% | Crash description
193+
%cause% | Potential cause of crash
194+
""")
195+
public String worldCrashWithCauseMessage = "**World %worldname% crashed:** %crashdescription%\n**Potential cause:** %cause%";
178196
}
179197

180198
/**

src/main/java/one/armelin/distale/DisTale.java

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,37 @@
11
package one.armelin.distale;
22

33
import com.hypixel.hytale.logger.HytaleLogger;
4+
import com.hypixel.hytale.logger.backend.HytaleLoggerBackend;
45
import com.hypixel.hytale.protocol.PlayerSkin;
56
import com.hypixel.hytale.server.core.command.system.CommandManager;
67
import com.hypixel.hytale.server.core.plugin.JavaPlugin;
78
import com.hypixel.hytale.server.core.plugin.JavaPluginInit;
89
import com.hypixel.hytale.server.core.universe.Universe;
10+
import com.hypixel.hytale.server.core.universe.world.World;
11+
import com.hypixel.hytale.server.core.universe.world.WorldConfig;
912
import net.dv8tion.jda.api.JDA;
1013
import net.dv8tion.jda.api.JDABuilder;
1114
import net.dv8tion.jda.api.entities.Activity;
1215
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
1316
import net.dv8tion.jda.api.exceptions.InvalidTokenException;
1417
import net.dv8tion.jda.api.requests.GatewayIntent;
18+
import net.dv8tion.jda.api.utils.MarkdownSanitizer;
1519
import net.dv8tion.jda.api.utils.MemberCachePolicy;
1620
import okhttp3.OkHttpClient;
1721
import okhttp3.Protocol;
1822
import one.armelin.distale.commands.ShrugCommand;
1923
import one.armelin.distale.listeners.*;
2024
import one.armelin.distale.listeners.systems.BeforeGatherMemoriesSystem;
2125
import one.armelin.distale.listeners.systems.PlayerDeathSystem;
26+
import one.armelin.distale.utils.ObservableCopyOnWriteArrayList;
2227

2328
import java.nio.file.Files;
2429
import java.util.Collections;
2530
import java.util.HashMap;
2631
import java.util.Map;
2732
import java.util.UUID;
33+
import java.util.logging.Level;
34+
import java.util.logging.LogRecord;
2835
import java.util.regex.Matcher;
2936
import java.util.regex.Pattern;
3037

@@ -53,6 +60,43 @@ public class DisTale extends JavaPlugin {
5360

5461
private static DisTale instance;
5562

63+
private static final ObservableCopyOnWriteArrayList<LogRecord> logWatcher = new ObservableCopyOnWriteArrayList<>(record -> {
64+
if(jda == null || stop || !config.announceCrashes) return;
65+
if(record.getLevel() == Level.SEVERE && record.getThrown() != null){
66+
if (record.getLoggerName().equals("Hytale")){
67+
Pattern pattern = Pattern.compile("Exception in thread Thread\\[#\\d+,([^,]+),[^\\]]*\\](?: potentially caused by (.+))?");
68+
Matcher matcher = pattern.matcher(record.getMessage());
69+
if (matcher.find()) {
70+
String threadName = matcher.group(1);
71+
String cause = matcher.group(2);
72+
if(threadName.startsWith("WorldThread")){
73+
String worldName = threadName.split(" - ")[1];
74+
Pattern uuidPattern = Pattern.compile("[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}");
75+
Matcher uuidMatcher = uuidPattern.matcher(worldName);
76+
if (uuidMatcher.find()) {
77+
World world = universe.getWorld(matcher.group());
78+
if(world != null){
79+
worldName = world.getWorldConfig().getDisplayName() != null ? world.getWorldConfig().getDisplayName() : WorldConfig.formatDisplayName(world.getName());
80+
}
81+
}
82+
String msg;
83+
if(cause != null){
84+
msg = DisTale.config.texts.worldCrashWithCauseMessage
85+
.replace("%worldname%", worldName)
86+
.replace("%crashdescription%", MarkdownSanitizer.escape(record.getThrown().getMessage()))
87+
.replace("%cause%", MarkdownSanitizer.escape(cause));
88+
} else {
89+
msg = DisTale.config.texts.worldCrashMessage
90+
.replace("%worldname%", worldName)
91+
.replace("%crashdescription%", MarkdownSanitizer.escape(record.getThrown().getMessage()));
92+
}
93+
textChannel.sendMessage(msg).queue();
94+
}
95+
}
96+
}
97+
}
98+
});
99+
56100
public DisTale(JavaPluginInit init) {
57101
super(init);
58102
instance = this;
@@ -70,6 +114,8 @@ public DisTale(JavaPluginInit init) {
70114
}
71115
config = Configuration.getConfig(getDataDirectory());
72116

117+
HytaleLoggerBackend.subscribe(logWatcher);
118+
73119
LOGGER.atInfo().log("DisTale initialized successfully!");
74120
}
75121

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package one.armelin.distale.utils;
2+
3+
import java.util.Collection;
4+
import java.util.concurrent.CopyOnWriteArrayList;
5+
import java.util.function.Consumer;
6+
7+
public class ObservableCopyOnWriteArrayList<E> extends CopyOnWriteArrayList<E> {
8+
9+
private final Consumer<E> onAdd;
10+
11+
public ObservableCopyOnWriteArrayList(Consumer<E> onAdd) {
12+
this.onAdd = onAdd;
13+
}
14+
15+
@Override
16+
public boolean add(E e) {
17+
boolean result = super.add(e);
18+
onAdd.accept(e);
19+
return result;
20+
}
21+
22+
@Override
23+
public void add(int index, E e) {
24+
super.add(index, e);
25+
onAdd.accept(e);
26+
}
27+
28+
@Override
29+
public boolean addAll(Collection<? extends E> c) {
30+
boolean result = super.addAll(c);
31+
if (result) c.forEach(onAdd);
32+
return result;
33+
}
34+
}

src/main/resources/manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"Group": "armelin1",
33
"Name": "DisTale",
4-
"Version": "1.4.4",
4+
"Version": "1.5.0",
55
"Description": "Discord bridge for Hytale servers - Chat integration, announcements, and commands",
66
"Authors": [
77
{

0 commit comments

Comments
 (0)