Minecraft Bukkit - Custom GUI when right click on a villager - java

I'm making a [Bed Wars][1] plugin for my Minecraft server. Actually I have to make a custom villager shop.
I have made my GUI (with implements InventoryHolder). It's working with a commands. I have searched all over the Internet, but I have not found anything on a system that makes, when you right click on a villager (I know how to spawn it) it's is showing my GUI. What would be an idea for that?
edit : I tried to use PlayerInteractAtEntityEvent, i maked a class, register it and make this code :
#EventHandler
public void interactAtEntity(PlayerInteractAtEntityEvent e) {
if (e.getRightClicked() == ShopVillager.villager1) {
System.out.println("UwU");
Player player = e.getPlayer();
FastShop shop = new FastShop(player);
player.openInventory(shop.getInventory());
e.setCancelled(true);
return;
}
}
It show the gui like 0.2sec but after i close it and show the original trade gui, and i got the uwu in my console.

It depend of how you make the PNJ (villager).
Spawn PNJ as default entity
If you spawn it with world.spawnEntity, you can use default spigot event.
For example, with PlayerInteractAtEntityEvent, you can get the entity.
Spawn entity with Packet
Personnally, I used packet to detect PacketPlayInUseEntity and get villager with the ID.
Globally, with multiple interact event and by checking location/nearest PNJ, you will be able to find the which one you are looking for.

If you want to have greater versatility and use things other than villagers, consider using the Citizens2 API, which lets you easily spawn entities and attach traits to them.
https://wiki.citizensnpcs.co/API
Adding Citizens to your Maven project
<repository>
<id>everything</id>
<url>https://repo.citizensnpcs.co/</url>
</repository>
<dependency>
<groupId>net.citizensnpcs</groupId>
<artifactId>citizens-main</artifactId>
<version>VERSION</version>
<type>jar</type>
<scope>provided</scope>
</dependency>
Custom Shop NPC
You can spawn an NPC, and attach a custom Trait to it. Here's how I implemented it in a minigame I made:
public class ItemShopTrait extends Trait
{
public ItemShopTrait()
{
super("itemshoptrait");
}
#EventHandler
public void rightClick(net.citizensnpcs.api.event.NPCRightClickEvent rightClickEvent)
{
if (rightClickEvent.getNPC().equals(this.getNPC()))
{
this.openShop(rightClickEvent.getClicker());
}
}
#EventHandler
public void leftClick(net.citizensnpcs.api.event.NPCLeftClickEvent leftClickEvent)
{
if (leftClickEvent.getNPC().equals(this.getNPC()))
{
this.openShop(leftClickEvent.getClicker());
}
}
public void openShop(Player player)
{
// Open shop inventory, etc.
}
}
And then to spawn the NPC and attach the trait:
Location shopLocation = /* Location where you want the NPC to spawn */;
// shopList is an ArrayList of usernames that have skins you want to use. This randomly chooses one of the skins from the list.
Random random = new Random();
String randomName = MapBase.shopList.get(random.nextInt(shopList.size()));
// EntityType.PLAYER can be changed to whatever EntityType you want, like a VILLAGER
// "Shop" is the name of the NPC
NPC npc = CitizensAPI.getNPCRegistry().createNPC(EntityType.PLAYER, "Shop");
// Sets the NPC's skin to always stay the same
npc.data().setPersistent(NPC.PLAYER_SKIN_UUID_METADATA, randomName);
// Add the right/left click traits to the NPC
npc.addTrait(new ItemShopTrait());
// No capes
SkinLayers trait = npc.getTrait(SkinLayers.class);
trait.hideCape();
trait.setVisible(SkinLayers.Layer.CAPE, false);
// Spawn the NPC in the world
npc.spawn(shopLocation);

I just go on github and i have explore a lot of bedwars plugin code, and i find !!!
I just need to use : PlayerInteractEntityEvent
Thats it

Related

How can I get the player that opens a crafting table in a Fabric mod?

