Closed NickCloudAT closed 10 months ago
Hi! Can you please add some code to reproduce the issue?
Hi! Can you please add some code to reproduce the issue?
Probably a bit tangled but this is the main file where I create the Advancements:
public class WCAdvancementsHandler {
private AdvancementTab advancementTab;
private RootAdvancement root;
private UltimateAdvancementAPI api = null;
private AdvancementChecks advancementChecks;
private final float yOffset = 3;
private final HashMap<String, BaseAdvancement> BASE_ADVANCEMENTS = new HashMap<>();
public WCAdvancementsHandler(){
advancementChecks = new AdvancementChecks(this);
registerAdvancements();
advancementChecks.startCheckRunnable();
}
public void registerAdvancements(){
if(!Main.getInstance().getServer().getPluginManager().isPluginEnabled("UltimateAdvancementAPI")){
Main.getInstance().getLogger().log(Level.INFO, "UltimateAdvancementAPI is not installed. Custom Advancements will not work.");
return;
}
api = UltimateAdvancementAPI.getInstance(Main.getInstance());
advancementTab = api.createAdvancementTab("wintercraft_advancements");
AdvancementDisplay rootDisplay = new AdvancementDisplay(Material.JACK_O_LANTERN, "§b§lWinterCraft 2024", AdvancementFrameType.TASK, true, true, 0, yOffset, "§eYour WinterCraft 2024 journey starts here!");
root = new RootAdvancement(advancementTab, "root", rootDisplay, "textures/block/snow.png");
buildAdvancements();
advancementTab.registerAdvancements(root, new HashSet<>(BASE_ADVANCEMENTS.values()));
advancementTab.getEventManager().register(advancementTab, PlayerLoadingCompletedEvent.class, e -> {
advancementTab.showTab(e.getPlayer());
advancementTab.grantRootAdvancement(e.getPlayer());
});
for(final Player on : Bukkit.getOnlinePlayers()){
advancementTab.showTab(on);
}
}
public AdvancementTab getWCAdvancementTab(){
return advancementTab;
}
public RootAdvancement getWCRootAdvancement(){
return root;
}
public void grantAdvancementByName(final Player p, final String name){
if(api == null || !BASE_ADVANCEMENTS.containsKey(name))return;
BASE_ADVANCEMENTS.get(name).grant(p);
}
public boolean hasEarnedAdvancement(final Player p, final String name){
if(api == null || !BASE_ADVANCEMENTS.containsKey(name))return false;
return BASE_ADVANCEMENTS.get(name).isGranted(p);
}
public void grantAdvancementIfHas(final Player p, final String toGrant, final String ifHas){
if(api == null || !BASE_ADVANCEMENTS.containsKey(toGrant) || !BASE_ADVANCEMENTS.containsKey(ifHas) || !hasEarnedAdvancement(p, ifHas))return;
grantAdvancementByName(p, toGrant);
}
public BaseAdvancement getAdvancementByName(final String name){
if(api == null || !BASE_ADVANCEMENTS.containsKey(name))return null;
return BASE_ADVANCEMENTS.get(name);
}
public UltimateAdvancementAPI getAdvancementAPI(){
return api;
}
//
private void buildAdvancements() {
final ItemStack slimeLocator = Main.getItemManageHandler().getItemFromFile("slimeLocator");
final ItemMeta slimeLocatorMeta = slimeLocator.getItemMeta();
// Define Advancements
createAdvancement(WCOpenSettingsMenuAdvancement.class, "settings_menu", Material.REDSTONE, "Open the settings menu", AdvancementFrameType.TASK, root, 1F, yOffset, "§cOpen the settings menu with §e/wc settings", 1);
createAdvancement(WCUseSlimeLocatorAdvancement.class, "use_slimelocator", slimeLocator, "Use a Slime Locator", AdvancementFrameType.TASK, getAdvancementByName("settings_menu"), 2F, yOffset - 1, "§eUse a Slime Locator at least once", 1);
slimeLocatorMeta.setCustomModelData(1);
slimeLocator.setItemMeta(slimeLocatorMeta);
createAdvancement(WCSlimeLocatorFindSlimeChunkAdvancement.class, "find_slimechunk", slimeLocator, "§5Slime chunk ahead!", AdvancementFrameType.CHALLENGE, getAdvancementByName("use_slimelocator"), 3F, yOffset - 1, "§cUse a Slime Locator and find a slime chunk", 1);
createAdvancement(WCTravelToNetherRoofAdvancement.class, "travel_netherroof", Material.OBSIDIAN, "How did I get here?!", AdvancementFrameType.TASK, getAdvancementByName("settings_menu"), 2F, yOffset + 1, "§eUse a Nether portal to reach the Nether roof", 1);
createAdvancement(WCBreakNetheriteHoeAdvancement.class, "break_netherite_hoe", Material.NETHERITE_HOE, "§5Serious loss :(", AdvancementFrameType.CHALLENGE, getAdvancementByName("travel_netherroof"), 3F, yOffset + 1, "§cHow did you manage to break a Netherite Hoe?!", 1);
createAdvancement(WCCraftGanAdvancement.class, "craft_gan", Material.COMMAND_BLOCK, "What is this currency?", AdvancementFrameType.TASK, getAdvancementByName("settings_menu"), 2F, yOffset, "§eCraft some Gan with your precious diamonds.", 1);
createAdvancement(WCCraftHalAdvancement.class, "craft_hal", Material.CHAIN_COMMAND_BLOCK, "You can even split it :O", AdvancementFrameType.TASK, getAdvancementByName("craft_gan"), 3F, yOffset, "§eDestroy some Gan and make some Hal out of it.", 1);
createAdvancement(WCCraftQuaAdvancement.class, "craft_qua", Material.REPEATING_COMMAND_BLOCK, "Compressed money!", AdvancementFrameType.TASK, getAdvancementByName("craft_hal"), 4F, yOffset, "§eCompress your Gan and make some Qua.", 1);
createAdvancement(WCHaveEnoughQuaAdvancement.class, "have_enough_qua", Material.REPEATING_COMMAND_BLOCK, "§5I'm rich, bitch!", AdvancementFrameType.GOAL, getAdvancementByName("craft_qua"), 5F, yOffset, "§cHave a full stack of Qua in your inventory.", 1);
createAdvancement(WCWalkDistanceAdvancement.class, "walk_100_km", Material.GOLDEN_BOOTS, "§5Walk in the park", AdvancementFrameType.GOAL, getAdvancementByName("settings_menu"), 1F, yOffset + 2, "§cWalk 100 kilometers.", 100000);
createAdvancement(WCCrouchDistanceAdvancement.class, "crouch_25_km", Material.GOLDEN_LEGGINGS, "§5Sneaky Snitch", AdvancementFrameType.GOAL, getAdvancementByName("walk_100_km"), 0F, yOffset + 2, "§cCrouch 25 kilometers.", 25000);
createAdvancement(WCShootAdvancement.class, "shoot_5000_times", Material.BOW, "§5Triggerhappy", AdvancementFrameType.GOAL, getAdvancementByName("settings_menu"), 2F, yOffset + 2, "§cShoot a Bow, Crossbow or Trident 5000 Times.", 5000);
}
private <T extends BaseAdvancement> void createAdvancement(Class<T> clazz, String id, Material icon, String title, AdvancementFrameType frameType, Advancement parent, float x, float y, String description, int maxProgression) {
try {
T advancement = clazz.getConstructor(String.class, AdvancementDisplay.class, Advancement.class, int.class)
.newInstance(id, new AdvancementDisplay(icon, title, frameType, true, true, x, y, description), parent, maxProgression);
BASE_ADVANCEMENTS.put(id, advancement);
} catch (Exception e) {
throw new RuntimeException("Failed to create and register advancement " + id, e);
}
}
private <T extends BaseAdvancement> void createAdvancement(Class<T> clazz, String id, ItemStack icon, String title, AdvancementFrameType frameType, Advancement parent, float x, float y, String description, int maxProgression) {
try {
T advancement = clazz.getConstructor(String.class, AdvancementDisplay.class, Advancement.class, int.class)
.newInstance(id, new AdvancementDisplay(icon, title, frameType, true, true, x, y, description), parent, maxProgression);
BASE_ADVANCEMENTS.put(id, advancement);
} catch (Exception e) {
throw new RuntimeException("Failed to create and register advancement " + id, e);
}
}
public AdvancementChecks getAdvancementChecks(){
return advancementChecks;
}
}
If you need something more, tell me.
I don't see anything problematic here. Can you also send the code of the advancement classes (please use a pastebin)? You can also send it privately to me on Discord if you don't feel comfortable sharing it publicly.
I don't see anything problematic here. Can you also send the code of the advancement classes (please use a pastebin)? You can also send it privately to me on Discord if you don't feel comfortable sharing it publicly.
Hey, sure. Would you mind just texting/adding me real quick? nickcloud on discord.
The issue is caused by some "large" advancements (with max progression in the thousands).
The solution is to show a completion percentage instead of the raw stat. The following code allows to do that without touching the max progression.
public class PercentageAdvancement extends BaseAdvancement {
@LazyValue
private AdvancementWrapper wrapper;
public PercentageAdvancement(@NotNull String key, @NotNull AdvancementDisplay display, @NotNull Advancement parent) {
super(key, display, parent);
}
public PercentageAdvancement(@NotNull String key, @NotNull AdvancementDisplay display, @NotNull Advancement parent, @Range(from = 1, to = Integer.MAX_VALUE) int maxProgression) {
super(key, display, parent, maxProgression);
}
@Override
@NotNull
public AdvancementWrapper getNMSWrapper() {
if (wrapper != null) {
return wrapper;
}
try {
return wrapper = AdvancementWrapper.craftBaseAdvancement(key.getNMSWrapper(), parent.getNMSWrapper(), display.getNMSWrapper(this), 100);
} catch (ReflectiveOperationException e) {
throw new RuntimeException(e);
}
}
@Override
public void onUpdate(@NotNull TeamProgression teamProgression, @NotNull Map<AdvancementWrapper, Integer> addedAdvancements) {
if (isVisible(teamProgression)) {
addedAdvancements.put(getNMSWrapper(), (getProgression(teamProgression) * 100) / maxProgression);
}
}
}
Hey.. So I noticed my client to have micro stutters everytime an advancements updates / progress changes..
It's very subtle but I'm prone to be annoyed by micro stutters so I noticed it. To be sure I also looked at my F3 menu with debug charts enabled:
As seen "scheduledExecutables" spikes everytime I get an update for the advancements. Is there any way I can avoid this? I have some advancements that require progress increments pretty much every 5 seconds, or for example when shooting a bow etc.