Closed kaiquyricardo closed 1 year ago
@SrMinister States must be created before view initialization, onRender
is called after view initialization. Move the paginationState
to class top level as a final
value
private final State<Pagination> paginationState = paginationState(
(context) -> listFriends(context.getPlayer()),
(item, friend) -> item.withItem(new ItemBuilder(Material.SKULL_ITEM).name("").build())
);
@Override
public void onInit(ViewConfigBuilder config) {
config.title("Lista de amigos")
.size(6)
.layout(
" ",
" OOOOOOO ",
" OOOOOOO ",
" ",
" ",
" ")
.cancelOnClick();
}
private List<Friends> listFriends(Player player) {
return plugin.getUserCache().getByName(player.getName()).getFriends();
}
Did you remove the context in the new update?
-> (context) -> Lists.newArrayList(AnimatedHeadsType.values()) not exist context
private final State<Pagination> paginationState = paginationState(
(context) -> Lists.newArrayList(AnimatedHeadsType.values()),
(context, item, index, animatedHeadsType) -> item.withItem(
new ItemBuilder(Material.SKULL_ITEM)
.texture(animatedHeadsType.getTexture())
.name(animatedHeadsType.getName())
.lore(
"§7Altere seu chapéu animado",
"§7para ficar no estilo.",
"",
"§aClique para alterar.")
.addFlag(ItemFlag.values())
.build()
).onClick(click -> {
final Player clicker = click.getPlayer();
final User user = userState.get(click);
AnimatedHeadsTask.stop(clicker);
AnimatedHeadsTask.startTask(clicker, animatedHeadsType);
MessageProvider.ORB_PICKUP.sendMessage(
clicker,
"§e§lGG! §eVocê acaba de selecionar o chapéu animado " +
animatedHeadsType.getName() +
"§e!"
);
user.setAnimatedHeads(animatedHeadsType);
user.setBanner(null);
user.setHeads(null);
user.setArmors(null);
clicker.getInventory().setChestplate(new ItemStack(Material.AIR));
clicker.getInventory().setLeggings(new ItemStack(Material.AIR));
clicker.getInventory().setBoots(new ItemStack(Material.AIR));
click.closeForPlayer();
})
);
@SrMinister paginationState with Function-like as sourceProvider
parameter was removed. Use lazyPaginationState
instead
Is there a way to use the spawner parameter on the current page to identify it as a state on another page?
line -> Arrays.asList(Spawner.values()), (context, builder, i, spawner) -> {
line -> ImmutableMap.of("spawners", spawner)));
private final State<Pagination> paginationState = paginationState(
Arrays.asList(Spawner.values()),
(context, builder, i, spawner) -> {
final double balance = EconomyAPI.ECONOMY.getBalance(context.getPlayer());
Discount discount = discountState.get(context);
if (!context.getPlayer().hasPermission(spawner.getPermission())) {
builder.withItem(
new ItemBuilder(Material.BARRIER)
.name("§cGerador bloqueado")
.lore(
"§7Você não tem permissão para",
"§7adquirir este gerador.")
.build());
return;
}
double discountSet = (discount == null ? spawner.getCoin() : spawner.getCoin() - spawner.getCoin() * (discount.getDiscount() / 100));
int calc = (int) (discount == null ? balance / spawner.getCoin() : balance / discountSet);
if (discount != null) discount.add(spawner.getCoin());
builder.withItem(
new ItemBuilder(Material.SKULL_ITEM)
.texture(spawner.getTexture())
.name("§aGerador de " + spawner.getName())
.lore(
"§7Tenha a chance de receber",
"§7chaves e bosses ao matar.",
"",
" §fCusto:",
" §8∙ §2$§f" + NumberFormatter.format(discountSet) + " §7(" + NumberFormatter.format((discount == null ? 0 : discount.getDiscount())) + "§7%)",
"",
" §aDrops:",
" §a▎ §fNormal: §7" + spawner.getDrop(),
"",
" §a▴ §fVocê consegue comprar",
" §7" + NumberFormatter.format(calc) + " §fgeradores deste tipo.",
"",
"§fClique para adquirir.")
.build()
).onClick(click -> click.openForPlayer(StoreView.class,
ImmutableMap.of("spawners", spawner)));
});
@SrMinister Do you mean another view?
See Sharing data between views and Initial State on Wiki.
private final State<Spawner> spawnerState = initialState("spawners");
ERROR: [19:23:53] [Server thread/ERROR]: Could not pass event InventoryClickEvent to spigot-spawnershop v1.0 org.bukkit.event.EventException: null at org.bukkit.plugin.java.JavaPluginLoader$1.execute(JavaPluginLoader.java:302) ~[patched_1.8.8.jar:git-PaperSpigot-445] at co.aikar.timings.TimedEventExecutor.execute(TimedEventExecutor.java:78) ~[patched_1.8.8.jar:git-PaperSpigot-445] at org.bukkit.plugin.RegisteredListener.callEvent(RegisteredListener.java:62) ~[patched_1.8.8.jar:git-PaperSpigot-445] at org.bukkit.plugin.SimplePluginManager.fireEvent(SimplePluginManager.java:517) [patched_1.8.8.jar:git-PaperSpigot-445] at org.bukkit.plugin.SimplePluginManager.callEvent(SimplePluginManager.java:502) [patched_1.8.8.jar:git-PaperSpigot-445] at net.minecraft.server.v1_8_R3.PlayerConnection.a(PlayerConnection.java:1657) [patched_1.8.8.jar:git-PaperSpigot-445] at net.minecraft.server.v1_8_R3.PacketPlayInWindowClick.a(SourceFile:31) [patched_1.8.8.jar:git-PaperSpigot-445] at net.minecraft.server.v1_8_R3.PacketPlayInWindowClick.a(SourceFile:9) [patched_1.8.8.jar:git-PaperSpigot-445] at net.minecraft.server.v1_8_R3.PlayerConnectionUtils$1.run(SourceFile:13) [patched_1.8.8.jar:git-PaperSpigot-445] at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [?:1.8.0_362] at java.util.concurrent.FutureTask.run(FutureTask.java:266) [?:1.8.0_362] at net.minecraft.server.v1_8_R3.SystemUtils.a(SourceFile:44) [patched_1.8.8.jar:git-PaperSpigot-445] at net.minecraft.server.v1_8_R3.MinecraftServer.B(MinecraftServer.java:774) [patched_1.8.8.jar:git-PaperSpigot-445] at net.minecraft.server.v1_8_R3.DedicatedServer.B(DedicatedServer.java:378) [patched_1.8.8.jar:git-PaperSpigot-445] at net.minecraft.server.v1_8_R3.MinecraftServer.A(MinecraftServer.java:713) [patched_1.8.8.jar:git-PaperSpigot-445] at net.minecraft.server.v1_8_R3.MinecraftServer.run(MinecraftServer.java:616) [patched_1.8.8.jar:git-PaperSpigot-445] at java.lang.Thread.run(Thread.java:750) [?:1.8.0_362] Caused by: java.lang.NullPointerException at net.hyren.spawnershop.view.StoreView.item(StoreView.java:93) ~[?:?] at net.hyren.spawnershop.view.StoreView.onFirstRender(StoreView.java:51) ~[?:?] at net.hyren.spawnershop.view.StoreView.onFirstRender(StoreView.java:22) ~[?:?] at net.hyren.core.spigot.inventory.pipeline.PlatformRenderInterceptor.intercept(PlatformRenderInterceptor.java:16) ~[?:?] at net.hyren.core.spigot.inventory.pipeline.PlatformRenderInterceptor.intercept(PlatformRenderInterceptor.java:8) ~[?:?] at net.hyren.core.spigot.inventory.pipeline.PipelineContext.loop(PipelineContext.java:43) ~[?:?] at net.hyren.core.spigot.inventory.pipeline.PipelineContext.proceed(PipelineContext.java:53) ~[?:?] at net.hyren.core.spigot.inventory.pipeline.PipelineContext.execute(PipelineContext.java:59) ~[?:?] at net.hyren.core.spigot.inventory.pipeline.Pipeline.execute(Pipeline.java:112) ~[?:?] at net.hyren.core.spigot.inventory.PlatformView.renderContext(PlatformView.java:295) ~[?:?] at net.hyren.core.spigot.inventory.pipeline.PlatformOpenInterceptor.finishOpen(PlatformOpenInterceptor.java:54) ~[?:?] at net.hyren.core.spigot.inventory.pipeline.PlatformOpenInterceptor.intercept(PlatformOpenInterceptor.java:28) ~[?:?] at net.hyren.core.spigot.inventory.pipeline.PlatformOpenInterceptor.intercept(PlatformOpenInterceptor.java:12) ~[?:?] at net.hyren.core.spigot.inventory.pipeline.PipelineContext.loop(PipelineContext.java:43) ~[?:?] at net.hyren.core.spigot.inventory.pipeline.PipelineContext.proceed(PipelineContext.java:53) ~[?:?] at net.hyren.core.spigot.inventory.pipeline.PipelineContext.execute(PipelineContext.java:59) ~[?:?] at net.hyren.core.spigot.inventory.pipeline.Pipeline.execute(Pipeline.java:119) ~[?:?] at net.hyren.core.spigot.inventory.PlatformView.open(PlatformView.java:132) ~[?:?] at net.hyren.core.spigot.inventory.PlatformView.navigateTo(PlatformView.java:160) ~[?:?] at net.hyren.core.spigot.inventory.context.PlatformConfinedContext.openForPlayer(PlatformConfinedContext.java:25) ~[?:?] at net.hyren.core.spigot.inventory.context.PlatformRenderContext.openForPlayer(PlatformRenderContext.java:316) ~[?:?] at net.hyren.core.spigot.inventory.context.SlotClickContext.openForPlayer(SlotClickContext.java:150) ~[?:?] at net.hyren.spawnershop.view.SpawnersView.lambda$null$0(SpawnersView.java:67) ~[?:?] at net.hyren.core.spigot.inventory.component.ItemComponent.clicked(ItemComponent.java:204) ~[?:?] at net.hyren.core.spigot.inventory.component.PaginationImpl.clicked(PaginationImpl.java:634) ~[?:?] at net.hyren.core.spigot.inventory.pipeline.ItemClickInterceptor.intercept(ItemClickInterceptor.java:35) ~[?:?] at net.hyren.core.spigot.inventory.pipeline.ItemClickInterceptor.intercept(ItemClickInterceptor.java:14) ~[?:?] at net.hyren.core.spigot.inventory.pipeline.PipelineContext.loop(PipelineContext.java:43) ~[?:?] at net.hyren.core.spigot.inventory.pipeline.PipelineContext.proceed(PipelineContext.java:53) ~[?:?] at net.hyren.core.spigot.inventory.pipeline.PipelineContext.execute(PipelineContext.java:59) ~[?:?] at net.hyren.core.spigot.inventory.pipeline.Pipeline.execute(Pipeline.java:119) ~[?:?] at net.hyren.core.spigot.inventory.IFInventoryListener.onInventoryClick(IFInventoryListener.java:57) ~[?:?] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_362] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_362] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_362] at java.lang.reflect.Method.invoke(Method.java:498) ~[?:1.8.0_362] at org.bukkit.plugin.java.JavaPluginLoader$1.execute(JavaPluginLoader.java:300) ~[patched_1.8.8.jar:git-PaperSpigot-445] ... 16 more
@SrMinister I'll take a look to find the cause of that NullPointerException
@SrMinister By default, the data is not transitioned entirely throughout the stream, that is, opening a screen with A initial data and navigating to B without declaring all data explicitly via openForPlayer
, the data from A will not be accessible from B. I I will add an option to make this the default behavior. This is the cause of your error.
You can create a temporary workaround for this replicating the current data using context.getInitialData()
Map<String, Object> data = new HashMap<>();
data.put("spawners", spawner);
data.putAll((Map<String, Object>) click.getInitialData());
click.openForPlayer(StoreView.class, data);
I saw that you updated the api, is it now possible to do this instead of creating a map? If so, could you explain it to me using the previous question?
I saw that you updated the api, is it now possible to do this instead of creating a map? If so, could you explain it to me using the previous question?
@SrMinister This change was not planned to v3.0.0, will be available in v3.0.1 or v3.1.0 :pray:
I cancel the click but I can't move the item in my inventory to drag it to slot 11 where the material is changed, in the past in previous libs I only had to activate the cancel click and nothing else, if I didn't want to drag it so, just add cancelOnClickPickup.
@RequiredArgsConstructor
public class EditWarpView extends View {
private final EssentialsPlugin plugin;
private final State<Warp> warpState = initialState("warp");
@Override
public void onInit(@NotNull ViewConfigBuilder config) {
config.title("Edição ▶ Warp · ")
.cancelOnClick();
}
@Override
public void onOpen(@NotNull OpenContext open) {
final Warp warp = warpState.get(open);
open.modifyConfig()
.title("Edição ▶ Warp · " + warp.getId()
);
}
@Override
public void onFirstRender(@NotNull RenderContext render) {
final Warp warp = warpState.get(render);
render.slot(
10,
new ItemBuilder(
Material.COMMAND
).name(
"§eAlterar nome"
).lore(
"§7Aqui você poderá alterar.",
"§7o nome da warp.",
"",
" §eInformações:",
" §fNome: §7" + (warp.getName() != null ? warp.getName() : "§c???"),
"",
"§fBotão esquerdo: §7Alterar nome",
""
).build()
).onClick(click -> {
final Player player = click.getPlayer();
MessageProvider.CLICK.sendMessage(
player,
"",
"§e Informe no chat o ´NOME` da warp.",
"§7 Para cancelar, digite ´§8cancelar§7´.",
""
);
click.closeForPlayer();
new ChatMonitor(player.getUniqueId(), messageOne -> {
warp.setName(colorize(messageOne));
MessageProvider.ORB_PICKUP.sendMessage(
player,
"§e§lGG! §eNome alterado com sucesso!"
);
plugin.getWarpFactory().addName(plugin, warp);
click.update();
click.openForPlayer(
EditWarpView.class,
Collections.singletonMap(
"warp",
warp
));
});
});
render.slot(
11,
new ItemBuilder(
warp.getIcon() != null ? warp.getIcon().clone() : new ItemStack(Material.BARRIER)
).name(
"§eAlterar ícone"
).lore(
"§7Aqui você poderá alterar.",
"§7o ícone da warp.",
"",
" §eInformações:",
" §fÍcone: §7" + (warp.getIcon() != null ? warp.getIcon().getType().name() : "§c???"),
"",
"§fArraste o ítem: §7Alterar ícone",
""
).build()
).onClick(click -> {
final Player player = click.getPlayer();
final ItemStack cursor = player.getItemOnCursor().clone();
if (cursor == null || cursor.getType() == Material.AIR) {
MessageProvider.ERROR.sendMessage(
player,
"§c§lEPA! §cVocê precisa arrastar um ítem para alterar o ícone."
);
return;
}
warp.setIcon(cursor);
click.update();
MessageProvider.ORB_PICKUP.sendMessage(
player,
"§e§lGG! §eÍcone alterado com sucesso!"
);
plugin.getWarpFactory().addIcon(plugin, warp);
});
render.slot(
12,
new ItemBuilder(
Material.EMPTY_MAP
).name(
"§eAlterar coordenadas"
).lore(
"§7Aqui você poderá alterar.",
"§7a coordenada da warp.",
"",
" §eInformações:",
" §fCoordenadas: §7" + (warp.getLocation() != null ? getFormattedText(LocationSerializer.fromString(warp.getLocation())) : "§c???"),
"",
"§fBotão esquerdo: §7Alterar localização",
""
).build()
).onClick(click -> {
final Player player = click.getPlayer();
val location = LocationSerializer.serialize(player.getLocation(), true);
warp.setLocation(location);
plugin.getWarpFactory().addLocation(plugin, warp);
MessageProvider.ORB_PICKUP.sendMessage(
player,
"§e§lGG! §eCoordenada alterada com sucesso!"
);
click.update();
click.openForPlayer(
EditWarpView.class,
ImmutableMap.of(
"warp",
warp
));
});
render.slot(
14,
new ItemBuilder(
Material.HOPPER
).name(
"§eAlterar slot"
).lore(
"§7Aqui você poderá alterar.",
"§7o slot da warp.",
"",
" §eInformações:",
" §fSlot: §7" + (warp.getSlot() != 0 ? warp.getSlot() : "§c???"),
"",
"§fBotão esquerdo: §7Alterar slot",
""
).build()
).onClick(click -> {
final Player player = click.getPlayer();
MessageProvider.CLICK.sendMessage(
player,
"",
"§a Informe no chat o ´SLOT´ da warp.",
"§7 Para cancelar, digite ´§8cancelar§7´.",
""
);
click.closeForPlayer();
new ChatMonitor(player.getUniqueId(), messageOne -> {
warp.setSlot(Integer.parseInt(messageOne));
MessageProvider.ORB_PICKUP.sendMessage(
player,
"§e§lGG! §eSlot alterado com sucesso!"
);
plugin.getWarpFactory().addSlot(plugin, warp);
click.update();
click.openForPlayer(
EditWarpView.class,
ImmutableMap.of(
"warp",
warp
));
});
});
render.slot(
15,
descriptionItem(warp)
).onClick(click -> {
final Player player = click.getPlayer();
if (click.isLeftClick()) {
MessageProvider.CLICK.sendMessage(
player,
"",
"§E Informe no chat o ´LORE` da warp.",
"§7 Para cancelar, digite ´§8cancelar§7´.",
""
);
click.closeForPlayer();
new ChatMonitor(player.getUniqueId(), messageOne -> {
warp.getLore().add(colorize(messageOne));
MessageProvider.ORB_PICKUP.sendMessage(
player,
"§e§lGG! §eLore adicionada com sucesso!"
);
plugin.getWarpFactory().addLore(plugin, warp);
click.update();
click.openForPlayer(
EditWarpView.class,
ImmutableMap.of(
"warp",
warp
));
});
return;
}
if (click.isRightClick()) {
plugin.getWarpFactory().removeLore(plugin, warp);
MessageProvider.ORB_PICKUP.sendMessage(
player,
"§e§lGG! §eLore removida com sucesso!"
);
click.update();
}
});
}
private ItemStack descriptionItem(Warp warp) {
val builder = new ItemBuilder(
Material.PAPER
).name(
"§eAlterar descrição"
).lore(
"§7Aqui você poderá alterar.",
"§7a lore da warp.",
"",
" §eInformações:"
);
plugin.getWarpFactory().getLore(plugin, warp.getId()).forEach(builder::addLore);
return builder.addLore(
"",
"§fBotão esquerdo: §7Adicionar lore",
"§fBotão direito: §7Remover lore",
""
).build();
}
private static String colorize(String text) {
return text.replace("&", "§");
}
}
@SrMinister Please open a separate issue for this issue https://github.com/DevNatan/inventory-framework/issues/441#issuecomment-1739637918 so we can track it and resolve it better
I saw that you updated the api, is it now possible to do this instead of creating a map? If so, could you explain it to me using the previous question?
@SrMinister Fixed in v3.0.1.
You must enable a transitiveInitialData
option in your ViewFrame/View configuration
Enable it globally
viewFrame.defaultConfig(config -> config.transitiveInitialData(true));
Or per-view
config.transitiveInitialData(true);
@RequiredArgsConstructor public class FriendsView extends View {