BlockPhysicsEvent and getting sign text.

Discussion in 'Plugin Development' started by CoffeeOD, Jun 27, 2012.

Thread Status:
Not open for further replies.
  1. Offline

    CoffeeOD

    I have now tried few hours to get this working without success. In short, I need to get sign text when its removed due by non-player damage, where BlockPhysicsEvent comes in. Im having trouble to get material into sign block to get necessary text out of the sign.

    I have read http://forums.bukkit.org/threads/detecting-when-a-sign-is-detached-from-a-wall.18323/ topic and looked into DreadKyller code, but thats seems quite much for such simple thing, hopefully there is more simple way to do this.

    Any suggestions would be welcome.

    Code:
    @EventHandler (priority = EventPriority.NORMAL)
    public void Mulkvisti (BlockPhysicsEvent  event){
     
    if (event.getBlock().getType().toString().startsWith("SIGN") || event.getBlock().getType().toString().startsWith("WALL_SIGN")) {
    Block block = event.getBlock();
    Sign saatana = (Sign)block.getState().getData();
    Block attached = block.getRelative(saatana.getAttachedFace());
     
    if (attached.getType().toString().equalsIgnoreCase("air")) {
    Bukkit.broadcastMessage("Yep, it was sign attached to another block, nice.");
    saatana.getLine(0);
    return; } } } }  
    I tried to cast different variations like (org.bukkit.block.Sign) to saatana.getline but none of them worked.

    I had idea to save boolean value to hashmap/something after "if (attached.getType().toString().equalsIgnoreCase("air"))" and pass it to another class (example classs B) which would have "saatana.getLine(0);" line, class "b" kick in it if that value I saved returned "true", but that seems very shaky to do and possible full of fail.
     
  2. That long code from that thread was poorly designed but it was made to capture who made the sign break without actually breaking it, if you don't need that, don't use it.... but there is a simplier way to do that too.

    You casted the wrong method to SIgn, it must be the BlockState itself:
    Sign sign = (Sign)block.getState();
    But you should check if it's actually an instance of that, it may be a sign material but maybe it doesn't have the sign properties.. I dunno... but to avoid errors:
    if(blockState instanceof Sign)
    Also make sure you store blockState because it's an expensive method, call it only once by storing it.

    They used .getData() in that thread because they used org.bukkit.material.Sign, not .block.Sign which you need.


    And don't use equal*() for simple enums like Material, use == like so:
    if(event.getBlock.getType() == Material.SIGN_POST || event.getBlock.getType() == Material.WALL_SIGN)
    if(attached.getType() == Material.AIR)
     
  3. Offline

    CoffeeOD

    Thanks Digi, I already tried with .block.Sign but problem was getting "attached" information. I even tried "Block attached = block.getRelative(((org.bukkit.material.Sign) saatana).getAttachedFace());" which of course gave error:

    Code:
    Caused by: java.lang.ClassCastException: org.bukkit.craftbukkit.block.CraftSign cannot be cast to org.bukkit.material.Sign
    
    With block.sign import, I get "The method getAttachedFace() is undefined for the type Sign", so it seems to only work for .material instead .block, of course with ".material" I cant get sign text to string which is problem I cant seem to solve :/
     
  4. You need to cast the MaterialData (block.getData()) to .material.Sign to get the attached face method I belive.
    Weird how sign is split up in 2 diferent objects :confused:, but I guess when they designed it, it made sense :}
     
  5. Offline

    CoffeeOD

    Unfortunately I couldnt get MaterialData to work either, no matter where I tried to cast it something was always "undefined for this type", I think imports might be problem since depending on material.sign or block.sign something worked but another didnt (for example getline worked with .block.sign but attached didnt, with .material.sign it was other way around). I tried every possible solution that made even little sense to me.

    I got something "working";
    Code:
    if (attached.getType().toString().equalsIgnoreCase("air")) {
    PsyBreak.CheckBreak(event);
    return; } } } }  
    and PsyBreak has
    Code:
    public static void CheckBreak (BlockPhysicsEvent  event){
     
    if (event.getBlock().getType().toString().startsWith("SIGN") || event.getBlock().getType().toString().startsWith("WALL_SIGN")) {
    Sign perkele = (Sign) event.getBlock().getState();
    if (perkele.getLine(0).equalsIgnoreCase("something") && Bukkit.getServer().getPlayer(perkele.getLine(1)) != null) {
    Player target = Bukkit.getServer().getPlayer(perkele.getLine(1));
    etc... 
    Problem is now plugin returns text from sign every time block is changed near sign, even when I wanted this only to happend if sign removed :/ Code at first poist would had been good enough but it didnt return any text from sign, this does return but too often :p

    If I just did not understood "MaterialData" thing, I would appreciate (spelling?) sample code or something to help me move forward with this.
     
  6. Offline

    desht

    Wow, the linked thread was probably my first post on the forums :)

    Anyhow, this is how I dealt with it: https://github.com/desht/ScrollingM...gmenusign/listeners/SMSBlockListener.java#L93

    Basically, get the block's BlockState (line 103), and if it's an Attachable (more generic than signs - but you could check specifically for org.bukkit.material.Sign), check the block it is (or should be attached to). If that block is AIR, then the attachable has become detached and needs to be handled appropriately. A more general check for any non-solid block as opposed to AIR might also be appropriate.
     
Thread Status:
Not open for further replies.

Share This Page