Is there something wrong in my Minecraft plugin? - java

This code doesn't work. Wonder, where I went wrong.
public class Basic extends JavaPlugin {
#EventHandler
public void onPlayerJoin (PlayerJoinEvent evt) {
Player player = evt.getPlayer();
PlayerInventory inventory = player.getInventory();
ItemStack itemstack = new ItemStack(Material.STICK,1);
if (player.hasPermission("lobby.lobby")) {
player.setHealth(0.5);
inventory.setItem(1,itemstack);
inventory.addItem(itemstack);
player.setWalkSpeed(3);
player.addPotionEffect(new PotionEffect(PotionEffectType.SPEED,9999, 1));
player.hidePlayer(player);
}
}
}
When I start my server, there are no errors in console. Everything is fine, but I don't get any items, no speed, no effects.

This could be any number of issues, and this is a poor question, but I would recommend adding a couple lines that print debug messages to the console, that way you know what parts of your code have run if any.
Most likely you do not have the permission node lobby.lobby, being an OP does not actually give you permission nodes. Get a permissions plugin such as Luck Perms and add the permission node to the default group or to yourself.

Related

Having Issues With onGuildMessageReceived() When Trying to Add Reactions

I'm trying to make the bot I'm coding react on a user's message when it has specific keywords in it. I have about 50 keywords that the bot can react to, but only if they are at the start of the message.
The bot will react with an emote when it's at the start of the user's message but not when it's after the first word.
I've already tried asking the discord for some help but it's pretty apparent that they don't really care to be friendly to newcomers. I've tried changing the argument from "0" to "Message.MAX_CONTENT_LENGTH" which didn't work. I also originally had an ArrayList that I converted into a String that didn't work, and later tried using just a normal List; with the same result. Right now I'm stuck with an extremely unoptimized if/else statement, but I can live with it. I just need it to work.
import net.dv8tion.jda.core.events.message.guild.GuildMessageReceivedEvent;
import net.dv8tion.jda.core.hooks.ListenerAdapter;
public class GuildMessageReceived extends ListenerAdapter {
public void onGuildMessageReceived(GuildMessageReceivedEvent event) {
String[] args = event.getMessage().getContentRaw().split("\\s+");
if (args[0].equalsIgnoreCase("zachary")) {
event.getMessage().addReaction("🕵").queue();
} // if
} // onGuildMessageReceived()
} // GuildMessageReceived
I expect the result to be a reaction on the message with the keyword located inside of it at any point, not just at the beginning. Assume that "money" is a keyword.
What I need:
[6:52 PM] Anon: I have money
|| Reactions: :spy:
What I get:
[6:52 PM] Anon: I have money
|| Reactions: None
Your code only reacts if the first message is a keyword because you're splitting by space and then only checking the first element of the array. Convert the array to an List and use contains(). For example:
List<String> words = Arrays.asList(event.getMessage().getContentRaw().split("\\s+"));
if (words.contains("zachary")) {
event.getMessage().addReaction("🕵").queue();
}
If you want to easily check for multiple keywords you can instead use Collections.disjoint(). For example:
Set<String> keywords = Set.of("foo", "bar", "baz");
List<String> words = Arrays.asList(event.getMessage().getContentRaw().split("\\s+"));
if (!Collections.disjoint(keywords, words)) {
event.getMessage().addReaction("🕵").queue();
}

How to choose the block that the item can be placed on?

