I am trying to develop a blacklist system for blocks for my server and this is how it should work: In the config.yml there are names of the materials of the blocks that are not allowed to be placed. Then a check is made for each placed block whether the material is contained in config.yml.
Here is my code:
package de.blocklog.blocklog;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.plugin.java.JavaPlugin;
import java.util.List;
public final class Main extends JavaPlugin implements Listener {
#Override
public void onEnable() {
// Plugin startup logic
}
#Override
public void onDisable() {
// Plugin shutdown logic
}
#EventHandler
public void onBlockPlace(BlockPlaceEvent event){
Block block = event.getBlock();
Material material = block.getType();
Player placer = event.getPlayer();
double x = block.getLocation().getX();
double y = block.getLocation().getY();
double z = block.getLocation().getZ();
List<String> bannedmats = this.getConfig().getStringList("banned-blocks");
for(World w : Bukkit.getWorlds()){
for(Player p : w.getPlayers()){
if(p.hasPermission("blocklogsystem.see") || p.hasPermission("blocklogsystem.*"))
p.sendMessage("[BLOCKLOG] Player " + placer.getDisplayName() + " placed " + material + " at X:" + x + " Y: " + y +" Z: "+ z);
if(material.name().equals(bannedmats))
p.sendMessage("[BLOCKLOG] Player " + placer.getDisplayName() + " placed an illegal " + material + " at X:" + x + " Y: " + y +" Z: "+ z);
}
}
}
}
But somehow it doesn't work :/
Yout need to register your Event in the onEnable Method like:
#Override
public void onEnable() {
// Plugin startup logic
Bukkit.getPluginManager().registerEvents(this, this);
}
To be fair, your provided information is a bit vague but I've recently implemented exactly this feature except with the banned blocks stored in memory as an ArrayList of Material objects.
Effectively what I do is make use of the .contains() method of an ArrayList object to check for presence of a given block in a list of blocks.
All this considered here is the basic run down, assuming you've already developed parsing your config.yml data into specifically an ArrayList of Material objects that looks something like this:
public static ArrayList<Material> PlacementBanned = new ArrayList<>();
{
PlacementBanned.addAll(Arrays.asList(Material.BARRIER, Material.COMMAND_BLOCK,
Material.CHAIN_COMMAND_BLOCK, Material.REPEATING_COMMAND_BLOCK, Material.COMMAND_BLOCK_MINECART,
Material.WATER, Material.LAVA, Material.STRUCTURE_BLOCK, Material.STRUCTURE_VOID));
}
Firstly, I highly recommend you use a separate class for the listener. like this:
Main
package myPlugin;
import myPlugin.myPackage.myListenerClass;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.java.JavaPlugin;
public class Main extends JavaPlugin {
public static Plugin instance;
#Override
public void onEnable() {
instance = this;
PluginManager pm = getServer().getPluginManager();
pm.registerEvents(new myListenerClass(), this);
}
}
myPackage.myListenerClass
package myPlugin.myPackage;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.event.Listener;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.block.BlockPlaceEvent;
public class myListenerClass implements Listener {
#EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = false)
public void onPlace(BlockPlaceEvent event) {
Block block = event.getBlockPlaced();
Material blockType = block.getType();
if (PlacementBanned.contains(blockType)) {
event.setCancelled(true);
return;
}
}
}
Note, LOWEST priority means it will be queued up in the first of 5 batches of all methods triggered by the listener in your code.
Related
My bot is stuck printing the output. I check and there was no problem with the logical part as I used the sane logic to make a normal java program. Please help as it is stuck printing the output in discord and I do not know how to solve it.
I also added some unnecessary print functions to find out where the error was. To my surprise, it was just in printing the message which is unusual as I have made bots before and none of them had any errors to just "print" messages.
import javax.security.auth.login.LoginException;
import net.dv8tion.jda.api.JDA;
import net.dv8tion.jda.api.JDABuilder;
import net.dv8tion.jda.api.OnlineStatus;
import net.dv8tion.jda.api.entities.Activity;
public class rpsidnfp {
public static JDA jda;
public static void main(String args[]) throws LoginException {
jda = JDABuilder.createDefault("(my token here)").build();
core2 core2obj = new core2();
jda.addEventListener(core2obj);
}
}
The former was my main class.
And below is the core class as it contains all the functions.
package pack.rpsidnfp;
import java.util.Random;
//import net.dv8tion.jda.api.entities.User;
import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
public class core2 extends ListenerAdapter {
public static String prefix = "!";
public void onGuildMessageReceived(GuildMessageReceivedEvent event) {
String input = event.getMessage().getContentRaw();
String[] options = {"rock", "paper", "scissors"};
Random robj = new Random();
int rnum = robj.nextInt(options.length);
System.out.println(rnum);
String conf = options[rnum];
event.getChannel().sendMessage(conf);
System.out.println(conf);
String same = prefix + conf;
String win = "congrats, you won!";
String lose = "lmao, you lost";
if(input.equals(same)) {
event.getChannel().sendMessage("we both kept the same thing");
}
else if(input.equals(prefix + options[0])) {
if(conf.equals(options[1])) {
event.getChannel().sendMessage(lose);
}
else if(conf.equals(prefix + options[2])) {
event.getChannel().sendMessage(win);
}
}
else if(input.equals(prefix + options[1])) {
if(conf.equals(options[0])) {
event.getChannel().sendMessage(win);
}
else if(conf.equals(options[2])) {
event.getChannel().sendMessage(lose);
}
}
else if(input.equals(prefix + options[2])) {
if(conf.equals(options[0])) {
event.getChannel().sendMessage(lose);
}
else if(conf.equals(options[2])) {
event.getChannel().sendMessage(win);
}
}
}
}
The sendMessage method returns a MessageAction. You need to call queue() on that RestAction instance.
Additionally, keep in mind that your bot receives its own messages so you should make sure it ignores those. You can add a if (event.getAuthor().isBot()) return; to the start of your listener method.
See Also:
Troubleshooting Guide: Nothing happens when using X
RestAction Guide
MessageListenerExample
JDA README
Hello people of the internet, I would like to know if there was a way to make a custom food item give you XP. I am in the middle of making a mod and would like "SimonApple" To give me XP. Please let me know if there is a way to do this.
package com.notsimon.blocksplus;
import cpw.mods.fml.common.Mod;
import cpw.mods.fml.common.Mod.EventHandler;
import cpw.mods.fml.common.event.FMLInitializationEvent;
import cpw.mods.fml.common.event.FMLPostInitializationEvent;
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
import cpw.mods.fml.common.registry.GameRegistry;
import net.minecraft.block.Block;
import net.minecraft.block.material.MapColor;
import net.minecraft.block.material.Material;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.item.Item;
import net.minecraft.item.ItemFood;
import net.minecraft.item.ItemStack;
#Mod(modid = "ep", name = "Experience Plus", version = "1.0")
public class ExperiencePlus {
public static Item SimonApple;
public static Item MagentaDust;
public static Block MagentaOre;
public static Block MagentaBlock;
#EventHandler
public void preInit(FMLPreInitializationEvent event) {
//Item/Block init and registering
//Config handling
//X * 0.5 = 20 Hunger
SimonApple = new ItemFood(10, 0.5F, false).setUnlocalizedName("SimonApple").setTextureName("bp:SimonApple").setCreativeTab(tabBlocksPlus);
MagentaOre = new BlockTable(Material.iron).setBlockName("MagentaOre").setBlockTextureName("bp:MagentaOre").setCreativeTab(tabBlocksPlus);
MagentaDust = new ItemTable().setUnlocalizedName("MagentaDust").setTextureName("bp:MagentaDust").setCreativeTab(tabBlocksPlus);
MagentaBlock = new MagentaBlock(Material.iron).setBlockName("MagentaBlock").setBlockTextureName("bp:MagentaBlock").setCreativeTab(tabBlocksPlus);
//item.itemTable and substring(5) removes "item."
GameRegistry.registerItem(SimonApple, SimonApple.getUnlocalizedName().substring(5));
GameRegistry.registerBlock(MagentaOre, MagentaOre.getUnlocalizedName().substring(5));
GameRegistry.registerItem(MagentaDust, MagentaDust.getUnlocalizedName().substring(5));
GameRegistry.registerBlock(MagentaBlock, MagentaBlock.getUnlocalizedName().substring(5));
GameRegistry.registerWorldGenerator(new OreGeneration(), 0);
}
#EventHandler
public void init(FMLInitializationEvent event) {
//Proxy, TileEntity, entity, GUI and Packet Registering
GameRegistry.addRecipe(new ItemStack(SimonApple, 2), new Object[]{"MMM","MBM","MMM", 'M', ExperiencePlus.MagentaDust, 'B', ExperiencePlus.MagentaBlock});
GameRegistry.addRecipe(new ItemStack(MagentaBlock), new Object[] {"MMM", "MMM", "MMM",'M', ExperiencePlus.MagentaDust});
}
#EventHandler
public void postInit(FMLPostInitializationEvent event) {
}
public static CreativeTabs tabBlocksPlus = new CreativeTabs("tabBlocksPlus"){
#Override
public Item getTabIconItem() {
return new ItemStack(MagentaOre).getItem();
}
};
}
You can't edit the current apple item in the game, you would have to create your own one as a forge mod item, which seems like what oyu have done. To make an item give XP, you use this:
player.addExperienceLevel(1); //player is an EntityPlayer or an EntityPlayerMP
SimonApple Item Class
This is what the item class for the SimonApple would look like (without imports):
public class SimonApple extends ItemFood {
private static final int LevelsToAdd = 10; //just an example number; play around with it
public SimonApple(String unlocalizedName, int healAmount, float saturationModifier, boolean wolvesFavorite, CreativeTab creativeTab) {
super(healAmount, saturationModifier, wolvesFavorite);
this.setUnlocalizedName(unlocalizedName);
this.setTextureName(Main.MODID + ":" + unlocalizedName);
this.setCreativeTab(creativeTab);
}
#Override
protected void onFoodEaten(ItemStack stack, World world, EntityPlayer player) {
super.onFoodEaten(stack, world, player);
player.addExperienceLevel(LevelsToAdd);
}
}
Changing Variables in the ExperiencePlus Class
You would need to change this:
public static Item SimonApple;
To something around the lines of this:
public static Item simonApple;
And you would need to change this:
SimonApple = new ItemFood(10, 0.5F, false).setUnlocalizedName("SimonApple").setTextureName("bp:SimonApple").setCreativeTab(tabBlocksPlus);
To just this:
simonApple = new SimonApple("SimonApple", 10, .5f, false, tabBlocksPlus);
NOTE: 10 should be the heal amount, and .5f should be the saturation amount (see table here)
Either create a new item as Abob78 suggests, or create an eventHandler that subscribes to the PlayerUseItem event to be triggered at the Finish state.
To limit the items that that trigger it, you'll have to look at using the itemstack NBT data to store a flag to identify "simon apples" from regular apples. this can be something as simple as a boolean flag such as "isSimonApple"
From the event, you should be able to extract an EntityLiving reference that can be cast to a player reference.
Then either augment the triggering player's XP or spawn XP orbs at their location.
I am trying to eliminate all the memory allocation during gameplay on my game and I have stuck to something strange that I never saw in the past, for some reason the use of instanceof is doing memory allocation on android, why is that?
This is the full code of OrangeFollower.java:
package enemies;
import game.ConcreteBodySystem;
import game.Tags;
import main.MainGame;
import player.Player;
import tools.Director;
import tools.FastMath;
import tools.Vector;
import tools.gColor;
import worldsystem.BlockCollitionSystem;
import worldsystem.Entity;
import worldsystem.IntervalSystem;
import worldsystem.SoundSystem;
import worldsystem.SpriteSystem;
import worldsystem.gWorld;
import com.badlogic.gdx.Gdx;
public class OrangeFollower extends Enemy {
public static int TAG=gWorld.getNextTag();
public OrangeFollower(final gWorld world) {
super(world);
this.tag =TAG;
initScale(0.8f,0.8f);
initColor(1,0.6f,0, 1);
initColScale(0.4f, 0.4f);
initSpeed(0.018f);
setGroups(Tags.GROUP_CONCRETE_ENEMIES,Tags.GROUP_DESTRACTABLE,Tags.GROUP_ENEMIE,Tags.GROUP_GREEN_ENEMIES,Tags.GROUP_MOVING);
SpriteSystem sm=(SpriteSystem) addSystem(new SpriteSystem(this, "sprites/sprites2.png",896,256,1,128,128,pos,scale,rotation,new gColor(1,1,1,1)));
addSystem(new ConcreteBodySystem(this));
addSystem(new EnemieSystem(this,2,20,false,true,false,false,Tags.GROUP_GREEN_ENEMIES){{multis=2;}});
addSystem(new BlockCollitionSystem(this,256,true){
#Override
public void colliding(Entity e) {
super.colliding(e);
if(e instanceof Generator)return;
Vector.vector.set(e.pos.x-pos.x, e.pos.y-pos.y);
float length = FastMath.sqrtBlazingFast(Vector.vector.x*Vector.vector.x + Vector.vector.y*Vector.vector.y);
if (length != 0) {
Vector.vector.x = Vector.vector.x / length;
Vector.vector.y = Vector.vector.y / length;
vel.x-=Vector.vector.x;
vel.y-=Vector.vector.y;
}
}
});
}
#Override
public void init() {
super.init();
speed=realSpeed;
}
#Override
public void update() {
super.update();
pos.x += (vel.x * speed) * Director.delta;
pos.y += (vel.y * speed) * Director.delta;
}
}
The class is initialized for the first time.
An inner class is not necessarily initialized when the outer class is. Again the java reference says: first use.
Memory allocation not only happens with new at the object instantiations, but also at the ClassLoaders.
What happens on Android is yet another affair, but fortunately Google still keeps close to processing model of the official JVMs.
As extracted from comments by #VinceEmigh, #SteveL, #fge.
So basically what I am trying to do is make it so every player has their own extra storage bag that they can upgrade(starting on that later), but at the moment I am stuck with this. I am making it so if the Hashmap "storage" does not contain a value, to create a new inventory and set it a value. The only problem is I cannot then use the inventory "bag" in another if statement to open it when the value is set. Here is my code :
package me.impatheimpaler.aqw;
import java.util.HashMap;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.block.Action;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.inventory.Inventory;
public class Storage implements Listener{
public me.impatheimpaler.aqw.Main plugin;
public HashMap<String, Inventory> storage = new HashMap<String, Inventory>();
public Storage(Main main) {
plugin = main;
}
#EventHandler
public void onInteract(PlayerInteractEvent e) {
if (!(e.getItem().getType() == Material.CHEST)) return;
if (!(e.getAction() == Action.RIGHT_CLICK_AIR || e.getAction() == Action.RIGHT_CLICK_BLOCK)) return;
if (e.getItem().getItemMeta().hasLore() &&
e.getItem().getItemMeta().getLore().contains(ChatColor.GREEN + "A bag for extra storage.")) {
if (storage.containsKey(null) && storage.containsValue(null)) {
Inventory bag = Bukkit.getServer().createInventory(e.getPlayer(), 9, "Storage");
storage.put(e.getPlayer().getName(), bag);
}
if (storage.contains(e.getPlayer().getName(), bag)) {
//Here is the error, as I cannot use the value "bag", because it cannot be
accessed from another if statement.
}
}
}
}
You could just declare bag outside of the if statement, then set it inside of the statement:
Inventory bag;
if(storage.containsKey(null) && storage.containsValue(null)){
//code
}
So, it could look something like this:
Inventory bag;
if (storage.containsKey(null) && storage.containsValue(null)) {
bag = Bukkit.getServer().createInventory(e.getPlayer(), 9, "Storage");
storage.put(e.getPlayer().getName(), bag);
}
if (storage.contains(e.getPlayer().getName(), bag)) {
//use "bag" however you want
}
Also, instead of checking if storage.containsKey(null), to check if the player's name NOT is in the HashMap, you should use:
if(!storage.containsKey(e.getPlayer().getName()){
Doing storage.containsKey(null) will check if the map has null as a key, it won't find anything out about the player
Ok, I am trying to attach data to a Minecraft Bukkit ItemStack. I would like it so the entity that it drops would also have it, but that is optional. If I can not do this directly, is there some other way I can keep a piece of data (java int, java string) with the item as it moves through players and their inventory slots? Thanks!
EDIT: Here's a code example.
package path.to.the.package;
import org.bukkit.event.*;
import org.bukkit.event.PlayerInteractEvent;
import org.bukkit.plugin.java.JavaPlugin;
public ExamplePlugin extends JavaPlugin
{
public List<ItemStack> stacks = new ArrayList<ItemStack>();
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args)
{
if(cmd.getName().equalsIgnoreCase("tester123"))
{
ItemStack stack = new ItemStack(272, 0, (byte)0);
Player p = (Player)sender;
stacks.add(stack);
p.getLocation().getWorld().dropItem(player.getLocation(), stack);
}
return true;
}
#EventHandler(priority = EventPriority.HIGHEST)
public void onItemStackRightClick(PlayerInteractEvent e)
{
Player player = e.getPlayer();
for(ItemStack item : items)
{
if(player.getItemInHand() == item)
{
//What I DO want is something like: if(item.getPluginData(this, "KEY") == "SPECIAL")
//And I would have set it like: item.setPluginData(this, "KEY", "SPECIAL");
player.sendMessage("You got one of our SPECIAL stone swords!!!!");
}
}
}
}
I whipped up this example but it does not work when I right click with the one special sword.
I would use ItemStack.getItemMeta() to set the lore value:
import java.util.ArrayList;
import java.util.List;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.event.*;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.plugin.java.JavaPlugin;
public class ExamplePlugin extends JavaPlugin
{
public List<ItemStack> stacks = new ArrayList<ItemStack>();
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args)
{
if(cmd.getName().equalsIgnoreCase("tester123"))
{
ItemStack stack = new ItemStack(272, 0, (byte)0);
Player p = (Player)sender;
stacks.add(stack);
ItemMeta i = stack.getItemMeta();
List<String> lore = new ArrayList<String>();
lore.add("Special");
i.setLore(lore);
p.getLocation().getWorld().dropItem(((Player)sender).getLocation(), stack);
}
return true;
}
#EventHandler(priority = EventPriority.HIGHEST)
public void onItemStackRightClick(PlayerInteractEvent e)
{
Player player = e.getPlayer();
if(player.getItemInHand().getItemMeta().hasLore())
{
if (player.getItemInHand().getItemMeta().getLore().get(0).equals("Special"))
{
player.sendMessage("You got one of our SPECIAL stone swords!!!!");
}
}
}
}
There is the http://jd.bukkit.org/apidocs/org/bukkit/metadata/Metadatable.html where you can store your data in a key-value way. Looks like it already provides an interface to store/retrieve data.
If you want to store invisible data (insteed of lore), just use metadata :
Good article from Samer Alsayegh -> http://sameralsayegh.com/how-to-use-metadata/