How can I get the player that opens a crafting table in a Fabric mod?
My current code to get inventory title/type
#Mixin(HandledScreens.class)
public class FastCraftMixin {
#Inject(at = #At("HEAD"), method = "open")
private static <T extends ScreenHandler> void open(ScreenHandlerType<T> type, MinecraftClient client, int id, Text title, CallbackInfo ci) {
System.out.println(title.toString());
}
}
You can use the client object to get player.
You can use client.player.
In some version, it's mcPlayer object.
There is only one MinecraftClient object and that class only exists on the client. Only one player can be playing on a client. If you're writing a function that has a MinecraftClient parameter then you know the player is the player. You could get it with client.player (as already mentioned) but you should also be aware that on clients, you can also use MinecraftClient.getInstance().player since there is only one.

Libgdx updating a label in a table

Having an issue with tables and updating a label! Here is the dilemma, I have a sell button in my game that is updating the player's coins whenever they sell an item, that part is working perfectly. The issue I am having is trying to get the coin value to update on the screen while there in this separate menu (see pic attached, coins in the top left). The problem is that the coin value is in another stage in another class. This is because I have different tables that pop up in the middle when I click the different buttons at the bottom. I have tried helper methods for going in and clearing that table and updating it and then sending me back to this item page but it is not working, I can post any code needed but this is more of a general question on how to update a label within a table in a stage.
Update: So to kinda sum up my question, I have a Screen and I have have three tables in it the bottom table the top left and the top right. Then I add the table to the stage in the middle when they press the inventory or shop button etc. What I am looking to do is to keep the item page open and simply just update the value of the Coin label, I know I can change the text using .setText(); Im just not sure how I can update that portion of the screen etc..
Update 2: If I just set the screen back to a new screen of this screen it updates the coin value but then I am not on the item page anymore which is not ideal.
Update 3: Thanks for the help so far guys, #John your answer is super helpful aswell. Im still not getting this working though here is a little bit of the code where the label is being handled.
playerCoinLabel = new Label(playerSave.getCoinsString(),skin,"defaultMiddle");
This is where it is getting added to the table.
tableLeft = new Table(skin);
stage.addActor(tableLeft);
tableLeft.setBounds(0,0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
tableLeft.setFillParent(true);
tableLeft.top().left();
tableLeft.add(healthNonButton).size(84,80).left().padLeft(10).padTop(5);
tableLeft.add(playerHealthLabel).left().padLeft(15);
tableLeft.row();
tableLeft.add(levelNonButton).size(74,70).center().padLeft(10);
tableLeft.add(playerLevelLabel).left().padLeft(19);
tableLeft.row();
tableLeft.add(coinNonButton).size(74,70).center().padLeft(10);
tableLeft.add(this.playerCoinLabel).left().padLeft(15); //This line
tableLeft.row();
Then I have this method for updating my label using the setText like you guys were telling me about.
public void updatePlayerCoins() {
playerCoinLabel.setText(playerSave.getCoinsString());
}
and if I call this method anywhere, render() or where im setting the new coin value it is not updating/changing the label in the top left of my screen. I can post all the code to a github if I need to just posted the things involving the label. This is just a project im working on to increase my skill set so sorry if I sound amateur, it is because I am!
Thanks everyone!
It seems like you're asking two things- how do I update a label? and How do I structure my code? It's hard to tell what's going wrong with the former since we can't see your code, but #Tenfour04 is right- you want to retain a reference to the label somewhere and call setText() when you want to change the amount.
As far as structuring your code, I would suggest a simple OOP design and then evolve it like so:
First, we need an object to represent the player:
class Player {
private int coins; // Pretend there are getters / setters.
private int health;
private int level;
}
Now you probably have more than one way that you want to represent this player information, so we'll split the rendering code into a separate class or set of classes:
class StatWidget {
private Stage stage;
private Player player;
private Label lblCoins;
public StatWidget(Player player) { // Pseudo-code
this.player = player;
this.stage = new Stage();
Table tbl = new Table();
this.lblCoins = new Label(); // Notice we keep a reference to the label
tbl.add( this.coins );
}
public void update() {
lblCoins.setText(player.getCoins());
}
}
Now you can sync the UI with your player object's state simply by calling Player#update(). But when do you call it?
You could call update() in your render method. This is a little inefficient because you're updating the object whether it needs to be updated or not, but it's dead simple, and if you're only updating a few UI elements this way it probably doesn't matter. Personally, I'd stop here.
If you want to be more precise, you would only call update() when you actually make a change to the Player's coins. You can do this by finding the places in your code where you set the player's coins and add the update call like so:
player.setCoins( A_LOT_OF_MONEY );
statWidget.update();
Problem is this gets more cumbersome as you add more widgets- all your game logic now has to know about StatWidget and make calls to it. We could cut this dependency a little bit by using an event-driven architecture. Essentially, whenever player's state changes, it would send an event to interested parties notifying them of the change. You could use the pseudo-code below:
interface Publisher {
void subscribe(Subscriber subby);
void unsubscribe(Subscriber subby);
}
class Player implements Publisher {
private List<Subscriber> subscribers;
private int coins;
// ...
public void setCoins(int amount) {
this.coins = amount;
for(Subscriber subscriber : subscribers) subscriber.notify("COINS", amount);
}
public void subscribe(Subscriber subby) {
this.subscribers.add(subby);
}
public void unsubscribe(Subscriber subby) {
this.subscribers.remove(subby);
}
}
interface Subscriber {
void notify(String event, int qty);
void dispose();
}
class StatWidget implements Subscriber {
private Publisher player;
private Label label;
// ...
public StatWidget(Player player) {
this.player = player;
this.player.addSubscriber(this);
void notify(String event, int qty) {
if(event.equals("COINS")) label.setText(qty);
}
void dispose() {
this.player.unsubscribe(this);
}
}
The event system above could certainly be polished, and you could likely do clever things with generics (or use a library that has thought all this out for your), but hopefully it illustrates the concepts.

How to set a single entity invisible to a player?

After much research and much time wasted, I still can't find out how to hide an entity to a player.
What I'm trying to do is create a disguise command. I've now gotten everything worked out, except the issue is that the entity is still visible, and once stationary you can't interact with anything because the mob's hitbox is in the way. I want to hide the entity from the player so that you can do this. I know with players you can use Player#hidePlayer(), but this does not work with entities. I've tried using solutions such as this, but it gave an error while following the example. (And many things were depreciated, so I assumed it was out of date. I'm using Spigot 1.11.2). Any help would be very much appreciated.
PS: If you're wondering why I don't just use an already made plugin, it's because none of them work from what I've found.
To accomplish what you want, you must use packets to cancel what the player sees.
I strongly recommend ProtocolLib, have it in your server and use in your plugin.
Bearing that in mind, Bukkit user Comphenix has developed a class for protocollib to hide entities. You can find it in github.
Comphenix also provides an example of usage, as you can see below:
public class ExampleMod extends JavaPlugin {
private EntityHider entityHider;
private static final int TICKS_PER_SECOND = 20;
#Override
public void onEnable() {
entityHider = new EntityHider(this, Policy.BLACKLIST);
}
#Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
if (sender instanceof Player) {
final Player player = (Player) sender;
final Sheep sheep = player.getWorld().spawn(player.getLocation(), Sheep.class);
// Show a particular entity
entityHider.toggleEntity(player, sheep);
getServer().getScheduler().scheduleSyncDelayedTask(this, new Runnable() {
#Override
public void run() {
entityHider.toggleEntity(player, sheep);
}
}, 10 * TICKS_PER_SECOND);
}
return true;
}
}

Managing Scene2d, libgdx

I'm making a simple point&click game using libGdx and their Scene2d. Now, when I enter a location my Stage is cleared and new Actors are beeing attached. It doesnt feel right and its not efficient.
Can I make all Actors at the begining (except backgrounds, I will load them when entering a location), add them to Stage and associate them with locations, so the Stage would know witch to draw?
My only idea was to check that in draw and act methods of every actor, but that would mean houndreds of checks in a loop. Maybe Scene2d got something to help me out? Or maybe there is another way to do it?
My only idea was to check that in draw and act methods of every actor, but that would mean houndreds of checks in a loop.
Yes, that will be inneficient, and above all, a hell to maintain.
Now, when I enter a location my Stage is cleared and new Actors are beeing attached.
This is where your problem is, you're not using scene2D as it should be IMHO. I hope you're up for an intense architecture & code refactoring session.
When entering a new location, you should be entering a new stage.
So first, you should have several stages :
class MainMenu extends Stage {
public MainMenu(){
// Add buttons to play or quit the game
}
}
class PointNClickStage extends Stage {
// Add stuff common to all point'n click stages such as an inventory display
}
class Island extends PointNClickStage {
public Island (){
// Add some palm trees and an hidden chest
}
}
class PirateShip extends PointNClickStage {
public PirateShip(){
// Add some pirates and their ship
}
}
... etc
Then in your application listener, you should implement a way to change the current stage being rendered. Conceptually, this is often called a "scene/stage director". Some scene-based frameworks, such as Cocos2D provides their own scene director, but libgdx doesn't currently. So, you have to implement this mechanism by yourself and here is a very basic example to help you get the gist of it :
public MyApp extends ApplicationAdapter {
private Stage currentStage;
private static MyApp instance;
// ...
#Override
public void create () {
instance = this;
MyApp.setStage(new MainMenu()); // The game begins in the main menu
}
#Override
public void render () {
Gdx.gl.glClearColor(0.15f, 0.1f, 0.15f, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
currentStage.act();
currentStage.draw();
}
public static void setStage(Stage stage){
instance.currentStage = stage;
Gdx.input.setInputProcessor(stage); // Important ;)
}
// ...
}
So that to change the location (current stage) you will only have to do :
MyApp.setStage(new PirateShip())
Then, if you don't want to recreate a new stage every time you change your location, you may initialize and keep a reference on them somewhere so that you will be able to change the location like that for example.
MyApp.setStage(some_list_containing_initialized_stage.get(id))
Alternatively, you may also look into this libgdx extension that provides scene2d utils classes such as a scene director, and transitions that may be useful for you if you don't want to reinvent the wheel later.

Looking for an appropriate design pattern

I have a game that tracks user stats after every match, such as how far they travelled, how many times they attacked, how far they fell, etc, and my current implementations looks somewhat as follows (simplified version):
Class Player{
int id;
public Player(){
int id = Math.random()*100000;
PlayerData.players.put(id,new PlayerData());
}
public void jump(){
//Logic to make the user jump
//...
//call the playerManager
PlayerManager.jump(this);
}
public void attack(Player target){
//logic to attack the player
//...
//call the player manager
PlayerManager.attack(this,target);
}
}
Class PlayerData{
public static HashMap<int, PlayerData> players = new HashMap<int,PlayerData>();
int id;
int timesJumped;
int timesAttacked;
}
public void incrementJumped(){
timesJumped++;
}
public void incrementAttacked(){
timesAttacked++;
}
}
Class PlayerManager{
public static void jump(Player player){
players.get(player.getId()).incrementJumped();
}
public void incrementAttacked(Player player, Player target){
players.get(player.getId()).incrementAttacked();
}
}
So I have a PlayerData class which holds all of the statistics, and brings it out of the player class because it isn't part of the player logic. Then I have PlayerManager, which would be on the server, and that controls the interactions between players (a lot of the logic that does that is excluded so I could keep this simple). I put the calls to the PlayerData class in the Manager class because sometimes you have to do certain checks between players, for instance if the attack actually hits, then you increment "attackHits".
The main problem (in my opinion, correct me if I'm wrong) is that this is not very extensible. I will have to touch the PlayerData class if I want to keep track of a new stat, by adding methods and fields, and then I have to potentially add more methods to my PlayerManager, so it isn't very modulized.
If there is an improvement to this that you would recommend, I would be very appreciative. Thanks.
I am not at all an expert in design patterns. But this is what I think might be useful:
To add actions to the player, you might wanna look at the Strategy Pattern. Just google for it and you will get lot of examples.
Here is an attempt by me:
For updating the player stats, I guess Observer Pattern will be helpful.
The Observer Pattern defines one-to-many dependency between objects so
that when one object changes state, all of its dependents are notified
and updated automatically.
It enforces loose coupling so that future changes are easy.
(You will have to read about Observer Pattern and also will have to see some examples. It is not as straight forward as Strategy.)
Due to the fact that you said you want to be able to add new stats and actions later, I would tend to make a stats object that doesn't need to know anything about the game it's recording. The advantage is that the Stats class would never need to change as you added new features.
public interface Stats {
void incrementStat(Object subject, String stat);
int getStat(Object subject, String stat);
}
You Player implementation would look something like:
public void jump() {
// Logic to make the player jump...
stats.incrementStat(this, "jump");
}
Of course, what you're trading for that flexibility is static type-checking on those increment methods. But in cases like this I tend to think the simplicity is worth it. In addition to removing tons of boiler plate from the PlayerData and PlayerManager classes, you also end up with a reusable component, and you can get rid of the cyclic dependency between PlayerManager and Player.

Categories