I would like to know how to choose the block that my TNT be placed on. Here is my code.
ItemStack tnt = new ItemStack(Material.TNT, 1);
As in give #p tnt 1 0 {PlaceOn:emerald_block}.
I am using Spigot for Minecraft 1.12 and Eclipse.
There is no way to do that via the Spigot API natively, you need to use NMS and NBT:
net.minecraft.server.v1_12_R1.ItemStack stack = CraftItemStack.asNMSCopy(tnt);
NBTTagList tags = (NBTTagList) stack.getTag().get("CanPlaceOn");
if (tags == null)
tags = new NBTTagList();
tags.add(new NBTTagString("minecraft:emerald_block"));
stack.getTag().set("CanPlaceOn", tags);
ItemStack toUse = CraftItemStack.asCraftMirror(stack);
Generally speaking if you can avoid using NMS you should, and there is a pretty easy way to do this. Whenever a block is placed by a player, a BlockPlaceEvent is called by the server. If you are unsure how they work, look here: http://bukkit.gamepedia.com/Event_API_Reference.
An example of how to handle this behavior is below:
public void onBlockPlace(BlockPlaceEvent e) {
if (e.getBlockPlaced().getType() == Material.TNT) {
Material belowType = e.getBlockPlaced().getRelative(BlockFace.DOWN).getType();
// your code here...
}
}
This code allows you to check if the block that is placed is TNT, then it retrieves the type of the block directly below it.
Hope this helps!!

bukkit - Prevent player from running command when in combat

So I'm developing a Java Plugin and I need to do something like the KitPvP servers do these days, the player selects a kit, and then they are only allowed to get a kit again once they've died.
I've tried this using strings to check if the player is in command, but I really don't know what/"how" to do with them. Any suggestions?
You could use a list to check if the player has got the kit in "this life".
For example in your main plugin class or in your command class you could add a static member like this:
public static ArrayList<UUID> usedKit = new ArrayList<UUID>();
In the onCommand() method you can check if the player hasn't got his kit yet:
if (!usedKit.contains(player.getUniqueId())) {
// Code to give the kit here...
usedKit.add(player.getUniqueId()); // Adds the player to the list
} else
player.sendMessage("You already got your kit.");
return true;
When the player dies you have to remove him from the list:
#EventHandler
public void onPlayerDeath(PlayerDeathEvent event) {
if (usedKit.contains(event.getPlayer().getUniqueId()))
usedKit.remove(event.getPlayer().getUniqueId());
}
I know that this answer is similar to Kerooker's but you should try to use UniqueIds since you can change your name in minecraft.
What you can do is create a list containing the names of the players that have already used the kits
List<String> players = new ArrayList<String>();
Then whenever they use the command, you check if the player is inside your list
boolean isInList = players.contain(yourPlayer.getName());
You can check that when you handle the command
if (isInList) {
player.sendMessage("You must die to use this again!");
return true; //To commandExecutor
}
If the player is not in the list, add him to the list and give the kit
players.add(yourPlayer.getName());
//Give the kit
Whenever a player die, you should try to remove his name from the List.
#EventHandler
public void onDeath(PlayerDeathEvent e) {
//Remove player from the list
}
Note that inside a onCommand, you have the following attributes of a command: CommandSender sender, Command cmd, String label, String[] args.
The sender argument may be your player, and you can check that by
if (sender instanceof Player) {
Player commandPlayer = (Player) sender;
}
I assume that you use the Spigot API and you'r probably searching for something like this PlayerDeathEvent
This gets triggered everytime a Player dies and you can compare them with your Players list and update the permissions(bukkit) permission(spiggot).
Hopefully this answered your question.

Need to split a thread so it runs in multiple threads. Also need to figure out a synchronized issue - JAVA

