Skip to content

Commit

Permalink
Merge pull request #16 from Hyukna/master
Browse files Browse the repository at this point in the history
更新 Slimefun
  • Loading branch information
xMikux authored Feb 25, 2024
2 parents 01075ff + 3f93bb0 commit 24c58b8
Show file tree
Hide file tree
Showing 19 changed files with 615 additions and 45 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/e2e-testing.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ jobs:
"https://api.papermc.io/v2/projects/paper/versions/$VERSION/builds/$BUILD/downloads/$JAR_FILE"
- name: Download Slimefun
uses: actions/download-artifact@v3
uses: actions/download-artifact@v4
with:
name: ${{ inputs.artifact-name }}
path: plugins/
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/pull-request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ jobs:
run: mvn package

- name: Upload the artifact
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: slimefun-${{ github.event.number }}-${{ env.SHORT_COMMIT_HASH }}
path: 'target/Slimefun v${{ env.JAR_VERSION }}.jar'
Expand Down
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,14 @@ Slimefun4 使用[bStats](https://bstats.org/plugin/bukkit/Slimefun/4574)來收
安裝此插件時,會自動下載我們的[bStats 模塊](https://github.com/Slimefun/MetricsModule),該模塊將用於伺服器自動更新,與主插件無關.這樣,在出現嚴重性能問題的情況下,即時數據和對影響性能的洞察可能至關重要,我們可以自動向bStats模塊推出更新.
這些更新可以關閉在於 `/plugins/Slimefun/config.yml`.要關閉整個指標收集,請參見上面的段落

---

Slimefun 同時使用自己的分析系統以匿名方式來收集有關此插件的效能資訊。<br>
這僅用於統計目的,因為我們對所有伺服器的效能運作有興趣。<br>
所有資料均為匿名,我們決不會查看到個別伺服器的資訊。<br>

你可以在 `/plugins/Slimefun/config.yml` 下停用。<br>

</details>

<details>
Expand Down
32 changes: 22 additions & 10 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@
<!-- Compiler plugin -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.12.0</version>
<version>3.12.1</version>

<configuration>
<excludes>
Expand Down Expand Up @@ -146,7 +146,7 @@
<!-- Plugin for Unit Tests -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.2.3</version>
<version>3.2.5</version>

<configuration>
<junitArtifactName>org.junit.jupiter:junit-jupiter</junitArtifactName>
Expand Down Expand Up @@ -191,7 +191,7 @@
<!-- Dependency shading -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.5.1</version>
<version>3.5.2</version>

<configuration>
<!-- Relocate these to avoid clashes and conflicts -->
Expand Down Expand Up @@ -345,11 +345,10 @@
</dependency>

<!-- Shaded packages -->
<!-- TODO: Revert changes back to maven when dough 1.3 released -->
<dependency>
<groupId>com.github.baked-libs.dough</groupId>
<artifactId>dough-api</artifactId>
<version>fcdbd45aa0</version>
<version>0130f8d9ce</version>
<scope>compile</scope>
</dependency>
<dependency>
Expand Down Expand Up @@ -377,13 +376,13 @@
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.10.1</version>
<version>5.10.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>5.9.0</version>
<version>5.10.0</version>
<scope>test</scope>
</dependency>
<dependency>
Expand All @@ -406,14 +405,27 @@
<groupId>org.jetbrains</groupId>
<artifactId>annotations</artifactId>
</exclusion>
<exclusion>
<groupId>io.papermc.paper</groupId>
<artifactId>paper-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Override MockBukkit's Paper to a pinned slightly older version -->
<!-- This is because MockBukkit currently fails after this PR: -->
<!-- https://github.com/PaperMC/Paper/pull/9629 -->
<dependency>
<groupId>io.papermc.paper</groupId>
<artifactId>paper-api</artifactId>
<version>1.20.4-R0.1-20240205.114523-90</version>
<scope>test</scope>
</dependency>

<!-- Third party plugin integrations / soft dependencies -->
<dependency>
<groupId>com.sk89q.worldedit</groupId>
<artifactId>worldedit-core</artifactId>
<version>7.2.18</version>
<version>7.2.19</version>
<scope>provided</scope>

<exclusions>
Expand All @@ -427,7 +439,7 @@
<dependency>
<groupId>com.sk89q.worldedit</groupId>
<artifactId>worldedit-bukkit</artifactId>
<version>7.2.18</version>
<version>7.2.19</version>
<scope>provided</scope>

<exclusions>
Expand All @@ -441,7 +453,7 @@
<dependency>
<groupId>com.gmail.nossr50.mcMMO</groupId>
<artifactId>mcMMO</artifactId>
<version>2.1.226</version>
<version>2.1.230</version>
<scope>provided</scope>

<exclusions>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.OptionalInt;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Consumer;
import java.util.stream.IntStream;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
Expand All @@ -35,6 +36,8 @@
import io.github.thebusybiscuit.slimefun4.api.researches.Research;
import io.github.thebusybiscuit.slimefun4.core.attributes.ProtectionType;
import io.github.thebusybiscuit.slimefun4.core.attributes.ProtectiveArmor;
import io.github.thebusybiscuit.slimefun4.core.debug.Debug;
import io.github.thebusybiscuit.slimefun4.core.debug.TestCase;
import io.github.thebusybiscuit.slimefun4.core.guide.GuideHistory;
import io.github.thebusybiscuit.slimefun4.implementation.Slimefun;
import io.github.thebusybiscuit.slimefun4.implementation.items.armor.SlimefunArmorPiece;
Expand All @@ -54,6 +57,8 @@
*/
public class PlayerProfile {

private static final Map<UUID, Boolean> loading = new ConcurrentHashMap<>();

private final UUID ownerId;
private final String name;

Expand Down Expand Up @@ -237,13 +242,15 @@ public void removeWaypoint(@Nonnull Waypoint waypoint) {
* The profile can then be removed from RAM.
*/
public final void markForDeletion() {
Debug.log(TestCase.PLAYER_PROFILE_DATA, "Marking {} ({}) profile for deletion", name, ownerId);
markedForDeletion = true;
}

/**
* Call this method if this Profile has unsaved changes.
*/
public final void markDirty() {
Debug.log(TestCase.PLAYER_PROFILE_DATA, "Marking {} ({}) profile as dirty", name, ownerId);
dirty = true;
}

Expand Down Expand Up @@ -358,22 +365,47 @@ public static boolean fromUUID(@Nonnull UUID uuid, @Nonnull Consumer<PlayerProfi
*/
public static boolean get(@Nonnull OfflinePlayer p, @Nonnull Consumer<PlayerProfile> callback) {
Validate.notNull(p, "Cannot get a PlayerProfile for: null!");

UUID uuid = p.getUniqueId();

Debug.log(TestCase.PLAYER_PROFILE_DATA, "Getting PlayerProfile for {}", uuid);

PlayerProfile profile = Slimefun.getRegistry().getPlayerProfiles().get(uuid);

if (profile != null) {
Debug.log(TestCase.PLAYER_PROFILE_DATA, "PlayerProfile for {} was already loaded", uuid);
callback.accept(profile);
return true;
}

Bukkit.getScheduler().runTaskAsynchronously(Slimefun.instance(), () -> {
// If we're already loading, we don't want to spin up a whole new thread and load the profile again/more
// This can very easily cause CPU, memory and thread exhaustion if the profile is large
// See #4011, #4116
if (loading.containsKey(uuid)) {
Debug.log(TestCase.PLAYER_PROFILE_DATA, "Attempted to get PlayerProfile ({}) while loading", uuid);

// We can't easily consume the callback so we will throw it away in this case
// This will mean that if a user has attempted to do an action like open a block while
// their profile is still loading. Instead of it opening after a second or whatever when the
// profile is loaded, they will have to explicitly re-click the block/item/etc.
// This isn't the best but I think it's totally reasonable.
return false;
}

loading.put(uuid, true);
Slimefun.getThreadService().newThread(Slimefun.instance(), "PlayerProfile#get(" + uuid + ")", () -> {
PlayerData data = Slimefun.getPlayerStorage().loadPlayerData(p.getUniqueId());

AsyncProfileLoadEvent event = new AsyncProfileLoadEvent(new PlayerProfile(p, data));
Bukkit.getPluginManager().callEvent(event);

Slimefun.getRegistry().getPlayerProfiles().put(uuid, event.getProfile());

// Make sure we call this after we put the PlayerProfile into the registry.
// Otherwise, we end up with a race condition where the profile is not in the map just _yet_
// but the loading flag is gone and we can end up loading it a second time (and thus can dupe items)
// Fixes https://github.com/Slimefun/Slimefun4/issues/4130
loading.remove(uuid);

callback.accept(event.getProfile());
});

Expand All @@ -391,14 +423,32 @@ public static boolean get(@Nonnull OfflinePlayer p, @Nonnull Consumer<PlayerProf
*/
public static boolean request(@Nonnull OfflinePlayer p) {
Validate.notNull(p, "Cannot request a Profile for null");
Debug.log(TestCase.PLAYER_PROFILE_DATA, "Requesting PlayerProfile for {}", p.getName());

UUID uuid = p.getUniqueId();

if (!Slimefun.getRegistry().getPlayerProfiles().containsKey(p.getUniqueId())) {
// If we're already loading, we don't want to spin up a whole new thread and load the profile again/more
// This can very easily cause CPU, memory and thread exhaustion if the profile is large
// See #4011, #4116
if (loading.containsKey(uuid)) {
Debug.log(TestCase.PLAYER_PROFILE_DATA, "Attempted to request PlayerProfile ({}) while loading", uuid);
return false;
}

if (!Slimefun.getRegistry().getPlayerProfiles().containsKey(uuid)) {
loading.put(uuid, true);
// Should probably prevent multiple requests for the same profile in the future
Bukkit.getScheduler().runTaskAsynchronously(Slimefun.instance(), () -> {
PlayerData data = Slimefun.getPlayerStorage().loadPlayerData(p.getUniqueId());
Slimefun.getThreadService().newThread(Slimefun.instance(), "PlayerProfile#request(" + uuid + ")", () -> {
PlayerData data = Slimefun.getPlayerStorage().loadPlayerData(uuid);

PlayerProfile pp = new PlayerProfile(p, data);
Slimefun.getRegistry().getPlayerProfiles().put(p.getUniqueId(), pp);
Slimefun.getRegistry().getPlayerProfiles().put(uuid, pp);

// Make sure we call this after we put the PlayerProfile into the registry.
// Otherwise, we end up with a race condition where the profile is not in the map just _yet_
// but the loading flag is gone and we can end up loading it a second time (and thus can dupe items)
// Fixes https://github.com/Slimefun/Slimefun4/issues/4130
loading.remove(uuid);
});

return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem;
import io.github.thebusybiscuit.slimefun4.api.researches.Research;
import io.github.thebusybiscuit.slimefun4.core.debug.TestCase;
import io.github.thebusybiscuit.slimefun4.implementation.Slimefun;

class SlimefunTabCompleter implements TabCompleter {
Expand All @@ -33,6 +34,13 @@ public SlimefunTabCompleter(@Nonnull SlimefunCommand command) {
public List<String> onTabComplete(CommandSender sender, Command cmd, String label, String[] args) {
if (args.length == 1) {
return createReturnList(command.getSubCommandNames(), args[0]);
} else if (args.length == 2) {
if (args[0].equalsIgnoreCase("debug")) {
return createReturnList(TestCase.VALUES_LIST, args[1]);
} else {
// Returning null will make it fallback to the default arguments (all online players)
return null;
}
} else if (args.length == 3) {
if (args[0].equalsIgnoreCase("give")) {
return createReturnList(getSlimefunItems(), args[2]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,25 @@ public void onExecute(@Nonnull CommandSender sender, @Nonnull String[] args) {
.append(serverSoftware)
.color(ChatColor.GREEN)
.append(" " + Bukkit.getVersion() + '\n')
.color(ChatColor.DARK_GREEN)
.color(ChatColor.DARK_GREEN);

builder
.append("Slimefun ")
.color(ChatColor.GREEN)
.append(Slimefun.getVersion() + '\n')
.append(Slimefun.getVersion())
.color(ChatColor.DARK_GREEN);
if (!Slimefun.getUpdater().isLatestVersion()) {
builder
.append(" (").color(ChatColor.GRAY)
.append("Update available").color(ChatColor.RED).event(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text(
"你的黏液科技已過時!\n" +
"請更新來獲得最新的錯誤修正與效能提升。\n" +
"請勿在更新到最新之前回報任何錯誤。"
)))
.append(")").color(ChatColor.GRAY);
}

builder.append("\n");
// @formatter:on

if (Slimefun.getMetricsService().getVersion() != null) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
package io.github.thebusybiscuit.slimefun4.core.debug;

import java.util.Arrays;
import java.util.List;
import java.util.Locale;

import javax.annotation.Nonnull;

import io.github.thebusybiscuit.slimefun4.core.services.AnalyticsService;

/**
* Test cases in Slimefun. These are very useful for debugging why behavior is happening.
* Server owners can enable these with {@code /sf debug <test-case>}
Expand All @@ -17,7 +21,20 @@ public enum TestCase {
* being checked and why it is comparing IDs or meta.
* This is helpful for us to check into why input nodes are taking a while for servers.
*/
CARGO_INPUT_TESTING;
CARGO_INPUT_TESTING,

/**
* Debug information regarding player profile loading, saving and handling.
* This is an area we're currently changing quite a bit and this will help ensure we're doing it safely
*/
PLAYER_PROFILE_DATA,

/**
* Debug information regarding our {@link AnalyticsService}.
*/
ANALYTICS;

public static final List<String> VALUES_LIST = Arrays.stream(values()).map(TestCase::toString).toList();

TestCase() {}

Expand Down
Loading

0 comments on commit 24c58b8

Please sign in to comment.