Home > Back-end >  how to use a list in another class?
how to use a list in another class?

Time:07-06

I want to create a list, add blocks to it and then use it in a BlockBreakEvent to check if the block is in the list and cancel the event if it's not. But I can't seem to create and add things in it any other way than in the actual event itself (which looks to me like it would create issues). The only thing that is working for me is creating the list in the event and adding blocks to it one by one which looks really messy compared to: creating the list in a separate class and just checking the list with if(Listname.contains(block)) does anyone know how I can achieve this? Whether its dependency injection, or whatever else. I just can't figure out how to put it to use.

Here's what I've tried and is currently working for me, but I believe it's theoretically incorrect:

public class Event implements Listener {
@EventHandler
public void onBreak(BlockBreakEvent e) {
    List<Material> allowedblocks = new ArrayList<Material>();
    allowedblocks.add(Material.STONE);
    //repeat this 10-50 times for whatever item
    
    
    Player p = e.getPlayer();
    Material block = e.getBlock().getType();
    
    if(allowedblocks.contains(block)){
        p.sendMessage("Invalid block. Break cancelled");
        e.setCancelled(true);
    }else{
        p.sendMessage("Valid Block");
    }
    }

}

CodePudding user response:

You can make allowedBlocks List a class field and fill it with elements inside of the constructor.

public class YourClass {
    private List<Material> allowedBlocks = new ArrayList<>();    

    public YourClass() {
        allowedBlocks.add(Material.STONE);
        //repeat this 10-50 times for whatever item
    }

    @EventHandler
    public void onBreak(BlockBreakEvent e) {
        Player p = e.getPlayer();
        Material block = e.getBlock().getType();
    
        if(allowedBlocks.contains(block)){
            p.sendMessage("Valid Block");
        } else {
            p.sendMessage("Invalid block. Break cancelled");
            e.setCancelled(true);
        }
    }
}

Another approach would be to make the list static and fill it with values inside of a static block. I would not recommend making the list static if you are planning to change its values, but if your allowed blocks are going to remain the same, it may be a good idea to even go further and make it public, so you can access it from anywhere without an instance of YourClass

public class YourClass {
  public static final List<Material> allowedBlocks;    

  static {
      List<Materials> list = new ArrayList<>();
      list.add(Material.STONE);
      //repeat this 10-50 times for whatever item

      //use an unmodifiable list, 
      //so you do not accidentally change its content later
      allowedBlocks = Collections.unmodifiableList(list);
  }

  @EventHandler
  public void onBreak(BlockBreakEvent e) {
      Player p = e.getPlayer();
      Material block = e.getBlock().getType();

      if(allowedBlocks.contains(block)){
          p.sendMessage("Valid Block");
      } else {
          p.sendMessage("Invalid block. Break cancelled");
          e.setCancelled(true);
      }
  }
}

In the first case, there will be a list of allowedBlocks per instance of YourClass, which means, that every time you call new YourClass() a new List will be created and filled. In the second case, there will be only one list which will be created and populated on class loading (at the very beginning of the program) start up.

P.S. I would rather use a Set instead of a List here, considering you are using contains very often.

CodePudding user response:

Try to create the List in a static context. This way the list is the same for all instances:

public class MyClass {
    
    public static List<Material> allowedblocks = new ArrayList<Material>();

    @EventHandler
    public void onBreak(BlockBreakEvent e) {
        allowedblocks.add(Material.STONE);
        ...

Then you can call the List from everywhere like this (e.g. if statement):

if(MyClass.allowedblocks.contains(block)) 

Your problem seems simmilar to this question, maybe this answer helps too: .

CodePudding user response:

Since you are using an enum to store your Material types, you can simply call the static .values() method through Material.

Ex:

@EventHandler
public void onBreak(BlockBreakEvent e) {
    Player p = e.getPlayer();
    Material block = e.getBlock().getType();
    if(List.of(Material.values()).contains(block)){
        p.sendMessage("Invalid block. Break cancelled");
        e.setCancelled(true);
    }else{
        p.sendMessage("Valid Block");
    }
    }

}

If you need to be able to customize what values are in the List you can use the singleton pattern to access that information globally.

The instance can be accessed statically from anywhere in the application:

import java.util.List;

public class BlockController {
        
    public static BlockController instance = new BlockController();
    
    private List<Material> allowedBlocks; 
    
    public BlockController() {
        this.allowedBlocks = new ArrayList<>();
    }
    
    public void addAllowedBlock(Material mat) {
        this.allowedBlocks.add(mat);
    }
    
    public void removeAllowedBlock(Material mat) {
        this.allowedBlocks.remove(mat);
    }
    
    public boolean containsBlock(Material mat) {
        return this.allowedBlocks.contains(mat);
    }
    
    public void clear() {
        this.allowedBlocks.clear();
    }
    
/**
 * You can add more functionality here...
 * This class can be accessed anywhere in the application
 * 
 * use:
 * 
 * BlockController controller = BlockController.instance;
 * controller.containsBlock(Material.BLOCK);
 */

}

CodePudding user response:

One approach to creating the list in a separate class is to use a static initializer block:

public class MyClass {
    public static final List<Material> ALLOWED_MATERIALS = new ArrayList<>();

    static {
        ALLOWED_MATERIALS.add( Material.STONE );
    }

    public static List<Material> getAllowedMaterials() {
        return Collections.unmodifiableList( ALLOWED_MATERIALS );
    }
    ...
 }
  • Related