This program is about showing the oldest, youngest ect person in a network.
I need to figure out how I can improve it, so I dont get the ConcurrentModificationException. I get this when I ask for displaying more of these multiple time, like asking for youngest, oldest, and make it refresh to tell me whos the current youngest.
public void randomIncreaseCoupling(int amount, double chance, double inverseChance) {
randomChangeCoupling(amount,chance,inverseChance,true);
}
public void randomDecreaseCoupling(int amount, double chance, double inverseChance) {
randomChangeCoupling(amount,chance,inverseChance,false);
This code is used in the network to randomly change the date outcome.
Also, I have this running in a Thread currently, but I need to fasten it, so I need to run each of the 'functions' to run in their own Thread.
The Class MainController is starting the Thread by:
public void startEvolution() {
if (display == null)
throw new Error("Controller not initialized before start");
evolutionThread = new NetworkEvolutionSimulator(network, display);
evolutionThread.start();
}
When I click on any button ex a button to show me the oldest in this network, it is done by:
public void startOldest() {
if (display == null)
throw new Error("Not properly initialized");
int order = display.getDistanceFor(Identifier.OLDEST);
Set<Person> oldest = network.applyPredicate(PredicateFactory.IS_OLDEST,
order);
display.displayData(Identifier.OLDEST, summarize(order, oldest));
I tried to make it like:
public void startOldest() {
if (display == null)
throw new Error("Not properly initialized");
int order = display.getDistanceFor(Identifier.OLDEST);
Set<Person> oldest = network.applyPredicate(PredicateFactory.IS_OLDEST,
order);
display.displayData(Identifier.OLDEST, summarize(order, oldest));
evolutionThread2 = new NetworkEvolutionSimulator(network, display);
evolutionThread2.start();
But this starts main thread over and over when I press the button. What I want is that this specific function and the others when I press the cercain button it has to start each of them in their own threads so I will be able to use more than one of them at a time. How shall I do this?
I can explain more if needed.
Thanks in advance.
My first post, so sorry if I didn't follow a specific rule.
You could use the synchronized keyword -
The synchronized keyword can be used to mark several types of code blocks:
Instance methods
Static methods
Code blocks inside instance methods
Code blocks inside static methods
Everywhere you're using your set oldest you could add a synchronized code block like this
synchronized(oldest) { ... }

How to use R model in java to predict with multiple models?

I have this constructor:
public Revaluator(File model,PrintStream ps) {
modelFile=model;
rsession=Rsession.newInstanceTry(ps, null);
rsession.eval("library(e1071)");
rsession.load(modelFile);
}
i want to load a model and predict with it.
the problem that Rsession.newInstanceTry(ps, null); is always the same session, so if i load another model, like:
Revaluator re1=new Revaluator(new File("model1.RData"),System.out);
Revaluator re2=new Revaluator(new File("model2.RData"),System.out);
Both re1 and re2 using the same model, since the var name is model, so only the last one loaded.
the evaluate function:
public REXP evaluate(Object[] arr){
String expression=String.format("predict(model, c(%s))", J2Rarray(arr));
REXP ans=rsession.eval(expression);
return ans;
}
//J2Rarray just creates a string from the array like "1,2,true,'hello',false"
i need to load about 250 predictors, is there a way to get every instance of Rsession as a new separated R Session?
You haven't pasted all of your code in your question, so before trying the (complicated) way below, please rule out the simple causes and make sure that your fields modelFile and rsession are not declared static :-)
If they are not:
It seems that the way R sessions are created is OS dependent.
On Unix it relies on the multi-session ability of R itself, on Windows it starts with Port 6311 and checks if it is still free. If it's not, then the port is incremented and it checks again, if it's free and so on.
Maybe something goes wrong with checking free ports (which OS are you working on?).
You could try to configure the ports manually and explicitly start different local R servers like this:
Logger simpleLogger = new Logger() {
public void println(String string, Level level) {
if (level == Level.WARNING) {
p.print("! ");
} else if (level == Level.ERROR) {
p.print("!! ");
}
p.println(string);
}
public void close() {
p.close();
}
};
RserverConf serverConf = new RserverConf(null, staticPortCounter++, null, null, null);
Rdaemon server = new Rdaemon(serverConf, this);
server.start(null);
rsession = Rsession.newInstanceTry(serverConf);
If that does not work, please show more code of your Revaluator class and give details about which OS you are running on. Also, there should be several log outputs (at least if the log level is configured accordingly). Please paste the logged messages as well.
Maybe it could also help to get the source code of rsession from Google Code and use a debugger to set a breakpoint in Rsession.begin(). Maybe this can help figuring out what goes wrong.

Categories