How do you create a custom item in Spigot 1.16.5? - java

I'm making a plugin that adds some useful items like House Building Wand, Exploding Sword, etc. But how can I add those items using the plugin?

Normally, you would want to make a class for your item.
For example, you can make a class HouseBuildingWand.java and add some Java logic in it.
public class HouseBuildingWand {
public static ItemStack getHouseBuildingWand() {
ItemStack houseBuildingWand = new ItemStack(Material.YOUR_ITEM);
return houseBuildingWand;
}
}
To make the ability, you have to use Java knowledge.
To add enchantments, flags, lore, names, check out https://bukkit.gamepedia.com/Plugin_Tutorial#Item_Manipulation.
To get the item, you would need a command or an event that would give you the item.
To check how the item was clicked, you can use an event listener with the event PlayerInteractEvent. Example:
#EventHandler
public void onRightClick (PlayerInteractEvent event) {
Player p = event.getPlayer();
if (event.getAction() == Action.RIGHT_CLICK_AIR) {
if (event.getItem().getType() == Material.YOUR_ITEM) {
// insert logic
}
}
}

Related

Updating JList by pressing button

first of all I will introduce what I am trying to do. This is an assignment in university we are making Hotel booking system with JAVA. To go straight to the point, all I need to know is how to update JList when I press button.
listModel = new DefaultListModel<Hotel>();
bookingList = new JList(listModel);
class MouseAdapterMod extends MouseAdapter {
public void mousePressed(MouseEvent e) {
if(e.getSource() == searchButton){
for(lists.getRoomsList() p : lists.getRoomsList())
{
listModel.addElement(p);
}
bookingList.setModel(listModel);
}
In this GUI class I have instance variable (lists) of Hotel class, in Hotel class there are methods
public ArrayList<Rooms> getRoomsList()
{
return roomsList.getListRooms();
}
public ArrayList<Suite> getSuitesList()
{
return roomsList.getListSuites();
}
this returns whole ArrayList of Room class objects and also ArrayList of Suite class.
QUESTION would be is how to show whole ArrayList of Rooms when I press button, in other words how to update JList which consists of objects, by pressing button?
I hope I explained alright.
Your for-each loop is wrong. Try this and see:
public void mousePressed(MouseEvent e) {
if(e.getSource().equals(searchButton)){
ArrayList<Rooms> rooms = lists.getRoomsList();
for(Rooms r : rooms) {
listModel.addElement(r);
}
bookingList.setModel(listModel);
}
}
This still looks sorta messy to me though. A more appropriate approach would be to set an event handler on the searchButton, to populate the JList when searchButton is clicked.
Also, are Rooms and Suites sub classes of Hotel? If not, you'll have to create listModel like this (for rooms):
listModel = new DefaultListModel<Rooms>();

Shaped Recipe with specifically named item?

I'm trying to create a crafting recipe with bukkit and I want the recipe to ONLY accept a leather helmet with the name "Better Helmet". right now I have this:
public static ItemStack lvl2Head = new ItemStack(Material.LEATHER_HELMET, 1);
{
//removed unnessecary information
lvl2HeadMeta.setDisplayName("Better Helmet 2");
}
public void lvl1ArmorHead() {
ShapedRecipe recipe = new ShapedRecipe(lvl2Head);
recipe.shape("AAA", "ABA", "AAA");
recipe.setIngredient('A', Material.DIAMOND);
//want it to check it under here in place of "LEATHER_HELMET"
recipe.setIngredient('B', Material.LEATHER_HELMET);
this.getServer().addRecipe(recipe);
}
Is there any way I can accomplish this? I tried putting the name of the new ItemStack in place of Material.LEATHER_HELMET but it wants MaterialData not an ItemStack.
update
I'm still able to pull the item out of the crafting table using a regular leather helmet this code created with jojodmo.
Main Class:
public static ShapedRecipe lvl1ArmorHeadRecipe() {
ShapedRecipe recipe = new ShapedRecipe(lvl1Head);
recipe.shape("AAA", "ABA", "AAA");
recipe.setIngredient('A', Material.DIAMOND);
recipe.setIngredient('B', Material.LEATHER_HELMET);
return recipe;
}
public void lvl1ArmorHead(){
this.getServer().addRecipe(lvl1ArmorHeadRecipe());
}
EventHandler class:
#EventHandler
public void craft(CraftItemEvent e){
if(e.getInventory() instanceof CraftingInventory){
CraftingInventory inv = (CraftingInventory) e.getInventory();
if(inv.getSize() != 4 && e.getRecipe().equals(Main.lvl1ArmorHeadRecipe())){
org.bukkit.inventory.ItemStack helm = inv.getMatrix()[5];
if(helm.hasItemMeta()){
if(helm.getItemMeta().getDisplayName().equals("Better Helmet")){
//done.
} else{
e.setCancelled(true);
}
} else {
e.setCancelled(true);
}
}
}
}
Note: This is for Bukkit 1.7.2
I've done this before, It took me so long to figure out how to do it! The only problem is that the result still shows up if you were to use a regular leather helmet, but it just doesn't let you take the result out of the crafting table.
Here's how I did it:
public ShapedRecipie lvl1ArmorHeadRecipie(){
ShapedRecipe recipe = new ShapedRecipe(lvl2Head);
recipe.shape("AAA", "ABA", "AAA");
recipe.setIngredient('A', Material.DIAMOND);
recipe.setIngredient('B', Material.LEATHER_HELMET);
return recipie;
}
public void lvl1ArmorHead(){
this.getServer().addRecipe(lvl1ArmorHeadRecipie());
//do everything in here normally
}
Next, use this. Make sure to make the class that this is in implement Listener
#EventHandler
public void craft(CraftItemEvent e){
if(e.getInventory() instanceof CraftingInventory){
CraftingInventory inv = (CraftingInventory) e.getInventory();
if(inv.getSize() != 4 && e.getRecipe().equals(lvl1ArmorHelmetRecipe())){
ItemStack helm = inv.getMatrix()[4];//get the middle item in the bench, which is the helmet
if(helm.hasItemMeta()){//make sure the helmet has item meta
if(helm.getItemMeta().getDisplayName().equals("Better Helmet")){//make sure the helmet's display name is 'Better Helmet'
//you're done! It works! Do something like tell the player "you have crafted better armor" or something here.
return;
}
}
//the return; above would have been called if the crafting had succeeded. When it got called, the remainder of this method would not run (this part will not be run if the crafting has succeeded)
//send the player a message to make it more realistic here. For my wizardry server I use: 'One of thee items used was incorrect, and unbalanced the energy. The death block hath been destroyed'
e.setCanceled(true);
e.setResult(new ItemStack(Material.AIR));
}
}
}
Look up the PrepareItemCraftEvent, I've answered your question on the bukkit forums, look at my post: http://forums.bukkit.org/threads/resource-no-nms-make-custom-crafting-recipes-ingredients-obey-itemmeta-displayname-e-t-c.280482/

Adding double-click expansion to the Tree Viewer in SWT

Double-Clicking tree items works completely fine, but when I press CTRL + M on the keyboard then the tree items expand\collapse, can someone please tell me the reason behind this? Is this a bug in Eclipse or why does this double-click functionality get triggered when I press CTRL+M.
Thanks.
Use TreeViewer.addDoubleClickListener to listen for tree double clicks not a mouse listener. You could use something like this:
private class DoubleClickListener implements IDoubleClickListener
{
#Override
public void doubleClick(final DoubleClickEvent event)
{
final IStructuredSelection selection = (IStructuredSelection)event.getSelection();
if (selection == null || selection.isEmpty())
return;
final Object sel = selection.getFirstElement();
final ITreeContentProvider provider = (ITreeContentProvider)treeViewer.getContentProvider();
if (!provider.hasChildren(sel))
return;
if (treeViewer.getExpandedState(sel))
treeViewer.collapseToLevel(sel, AbstractTreeViewer.ALL_LEVELS);
else
treeViewer.expandToLevel(sel, 1);
}
}
Update:
Using TreeViewer.addDoubleClickListener is the preferred way to do double click handling for all classes derived from StructuredViewer.
Each double click listener is run using SafeRunnable which deals with any exceptions that the listener may throw, this safeguards the rest of the code for errors in the listeners.
The DoubleClickEvent provides direct access to the model object data so it is not necessary to deal with Tree or TreeItem objects to work out selections.
The double click code in the TreeViewer interfaces correctly with the OpenStrategy single / double click to open code.
I think the following code will be better , cause it will not cause the tree item to reload children and will keep the original state of other tree items.
_treeViewer.addDoubleClickListener( new IDoubleClickListener()
{
#Override
public void doubleClick( DoubleClickEvent event )
{
ISelection selection = event.getSelection();
if( selection instanceof ITreeSelection )
{
TreePath[] paths= ((ITreeSelection)selection).getPathsFor(selectedItem);
for (int i= 0; i < paths.length; i++)
{
_treeViewer.setExpandedState(paths[i], !_treeViewer.getExpandedState(paths[i]));
}
}
}
}
} );

How do I implement a simple undo/redo for actions in java?

I've created an XML editor and I'm stuck at the last phase: adding undo/redo functionality.
I've only got to add undo/redo for when users add elements, attributes, or text to the JTree.
I'm still quite new at this but in school today I attempted (unsuccessfully) to create two stack object []'s called undo and redo and to add the actions performed into them.
For instance, I have:
Action AddElement() {
// some code
public void actionPerformed(ActionEvent e) {
performElementAction();
}
}
the performElementAction just actually adds an Element to the JTree.
I want to add a way to add this action performed to my undo stack. is there a simple way to just undo.push( the entire action performed) or something?
TL;DR: You can support undo and redo actions by implementing the Command (p.233) and Memento (p.283) patterns (Design Patterns - Gamma et. al).
The Memento Pattern
This simple pattern allows you to save the states of an object. Simply wrap the object in a new class and whenever its state changes, update it.
public class Memento
{
MyObject myObject;
public MyObject getState()
{
return myObject;
}
public void setState(MyObject myObject)
{
this.myObject = myObject;
}
}
The Command Pattern
The Command pattern stores the original object (that we want to support undo/redo) and the memento object, which we need in case of an undo. Moreover, 2 methods are defined:
execute: executes the command
unExecute: removes the command
Code:
public abstract class Command
{
MyObject myObject;
Memento memento;
public abstract void execute();
public abstract void unExecute();
}
They define the logical "Actions" that extend Command (e.g. Insert):
public class InsertCharacterCommand extends Command
{
//members..
public InsertCharacterCommand()
{
//instantiate
}
#Override public void execute()
{
//create Memento before executing
//set new state
}
#Override public void unExecute()
{
this.myObject = memento.getState()l
}
}
Applying the patterns:
This last step defines the undo/redo behavior. The core idea is to store a stack of commands that works as a history list of the commands. To support redo, you can keep a secondary pointer whenever an undo command is applied. Note that whenever a new object is inserted, then all the commands after its current position get removed; that's achieved by the deleteElementsAfterPointer method defined below:
private int undoRedoPointer = -1;
private Stack<Command> commandStack = new Stack<>();
private void insertCommand()
{
deleteElementsAfterPointer(undoRedoPointer);
Command command =
new InsertCharacterCommand();
command.execute();
commandStack.push(command);
undoRedoPointer++;
}
private void deleteElementsAfterPointer(int undoRedoPointer)
{
if(commandStack.size()<1)return;
for(int i = commandStack.size()-1; i > undoRedoPointer; i--)
{
commandStack.remove(i);
}
}
private void undo()
{
Command command = commandStack.get(undoRedoPointer);
command.unExecute();
undoRedoPointer--;
}
private void redo()
{
if(undoRedoPointer == commandStack.size() - 1)
return;
undoRedoPointer++;
Command command = commandStack.get(undoRedoPointer);
command.execute();
}
Conclusion:
What makes this design powerful is the fact that you can add as many commands as you like (by extending the Command class) e.g., RemoveCommand, UpdateCommand and so on. Moreover, the same pattern is applicable to any type of object, making the design reusable and modifiable across different use cases.
You have to define undo(), redo() operations along with execute() in Command interface itself.
example:
interface Command {
void execute() ;
void undo() ;
void redo() ;
}
Define a State in your ConcreteCommand class. Depending on current State after execute() method, you have to decide whether command should be added to Undo Stack or Redo Stack and take decision accordingly.
Have a look at this undo-redo command article for better understanding.
I would try to create an Action class, with a AddElementAction class inheriting off Action.
AddElementAction could have a Do() and Undo() method which would add/remove elements accordingly. You can then keep two stacks of Actions for undo/redo, and just call Do()/Undo() on the top element before popping it.

Is this typically how Java interfaces are used to set up event handlers, and are there hidden drawbacks to this approach?

Hey all, I'm still relatively new to Java, and looking for a sanity check.
I've been studying this Java port of Cocos2D and noticed that the CCLayer class has built-in hooks to the Android native touch events. That's great, but what I'd really like is for objects like CCSprite to directly respond to touch events without having to listen for those events in the layer and iterate through all the children to find which ones happen to intersect the event's x/y coordinates. So I figured that this would be the perfect chance to test my understanding of how to set up some event handlers and make a subclass of CCSprite that actually listens for touches without needing to go through CCLayer to know about it. Furthermore, I wanted to be able to assign different behaviors to different CCSprite instances on an ad-hoc basis without explicitly subclassing further, much like Android Buttons don't need to be subclassed just to give them a handler for their touch events.
This is what I came up with on a first pass:
// My touch interface for all touchable CCNode objects.
package com.scriptocalypse.cocos2d;
public interface ITouchable {
boolean onCCTouchesBegan();
boolean onCCTouchesEnded();
boolean onCCTouchesMoved();
}
And now the class that uses the ITouchable interface for its callbacks...
public class CCTouchSprite extends CCSprite implements CCTouchDelegateProtocol {
protected ITouchable mTouchable;
public void setTouchable(ITouchable pTouchable){
mTouchable = pTouchable;
boolean enable = mTouchable != null;
this.setIsTouchEnabled(enable);
}
public void setIsTouchable(boolean pEnabled){
// code to enable and disable touches snipped...
}
/////
// And now implementing the CCTouchDelegateProtocol...
/////
public boolean ccTouchesBegan(MotionEvent event) {
Log.d("hi there", "touch me");
if(mTouchable != null){
mTouchable.onCCTouchesBegan();
}
return CCTouchDispatcher.kEventHandled; // TODO Auto-generated method stub
}
public boolean ccTouchesMoved(MotionEvent event) {
if(mTouchable != null){
mTouchable.onCCTouchesMoved();
}
return CCTouchDispatcher.kEventIgnored; // TODO Auto-generated method stub
}
public boolean ccTouchesEnded(MotionEvent event) {
Log.d("hi there", "not touch me");
if(mTouchable != null){
mTouchable.onCCTouchesEnded();
}
return CCTouchDispatcher.kEventIgnored; // TODO Auto-generated method stub
}
}
And finally, instantiate the class and implement the interface...
final CCTouchSprite sprite = new CCTouchSprite(tex);
sprite.setIsTouchEnabled(true);
sprite.setPosition(CGPoint.ccp(160,240));
sprite.setTouchable(new ITouchable(){
#Override
public boolean onCCTouchesBegan() {
Log.d("SWEET SUCCESS", "I got a touch through my interface!");
return true;
}
#Override
public boolean onCCTouchesEnded() {
Log.d("SWEET SUCCESS", "You stopped touching my interface!");
sprite.runAction(CCRotateBy.action(1, 360));
return false;
}
#Override
public boolean onCCTouchesMoved(){
Log.d("SWEET SUCCESS", "You moved the touch");
return false;
}
});
So all of this works. The subclass does successfully register with the Cocos2D touch dispatcher, which successfully calls those ccTouches functions and pass them MotionEvents, which in turn call my Interface functions if the interface has been instantiated.
Is this the "proper" way to do it (Define "it" as you see fit, ranging from using Interfaces to create event handlers to working with Cocos2D, to writing Java at all)? Are there drawbacks to this that I'm not aware of? Is this somehow worse for performance than iterating through all the CCNode objects that are children of CCLayer? If so, how can that possibly be?
I think you have got the basics for setting up a listener right. There are some things I would change though.
First, the setter setIsTouchable. It's weird. You need a listener object to pass touch events to right? So what is this setter going to do when you pass it true (as your example does)? You snipped the code, but setting a boolean field to true does not seem right here as it would put the sprite object in an inconsistent internal state. I would just drop that setter. The getter can just evaluate whether mTouchable is assigned or null.
Second, why limit yourself to one listener? Change mTouchable to mTouchables, being a list of ITouchables. Then change setTouchable to addTouchable and possibly add removeTouchable and clearTouchables methods. This way you can add multiple listeners for different behaviors having to respond to the same events. This is how most other event systems work as well. You then just change isTouchable to check whether the list is empty or not.
scriptoclypse... I really am not completely understanding your question, but you have not had any response and yes interfaces and events are very similar. At this level I can only respond in C#.

Categories