All pastes #215358 Raw Edit

Anonymous

public java v1 · immutable
#215358 ·published 2006-10-22 15:59 UTC
rendered paste body
/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * * http://www.gnu.org/copyleft/gpl.html */package net.sf.l2j.gameserver.model.entity.geodata;import java.util.logging.Logger;import java.io.File;import java.io.RandomAccessFile;import net.sf.l2j.gameserver.model.L2Object;import net.sf.l2j.gameserver.model.L2World;import javolution.util.FastMap;/**clanth --  22 oct 2006 **/public class GeoDataRequester{    private static final int SHIFT_BY = 11;    /** Map dimensions */    public static final int MAP_MIN_X = -131072;    public static final int MAP_MAX_X = 228608;    public static final int MAP_MIN_Y = -262144;    public static final int MAP_MAX_Y = 262144;    public static final int CELL_OFFSET = 0x7FF;    /** calculated offset used so top left region is 0,0 */    private static final int OFFSET_X = Math.abs(MAP_MIN_X >> SHIFT_BY);    private static final int OFFSET_Y = Math.abs(MAP_MIN_Y >> SHIFT_BY);    private static final byte  EAST=1, WEST=2, SOUTH=4, NORTH=8;    private short defaultCapacity;    private long defaultExpirationTime;    public static GeoDataRequester _instance = new GeoDataRequester();    private static Logger _log = Logger.getLogger(GeoDataRequester.class.getName());    private FastMap<String,GeoBlock> geoList;    private FastMap<Integer,GeoDataBuffer> geoRequestBuffer;    public class FarPoint    {        public int x;        public int y;        public short z;        public boolean LoS;    }    private class GeoBlock    {        public Cell[][] geoInnerBlock = new Cell[16][16];        public long expirationTime;        public String key;    }    private class Cell    {    }    private class CoarseCell extends Cell    {        public short minZ_NSEW;        public short maxZ;    }    private class DetailedCell extends Cell    {        public short[][] NSEW_Z = new short [8][8];    }    private class multiLevelDetailedCell extends Cell    {        public layers[][] NSEW_Z = new layers [8][8];    }    private class layers    {        public short[] layer;        private layers(short amount)        {            layer = new short[amount];        }    }    public class GeoSubCell    {        //public int currentLayer;        //public byte cellType;        public short zNSEW;        public short Z = 0;        public byte NSEW = 0;        public GeoSubCell()        {            //do nothing        }        public GeoSubCell(short newZNSEW)        {            zNSEW = newZNSEW;        }        public GeoSubCell(short newZ, byte newNSEW)        {            zNSEW = (short)(((newZ<<1)& 0x0fff0) | (newNSEW & 0x0f));        }        public short getZ()        {            if (Z == 0)            {                return (short)((zNSEW>>1) & 0xFFFFFFF8);            }            else            {                return Z;            }        }        public byte getNSEW()        {            if (NSEW == 0)            {                return (byte)(zNSEW & 0x0F);            }            else            {                return NSEW;            }        }    }    private class GeoDataBuffer    {        public int key;        public int x;        public int y;        public int z;        public int targetX;        public int targetY;        public int targetZ;        public byte mov_atk; // move = 0 atk = 1        public boolean hadLoS;    }    public GeoDataRequester()    {        defaultCapacity = 500;  //maximum of 16x16 regions loaded in memory        defaultExpirationTime  = 900000;     // unused files expire after 900 secs.        geoList = new FastMap<String,GeoBlock>().setShared(true);        geoRequestBuffer = new FastMap<Integer,GeoDataBuffer>().setShared(true);    }    public static GeoDataRequester getInstance()    {        if(_instance == null)        {            _instance = new GeoDataRequester();        }        return _instance;    }    public void setDefaultExpirationTime (long expTime)    {        defaultExpirationTime = expTime;    }    public long getDefaultExpirationTime ()    {        return defaultExpirationTime;    }    public int getGeoListSize()    {        return geoList.size();    }    public synchronized GeoBlock getGeoBlock(int X , int Y)    {        int tileX;        int tileY;        GeoBlock block;        String skey;        byte[] allBlocks;        tileX = (X >> SHIFT_BY) + OFFSET_X;        tileY = (Y >> SHIFT_BY) + OFFSET_Y;        skey = String.valueOf(tileX) + String.valueOf(tileY);        try        {            if ( geoList.containsKey(skey) == true )            {                block = geoList.get(skey);                block.expirationTime = System.currentTimeMillis();                return block;            }            else            {                block = new GeoBlock();                allBlocks  = readGeoData( X,Y );                if (allBlocks == null)                {                    // no geodata                    return null;                }                block.geoInnerBlock = parseGeoBlock(allBlocks);                block.expirationTime = System.currentTimeMillis();                block.key = skey;                geoList.put(skey,block);            }            FlushGeoList();            return block;        }        catch ( Exception e)        {            _log.warning("Error load GeoBlock Exception : " + e.getMessage());            return null;        }    }    private synchronized void FlushGeoList()    {        long now = System.currentTimeMillis();        try        {            for (GeoBlock expiredBlock : geoList.values())            {                if( (now -  expiredBlock.expirationTime) > defaultExpirationTime )                {                    // object has expired so clean up                    for(int i = 0 ; i < 16 ; i ++ )                    {                        for (int j = 0; j < 16 ; j ++ )                        {                            if  (expiredBlock.geoInnerBlock[i][j] instanceof DetailedCell)                            {                                ((DetailedCell)expiredBlock.geoInnerBlock[i][j]).NSEW_Z = null;                            }                            else if  (expiredBlock.geoInnerBlock[i][j] instanceof multiLevelDetailedCell)                            {                                for (int k = 0 ; k < 8 ; k ++)                                {                                    for (int l = 0 ; l < 8 ; l ++)                                    {                                        ((multiLevelDetailedCell)expiredBlock.geoInnerBlock[i][j]).NSEW_Z[k][l] = null;                                    }                                }                            }                            expiredBlock.geoInnerBlock[i][j] = null;                        }                    }                    geoList.remove(expiredBlock.key);                    expiredBlock.geoInnerBlock = null;                    expiredBlock = null;                }            }        }        catch (Exception e)        {            _log.warning("Error FlushGeoList Expired Block Exception : " + e.getMessage());        }        if (geoList.size() >= defaultCapacity)        {            // remove the oldest            GeoBlock toBeRemoved = null;            long longest = 0;            //geoList.head().getNext();            try            {                for (GeoBlock overPopulatedBlock : geoList.values())                {                    if (now - overPopulatedBlock.expirationTime  >  longest)                    {                        toBeRemoved = overPopulatedBlock;                        longest = now - overPopulatedBlock.expirationTime;                    }                }            }            catch (Exception e)            {                _log.warning("Error FlushGeoList Crowded Block frist loop Exception : " + e.getMessage());            }            try            {                for(int i = 0 ; i < 16 ; i ++ )                {                    for (int j = 0; j < 16 ; j ++ )                    {                        if (toBeRemoved.geoInnerBlock != null )                        {                            if  (toBeRemoved.geoInnerBlock[i][j] instanceof multiLevelDetailedCell)                            {                                for (int k = 0 ; k < 8 ; k ++)                                {                                    for (int l = 0 ; l < 8 ; l ++)                                    {                                        ((multiLevelDetailedCell)toBeRemoved.geoInnerBlock[i][j]).NSEW_Z[k][l] = null;                                    }                                }                            }                            toBeRemoved.geoInnerBlock[i][j] = null;                        }                    }                }                geoList.remove(toBeRemoved.key);                toBeRemoved.geoInnerBlock = null;                toBeRemoved = null;            }            catch (Exception e)            {                _log.warning("Error FlushGeoList Crowded Block Second loop Exception : " + e.getMessage());            }        }        // TODO        //Flush unused object in geo buffer        L2Object obj;        try        {            for (GeoDataBuffer expiredBlock : geoRequestBuffer.values())            {                obj = L2World.getInstance().findObject(expiredBlock.key);                if ( obj == null)                {                    geoRequestBuffer.remove(expiredBlock.key);                    expiredBlock = null;                }            }        }        catch (Exception e)        {            _log.warning("Error in flushing geoRequestBuffer");        }    }    private GeoDataBuffer checkGeoBuffer(int objId, int npcX, int npcY, int npcZ, int targetX, int targetY, int  targetZ)    {        GeoDataBuffer geobuf;        if( geoRequestBuffer.containsKey(objId) == true )        {            geobuf = geoRequestBuffer.get(objId);            if ( geobuf.x==npcX && geobuf.y==npcY && geobuf.z==npcZ && geobuf.targetX==targetX && geobuf.targetY==targetY && geobuf.targetZ==targetZ )            {                return geobuf;            }            else            {                //_log.warning( " refreshing buffer " + objId );                geobuf.x = npcX;                geobuf.y = npcY;                geobuf.z = npcZ;                geobuf.targetX = targetX;                geobuf.targetY = targetY;                geobuf.targetZ = targetZ;                return null;            }        }        else        {            geobuf = new GeoDataBuffer();            geobuf.key = objId;            geobuf.x = npcX;            geobuf.y = npcY;            geobuf.z = npcZ;            geobuf.targetX = targetX;            geobuf.targetY = targetY;            geobuf.targetZ = targetZ;            geoRequestBuffer.put(objId,geobuf);        }        return null;    }    public byte[] readGeoData(int X, int Y)    {        RandomAccessFile currentFile;        // 1) get the name of the file containing the geodata for this block        String filename = getBlockFileName(X, Y);        try        {            byte[] rawInfo = null;            currentFile = new RandomAccessFile(filename,"r");            //GeoDataFileReader fileReader = GeoFilePoolManager.getInstance().checkOut(filename);            if( currentFile.length() > 0)            {                long arraySize = currentFile.length();                if (arraySize > 0)                {                    rawInfo = new byte[(int)arraySize];                }                if (rawInfo != null)                {                    int readLength = currentFile.read(rawInfo);                    if (readLength == -1 )                    {                        //_log.warning( "error reading geodata file " + filename);                        currentFile.close();                        return null;                    }                }            }            currentFile.close();            return rawInfo;        }        catch(Exception e)        {            //_log.warning( "Error reading geodata file e=" + e.getMessage());            return null;        }    }    private Cell[][] parseGeoBlock (byte[] rawInfo)    {        byte header;        int dataPosition = 0;        Cell block[][] = new Cell[16][16];        try        {            for (int x = 0; x < 16; x++)            {                for(int y = 0; y < 16; y++)                {                    header = rawInfo[dataPosition];                    dataPosition ++;                    if (header == 0x00)                    {                        block[x][y] = new CoarseCell();                        ((CoarseCell) (block[x][y])).minZ_NSEW = parseFlippedShort(rawInfo[dataPosition],rawInfo[dataPosition+1]);                        dataPosition += 2;                        ((CoarseCell) (block[x][y])).maxZ = parseFlippedShort(rawInfo[dataPosition],rawInfo[dataPosition+1]);                        dataPosition += 2;                    }                    else if (header == 0x01)                    {                        block[x][y] = new DetailedCell();                        // Values are provided in y-first order                        for (short i=0;i<8;i++)                        {                            for (short j= 0 ; j < 8 ; j ++)                            {                                ((DetailedCell) (block[x][y])).NSEW_Z[i][j] = parseFlippedShort(rawInfo[dataPosition],rawInfo[dataPosition+1]);                                dataPosition += 2;                            }                        }                    }                    else if (header == 0x02)                    {                        block[x][y] = new multiLevelDetailedCell();                        // Values are provided in y-first order                        for (short i=0;i<8;i++)                        {                            for (short j= 0 ; j < 8 ; j ++)                            {                                short numLayers = parseFlippedShort(rawInfo[dataPosition],rawInfo[dataPosition+1]);                                dataPosition += 2;                                ((multiLevelDetailedCell) block[x][y]).NSEW_Z[i][j]  = new layers(numLayers);                                for(int k=0;k<numLayers;k++)                                {                                    ((multiLevelDetailedCell) block[x][y]).NSEW_Z[i][j].layer[k]  = parseFlippedShort(rawInfo[dataPosition],rawInfo[dataPosition+1]);                                    dataPosition += 2;                                }                            }                        }                    }                    else                    {                        //geodata file structure error;                        _log.warning( "Error in Geodata file, structure error");                        block = null;                        return null;                    }                }            }            return block;        }        catch(Exception e)        {            _log.warning( "Error parsing geodata : " + e.getMessage());            block = null;            return null;        }    }    private short parseFlippedShort(byte first, byte second)    {        int temp = first;        // The next line is necessary.  Otherwise, negative numbers get        // filled with leading 1's and mess up the following bit-wise OR.        temp = temp & 0x0ff;        temp = temp | (second<<8);        return (short)temp;    }    /**     * find the file that contains the info for this GeoBlock     * Each file contains 1 coarse cell or  8x8 = 64 blocks with block 0,0 at the beginning on file 16_10     * Given the X and Y find the file.     */    private String getBlockFileName(int X,int Y)    {        int tileX = (X >> SHIFT_BY) + OFFSET_X;        int tileY = (Y >> SHIFT_BY) + OFFSET_Y;        int fileX =(tileX / 16) + 16;        int fileY = (tileY / 16) + 10;        int subx =(tileX % 16);        int suby =(tileY % 16);        String filename = "data/geodata/" + fileX + "_" + fileY;        filename += "/" +fileX+"_" + fileY + "_" + subx + "_" + suby +  ".l2j";        File filecheck = new File(filename);        if (!filecheck.exists())        {            //_log.warning("check X = " + tileX + "   Y =" + tileY);            //_log.warning("Geodata file " + filecheck.getAbsolutePath() + " does not exist");            return null;        }        //_log.config("Geodata file located = " + filename);        return filename;    }    /**      not working yet     */    public FarPoint  getFarMovementPoint(L2Object source, L2Object target)    {        return getFarMovementPoint(source.getObjectId(), source.getX(), source.getY(), (short) source.getZ() , target.getX(), target.getY(), (short)target.getZ());    }    public FarPoint getFarMovementPoint(L2Object source, int targetX , int targetY , int targetZ)    {        return getFarMovementPoint(source.getObjectId(), source.getX(), source.getY(), (short) source.getZ() , targetX, targetY, (short)targetZ);    }    public FarPoint getFarMovementPoint(int objId, int sourceX, int sourceY, short sourceZ, int targetX , int targetY , short targetZ)    {        FarPoint p = new FarPoint();        if (hasMovementLoS (objId, sourceX, sourceY, sourceZ, targetX, targetY, targetZ) == true)        {            p.x = targetX;            p.y = targetY;            p.z = targetZ;            p.LoS = true;            return p;        }        return p;    }    public boolean hasMovementLoS(L2Object source, L2Object target)    {        return hasMovementLoS (source.getObjectId(),  source.getX(),source.getY(), (short) source.getZ() , target.getX(), target.getY(), (short) target.getZ());    }    public boolean hasMovementLoS(L2Object source, int targetX , int targetY , int targetZ)    {        return hasMovementLoS (source.getObjectId(), source.getX(), source.getY(), (short) source.getZ() , targetX, targetY, (short)targetZ);    }    public boolean hasLoS(L2Object source, int targetX , int targetY , short targetZ)    {        return hasMovementLoS (source.getObjectId(), source.getX(), source.getY(), (short) source.getZ() , targetX, targetY, targetZ);    }    public boolean hasMovementLoS(int objId, int sourceX, int sourceY, short sourceZ, int targetX , int targetY , short targetZ)    {        float m;        float b;        int x;        int y;        byte NSEW;        short newZ;        boolean LoS;        GeoDataBuffer geobuf;        GeoSubCell cellData;        //_log.warning("Geodata MLOS start");        double range = ((sourceX - targetX)*(sourceX - targetX) + (sourceY - targetY)*(sourceY - targetY));        if (range < 900  && (sourceZ & 0xFFF8) == (targetZ & 0xFFF8))        {            // self / 30 Ticks or mob is 8z ticks away force LOS            return true;        }        geobuf =checkGeoBuffer(objId, sourceX, sourceY, sourceZ, targetX, targetY, targetZ);        if (geobuf != null)        {            if (geobuf.mov_atk == 0)                return geobuf.hadLoS;        }        LoS = true;        newZ =sourceZ;        // avoid / 0 error        if (sourceX != targetX)        {            m = (float) (sourceY - targetY) / (sourceX - targetX);        }        else        {            m =0;        }        b = sourceY - (m*sourceX);        if ( sourceX == targetX ) // vertical line        {            if (sourceY > targetY)  //north            {                newZ =sourceZ;                for (y=sourceY;y > targetY+16;y = y - 16)                {                    cellData = getGeoInfoNearest(sourceX, y & 0xFFFFFFF0,newZ);                    NSEW = cellData.getNSEW();                    newZ =  cellData.getZ();                    //_log.warning("Geodata MLOS x:" + sourceX + " y:" + y + " z:" + cellData.getZ() );                    if ( (NSEW & SOUTH) == 0)                    {                        LoS = false;                        break;                    }                }            }            else            {                newZ =sourceZ;                for (y=sourceY;y < targetY-16;y=y + 16)                {                    cellData = getGeoInfoNearest(sourceX, (y+16) & 0xFFFFFFF0,newZ);                    NSEW = cellData.getNSEW();                    newZ =  cellData.getZ();                    //_log.warning("Geodata MLOS x:" + sourceX + " y:" + y + " z:" + cellData.getZ() );                    if ( (NSEW & NORTH) == 0)                    {                        LoS = false;                        break;                    }                }            }        }        else if (targetY==sourceY)   	// Horizontal Line or m=0        {            if (sourceX > targetX)  // west            {                newZ =sourceZ;                for (x=sourceX;x > targetX+16;x=x - 16)                {                    cellData = getGeoInfoNearest(x & 0xFFFFFFF0,sourceY,newZ);                    NSEW = cellData.getNSEW();                    newZ =  cellData.getZ();                    //_log.warning("Geodata MLOS x:" + x + " y:" + sourceY + " z:" + cellData.getZ() );                    if ( (NSEW & WEST) == 0)                    {                        LoS = false;                        break;                    }                }            }            else // EAST            {                newZ =sourceZ;                for (x=sourceX;x < targetX-16;x=x + 16)                {                    cellData = getGeoInfoNearest((x +16)& 0xFFFFFFF0,sourceY,newZ);                    NSEW = cellData.getNSEW();                    newZ =  cellData.getZ();                    //_log.warning("Geodata MLOS x:" + x + " y:" + sourceY + " z:" + cellData.getZ() );                    if ( (NSEW & EAST) == 0)                    {                        LoS = false;                        break;                    }                }            }        }        else if (( m > 0 && m <= 1) || ( m < 0 && m >= -1) ) // east west line -- so more X's to verify than Y's        {            if ( sourceX < targetX) // going East            {                newZ =sourceZ;                for (x=sourceX;x < targetX-16 ; x = x + 16)                {                    y = (int)((m*x) + b);                    cellData = getGeoInfoNearest((x + 16) & 0xFFFFFFF0  , y , newZ);                    NSEW = cellData.getNSEW();                    newZ =  cellData.getZ();                    //_log.warning("Geodata MLOS x:" + x + " y:" + y + " z:" + cellData.getZ() );                    if ((NSEW & EAST) == 0)                    {                        LoS = false;                        break;                    }                }                if ( m > 0 ) // North bound                {                    newZ =sourceZ;                    for (y=sourceY;y < targetY-16; y = y + 16)                    {                        x = (int) ((y-b) / m);                        cellData = getGeoInfoNearest( x  , (y + 16) & 0xFFFFFFF0  , newZ);                        NSEW = cellData.getNSEW();                        newZ =  cellData.getZ();                        //_log.warning("Geodata MLOS x:" + x + " y:" + y + " z:" + cellData.getZ() );                        if ((NSEW & NORTH) == 0)                        {                            LoS = false;                            break;                        }                    }                }                else // South Bound                {                    newZ =sourceZ;                    for (y=sourceY;y > targetY+16; y = y - 16)                    {                        x = (int) ((y -b) / m);                        cellData = getGeoInfoNearest( x  , y & 0xFFFFFFF0, newZ);                        NSEW = cellData.getNSEW();                        newZ =  cellData.getZ();                        //_log.warning("Geodata MLOS x:" + x + " y:" + y + " z:" + cellData.getZ() );                        if ((NSEW & SOUTH) == 0)                        {                            LoS = false;                            break;                        }                    }                }            }            else // going West            {                newZ =sourceZ;                for ( x=sourceX;x > targetX+16 ; x = x - 16)                {                    y = (int)((m*x) + b);                    cellData = getGeoInfoNearest( x & 0xFFFFFFF0 ,y , newZ);                    NSEW = cellData.getNSEW();                    newZ =  cellData.getZ();                    //_log.warning("Geodata MLOS x:" + x + " y:" + y + " z:" + cellData.getZ() );                    if ((NSEW & WEST) == 0)                    {                        LoS = false;                        break;                    }                }                if ( m > 0 ) // North                {                    newZ =sourceZ;                    for ( y=sourceY;y < targetY-16; y = y + 16)                    {                        x = (int) ((y-b) / m);                        cellData = getGeoInfoNearest(x  ,(y + 16) & 0xFFFFFFF0 , newZ);                        NSEW = cellData.getNSEW();                        newZ =  cellData.getZ();                        //_log.warning("Geodata MLOS x:" + x + " y:" + y + " z:" + cellData.getZ() );                        if ((NSEW & NORTH) == 0)                        {                            LoS = false;                            break;                        }                    }                }                else // South                {                    newZ =sourceZ;                    for ( y = sourceY;y > targetY+16; y = y - 16)                    {                        x = (int) ((y-b) / m);                        cellData = getGeoInfoNearest( x  , y & 0xFFFFFFF0 , newZ);                        NSEW = cellData.getNSEW();                        newZ =  cellData.getZ();                        //_log.warning("Geodata MLOS x:" + x + " y:" + y + " z:" + cellData.getZ() );                        if ((NSEW & SOUTH) == 0)                        {                            LoS = false;                            break;                        }                    }                }            }        }        else if ( m > 1 || m < -1) //north south line --  so, more y's to verify than x's        {            if (sourceY > targetY) // going north            {                newZ =sourceZ;                for ( y = sourceY ; y > targetY+16 ; y = y - 16)                {                    //y = (m * x) + b;                    x = (int) ((y-b) / m);                    cellData = getGeoInfoNearest( x , y & 0xFFFFFFF0 , newZ);                    NSEW = cellData.getNSEW();                    newZ =  cellData.getZ();                    //_log.warning("Geodata MLOS x:" + x + " y:" + y + " z:" + cellData.getZ() );                    if ((NSEW & NORTH) == 0)                    {                        LoS = false;                        break;                    }                }                if ( m > 0 ) // EAST Bound                {                    newZ =sourceZ;                    for ( x = sourceX;x < targetX-16; x = x + 16)                    {                        y = (int)((m*x)+b);                        cellData = getGeoInfoNearest( (x + 16) & 0xFFFFFFF0  , y , newZ);                        NSEW = cellData.getNSEW();                        newZ =  cellData.getZ();                        //_log.warning("Geodata MLOS x:" + x + " y:" + y + " z:" + cellData.getZ() );                        if ((NSEW & EAST) == 0)                        {                            LoS = false;                            break;                        }                    }                }                else // West Bound                {                    newZ =sourceZ;                    for ( x = sourceX;x > targetX+16; x = x - 16)                    {                        y = (int)((m*x)+b);                        cellData = getGeoInfoNearest( (x + 16) & 0xFFFFFFF0  , y , newZ);                        NSEW = cellData.getNSEW();                        newZ =  cellData.getZ();                        //_log.warning("Geodata MLOS x:" + x + " y:" + y + " z:" + cellData.getZ() );                        if ((NSEW & WEST) == 0)                        {                            LoS = false;                            break;                        }                    }                }            }            else // going South            {                newZ =sourceZ;                for ( y = sourceY ; y < targetY-16 ; y = y + 16)                {                    //y = (m * x ) + b;                    x =(int) ((y-b)/m);                    cellData = getGeoInfoNearest(x ,(y+16) & 0xFFFFFFF0, newZ);                    NSEW = cellData.getNSEW();                    newZ =  cellData.getZ();                    //_log.warning("Geodata MLOS x:" + x + " y:" + y + " z:" + cellData.getZ() );                    if ((NSEW & SOUTH) == 0)                    {                        LoS = false;                        break;                    }                }                if (m > 0) // WEST bound                {                    newZ =sourceZ;                    for ( x = sourceX;x > targetX+16 ; x = x - 16)                    {                        y = (int)((m*x)+b);                        cellData = getGeoInfoNearest( x & 0xFFFFFFF0 , y , newZ);                        NSEW = cellData.getNSEW();                        newZ =  cellData.getZ();                        if ((NSEW & WEST) == 0)                        {                            LoS = false;                            break;                        }                    }                }                else // EAST bound                {                    newZ =sourceZ;                    for ( x = sourceX;x < targetX-16 ; x = x + 16)                    {                        y = (int)((m*x)+b);                        cellData = getGeoInfoNearest((x +16) & 0xFFFFFFF0 ,y , newZ);                        NSEW = cellData.getNSEW();                        newZ =  cellData.getZ();                        //_log.warning("Geodata MLOS x:" + x + " y:" + y + " z:" + cellData.getZ() );                        if ((NSEW & EAST) == 0)                        {                            LoS = false;                            break;                        }                    }                }            }        }        //_log.warning("Geodata MLOS stop");        geobuf = geoRequestBuffer.get(objId);        geobuf.hadLoS = LoS;        geobuf.mov_atk =0;        return LoS;    }    public boolean hasAttackLoS(L2Object source, L2Object target)    {        return hasAttackLoS (source.getObjectId(),  source.getX(),source.getY(), (short) source.getZ() , target.getX(), target.getY(), (short) target.getZ());    }    public boolean hasAttackLoS(L2Object source, int targetX , int targetY , int targetZ)    {        return hasAttackLoS (source.getObjectId(), source.getX(), source.getY(), (short) source.getZ() , targetX, targetY, (short)targetZ);    }    public boolean hasAttackLoS(L2Object source, int targetX , int targetY , short targetZ)    {        return hasAttackLoS (source.getObjectId(), source.getX(), source.getY(), (short) source.getZ() , targetX, targetY, targetZ);    }    public boolean hasAttackLoS(int objId, int sourceX, int sourceY, short sourceZ, int targetX , int targetY , short targetZ)    {        float m;        float b;        int x;        int y;        byte NSEW;        short newZ;        boolean LoS;        GeoDataBuffer geobuf;        GeoSubCell cellData;        //_log.warning("Geodata ALOS start");        double range = ((sourceX - targetX)*(sourceX - targetX) + (sourceY - targetY)*(sourceY - targetY));        if (range < 900  && (sourceZ & 0xFFF8) == (targetZ & 0xFFF8))        {            // self / 30 Ticks or mob is 8z ticks away force LOS            return true;        }        geobuf =checkGeoBuffer(objId, sourceX, sourceY, sourceZ, targetX, targetY, targetZ);        if (geobuf != null)        {            if (geobuf.mov_atk == 1)                return geobuf.hadLoS;        }        LoS = true;        newZ =sourceZ;        // avoid / 0 error        if (sourceX != targetX)        {            m = (float) (sourceY - targetY) / (sourceX - targetX);        }        else        {            m =0;        }        b = sourceY - (m*sourceX);        if ( sourceX == targetX ) // vertical line        {            if (sourceY > targetY)  //north            {                newZ =sourceZ;                for (y=sourceY;y > targetY+16;y = y - 16)                {                    cellData = getGeoInfoNearest(sourceX, y & 0xFFFFFFF0,newZ);                    //edge checking                    //if ( cellData.getZ() - newZ > 20 ) // impassable, too high, so get Floor                    //{                    //cellData = getGeoInfoNearestFloor(sourceX, y & 0xFFFFFFF0,newZ);                    //}                    NSEW = cellData.getNSEW();                    newZ =  cellData.getZ();                    //_log.warning("Geodata ALOS x:" + sourceX + " y:" + y + " z:" + cellData.getZ() );                    if ( (NSEW & SOUTH) == 0)                    {                        LoS = false;                        break;                    }                }            }            else            {                newZ =sourceZ;                for (y=sourceY;y < targetY-16;y=y + 16)                {                    cellData = getGeoInfoNearest(sourceX, (y+16) & 0xFFFFFFF0,newZ);                    NSEW = cellData.getNSEW();                    newZ =  cellData.getZ();                    //_log.warning("Geodata ALOS x:" + sourceX + " y:" + y + " z:" + cellData.getZ() );                    if ( (NSEW & NORTH) == 0)                    {                        LoS = false;                        break;                    }                }            }        }        else if (targetY==sourceY)      // Horizontal Line or m=0        {            if (sourceX > targetX)  // west            {                newZ =sourceZ;                for (x=sourceX;x > targetX+16;x=x - 16)                {                    cellData = getGeoInfoNearest(x & 0xFFFFFFF0,sourceY,newZ);                    NSEW = cellData.getNSEW();                    newZ =  cellData.getZ();                    //_log.warning("Geodata ALOS x:" + x + " y:" + sourceY  + " z:" + cellData.getZ() );                    if ( (NSEW & WEST) == 0)                    {                        LoS = false;                        break;                    }                }            }            else // EAST            {                newZ =sourceZ;                for (x=sourceX;x < targetX-16;x=x + 16)                {                    cellData = getGeoInfoNearest((x +16)& 0xFFFFFFF0,sourceY,newZ);                    NSEW = cellData.getNSEW();                    newZ =  cellData.getZ();                    //_log.warning("Geodata ALOS x:" + x + " y:" + sourceY  + " z:" + cellData.getZ() );                    if ( (NSEW & EAST) == 0)                    {                        LoS = false;                        break;                    }                }            }        }        else if (( m > 0 && m <= 1) || ( m < 0 && m >= -1) ) // east west line -- so more X's to verify than Y's        {            if ( sourceX < targetX) // going East            {                newZ =sourceZ;                for (x=sourceX;x < targetX-16 ; x = x + 16)                {                    y = (int)((m*x) + b);                    cellData = getGeoInfoNearest((x + 16) & 0xFFFFFFF0  , y , newZ);                    NSEW = cellData.getNSEW();                    newZ =  cellData.getZ();                    //_log.warning("Geodata ALOS x:" + x + " y:" + y + " z:" + cellData.getZ() );                    if ((NSEW & EAST) == 0)                    {                        LoS = false;                        break;                    }                }                if ( m > 0 ) // North bound                {                    newZ =sourceZ;                    for (y=sourceY;y < targetY-16; y = y + 16)                    {                        x = (int) ((y-b) / m);                        cellData = getGeoInfoNearest( x  , (y + 16) & 0xFFFFFFF0  , newZ);                        NSEW = cellData.getNSEW();                        newZ =  cellData.getZ();                        //_log.warning("Geodata ALOS x:" + x + " y:" + y + " z:" + cellData.getZ() );                        if ((NSEW & NORTH) == 0)                        {                            LoS = false;                            break;                        }                    }                }                else // South Bound                {                    newZ =sourceZ;                    for (y=sourceY;y > targetY+16; y = y - 16)                    {                        x = (int) ((y -b) / m);                        cellData = getGeoInfoNearest( x  , y & 0xFFFFFFF0, newZ);                        NSEW = cellData.getNSEW();                        newZ =  cellData.getZ();                        //_log.warning("Geodata ALOS x:" + x + " y:" + y + " z:" + cellData.getZ() );                        if ((NSEW & SOUTH) == 0)                        {                            LoS = false;                            break;                        }                    }                }            }            else // going West            {                newZ =sourceZ;                for ( x=sourceX;x > targetX+16 ; x = x - 16)                {                    y = (int)((m*x) + b);                    cellData = getGeoInfoNearest( x & 0xFFFFFFF0 ,y , newZ);                    NSEW = cellData.getNSEW();                    newZ =  cellData.getZ();                    //_log.warning("Geodata ALOS x:" + x + " y:" + y + " z:" + cellData.getZ() );                    if ((NSEW & WEST) == 0)                    {                        LoS = false;                        break;                    }                }                if ( m > 0 ) // North                {                    newZ =sourceZ;                    for ( y=sourceY;y < targetY-16; y = y + 16)                    {                        x = (int) ((y-b) / m);                        cellData = getGeoInfoNearest(x  ,(y + 16) & 0xFFFFFFF0 , newZ);                        NSEW = cellData.getNSEW();                        newZ =  cellData.getZ();                        //_log.warning("Geodata ALOS x:" + x + " y:" + y + " z:" + cellData.getZ() );                        if ((NSEW & NORTH) == 0)                        {                            LoS = false;                            break;                        }                    }                }                else // South                {                    newZ =sourceZ;                    for ( y = sourceY;y > targetY+16; y = y - 16)                    {                        x = (int) ((y-b) / m);                        cellData = getGeoInfoNearest( x  , y & 0xFFFFFFF0 , newZ);                        NSEW = cellData.getNSEW();                        newZ =  cellData.getZ();                        //_log.warning("Geodata ALOS x:" + x + " y:" + y + " z:" + cellData.getZ() );                        if ((NSEW & SOUTH) == 0)                        {                            LoS = false;                            break;                        }                    }                }            }        }        else if ( m > 1 || m < -1) //north south line --  so, more y's to verify than x's        {            if (sourceY > targetY) // going north            {                newZ =sourceZ;                for ( y = sourceY ; y > targetY+16 ; y = y - 16)                {                    //y = (m * x) + b;                    x = (int) ((y-b) / m);                    cellData = getGeoInfoNearest( x , y & 0xFFFFFFF0 , newZ);                    NSEW = cellData.getNSEW();                    newZ =  cellData.getZ();                    //_log.warning("Geodata ALOS x:" + x + " y:" + y + " z:" + cellData.getZ() );                    if ((NSEW & NORTH) == 0)                    {                        LoS = false;                        break;                    }                }                if ( m > 0 ) // EAST Bound                {                    newZ =sourceZ;                    for ( x = sourceX;x < targetX-16; x = x + 16)                    {                        y = (int)((m*x)+b);                        cellData = getGeoInfoNearest( (x + 16) & 0xFFFFFFF0  , y , newZ);                        NSEW = cellData.getNSEW();                        newZ =  cellData.getZ();                        //_log.warning("Geodata ALOS x:" + x + " y:" + y + " z:" + cellData.getZ() );                        if ((NSEW & EAST) == 0)                        {                            LoS = false;                            break;                        }                    }                }                else // West Bound                {                    newZ =sourceZ;                    for ( x = sourceX;x > targetX+16; x = x - 16)                    {                        y = (int)((m*x)+b);                        cellData = getGeoInfoNearest( (x + 16) & 0xFFFFFFF0  , y , newZ);                        NSEW = cellData.getNSEW();                        newZ =  cellData.getZ();                        //_log.warning("Geodata ALOS x:" + x + " y:" + y + " z:" + cellData.getZ() );                        if ((NSEW & WEST) == 0)                        {                            LoS = false;                            break;                        }                    }                }            }            else // going South            {                newZ =sourceZ;                for ( y = sourceY ; y < targetY-16; y = y + 16)                {                    //y = (m * x ) + b;                    x =(int) ((y-b)/m);                    cellData = getGeoInfoNearest(x ,(y+16) & 0xFFFFFFF0, newZ);                    NSEW = cellData.getNSEW();                    newZ =  cellData.getZ();                    //_log.warning("Geodata ALOS x:" + x + " y:" + y + " z:" + cellData.getZ() );                    if ((NSEW & SOUTH) == 0)                    {                        LoS = false;                        break;                    }                }                if (m > 0) // WEST bound                {                    newZ =sourceZ;                    for ( x = sourceX;x > targetX+16; x = x - 16)                    {                        y = (int)((m*x)+b);                        cellData = getGeoInfoNearest( x & 0xFFFFFFF0 , y , newZ);                        NSEW = cellData.getNSEW();                        newZ =  cellData.getZ();                        //_log.warning("Geodata ALOS x:" + x + " y:" + y + " z:" + cellData.getZ() );                        if ((NSEW & WEST) == 0)                        {                            LoS = false;                            break;                        }                    }                }                else // EAST bound                {                    newZ =sourceZ;                    for ( x = sourceX;x < targetX-16; x = x + 16)                    {                        y = (int)((m*x)+b);                        cellData = getGeoInfoNearest((x +16) & 0xFFFFFFF0 ,y , newZ);                        NSEW = cellData.getNSEW();                        newZ =  cellData.getZ();                        //_log.warning("Geodata ALOS x:" + x + " y:" + y + " z:" + cellData.getZ() );                        if ((NSEW & EAST) == 0)                        {                            LoS = false;                            break;                        }                    }                }            }        }        //_log.warning("Geodata ALOS stop");        geobuf = geoRequestBuffer.get(objId);        geobuf.hadLoS = LoS;        geobuf.mov_atk = 1;        return LoS;    }    public GeoSubCell getGeoInfoLayer(int x, int y, short z, short layer)    {        // get the Geodata info from the region's geodata where the passed xyz belong.        //System.out.println("Checking cell info...");        GeoBlock geo;        GeoSubCell cell;        geo = getGeoBlock(x,y); //load in mem        if (geo != null) // if got geo file        {            cell = getNearestLayer(geo.geoInnerBlock[(x & CELL_OFFSET) >>> 7][(y & CELL_OFFSET) >>> 7], x ,y, z,layer);            if ( cell != null)            {                return cell;            }        }        GeoSubCell  subcell = new GeoSubCell();        subcell.Z = z;        subcell.NSEW = 15;        return subcell;    }    public GeoSubCell getGeoInfoNearestFloor(int x, int y, short z)    {        // get the Geodata info from the region's geodata where the passed xyz belong.        //System.out.println("Checking cell info...");        GeoBlock geo;        geo = getGeoBlock(x,y); //load in mem        if (geo != null) // if got geo file        {            return getNearestFloorSubcell(geo.geoInnerBlock[(x & CELL_OFFSET) >>> 7][(y & CELL_OFFSET) >>> 7], x ,y, z);        }        GeoSubCell  subcell = new GeoSubCell();        subcell.Z = z;        subcell.NSEW = 15;        return subcell;    }    public GeoSubCell getGeoInfoNearest(int x, int y, short z)    {        GeoBlock geo;        geo = getGeoBlock(x,y); //load in mem        if (geo != null)        {            return getNearestSubcell(geo.geoInnerBlock[(x & CELL_OFFSET) >>> 7][(y & CELL_OFFSET) >>> 7], x ,y, z);        }        GeoSubCell  subcell = new GeoSubCell();        subcell.Z = z;        subcell.NSEW = 15;        return subcell;    }    /*	public Boolean getIsInWater(int x, int y, int z)	{		// get the Geodata info from the region's geodata where the passed xyz belong.			//System.out.println("Checking cell info...");		return _worldRegions[(x >> SHIFT_BY) + OFFSET_X][(y >> SHIFT_BY) + OFFSET_Y].getGeoBlock().						getGeoCell(x & CELL_OFFSET, y & CELL_OFFSET, (short)z).						isWater((x & 0x07F),(y & 0x07F), z);	}     */    private GeoSubCell getNearestSubcell(Cell cell,int x, int y, short z)    {        GeoSubCell subcell;        x = (x & 127) >>>4;        y = (y & 127) >>> 4;        if (cell instanceof CoarseCell )        {            subcell = new GeoSubCell ();            if ( (Math.abs( z -  ((CoarseCell)(cell)).minZ_NSEW)) <= ( z - ((CoarseCell)(cell)).maxZ))            {                subcell.Z =  ((CoarseCell)(cell)).minZ_NSEW;            }            else            {                subcell.Z =  ((CoarseCell)(cell)).maxZ;            }            subcell.NSEW = 15;            return subcell;        }        else if (cell instanceof DetailedCell  )        {            subcell = new GeoSubCell (((DetailedCell)(cell)).NSEW_Z[x][y]);            return subcell;        }        else if ( cell instanceof multiLevelDetailedCell )        {            int layers;            int smallestDist = 9999999;            int smallestValue;            int nearestLayer=0;            int tmpValue;            layers = ((multiLevelDetailedCell)(cell)).NSEW_Z[x][y].layer.length;            for (int i = 0 ; i < layers ; i++)            {                // if this is a valid floor for the passed z value                tmpValue = ((multiLevelDetailedCell)(cell)).NSEW_Z[x][y].layer[i] >>1 & 0xFFFFFFF8 ;            if ( z >= tmpValue)            {                smallestValue = z - tmpValue;            }            else            {                smallestValue = tmpValue-z;            }            if (Math.abs(smallestValue) <= smallestDist)            {                smallestDist = Math.abs(smallestValue);                nearestLayer = i;            }            }            subcell = new GeoSubCell (((multiLevelDetailedCell)(cell)).NSEW_Z[x][y].layer[nearestLayer]);            return subcell;        }        return null;    }    private GeoSubCell getNearestFloorSubcell(Cell cell,int x, int y, short z)    {        GeoSubCell subcell;        x = (x & 127) >>>4;        y = (y & 127) >>> 4;        if (cell instanceof CoarseCell )        {            subcell = new GeoSubCell();            subcell.Z =  ((CoarseCell)(cell)).minZ_NSEW;            subcell.NSEW = 15;            return subcell;        }        else if (cell instanceof DetailedCell  )        {            subcell = new GeoSubCell (((DetailedCell)(cell)).NSEW_Z[x][y]);            return subcell;        }        else if ( cell instanceof multiLevelDetailedCell )        {            int layers;            int smallestDist = 9999999;            int smallestValue;            int nearestLayer=0;            int tmpValue;            layers = ((multiLevelDetailedCell)(cell)).NSEW_Z[x][y].layer.length;            for (int i = 0 ; i < layers ; i++)            {                // if this is a valid floor for the passed z value                tmpValue = (((multiLevelDetailedCell)(cell)).NSEW_Z[x][y].layer[i] >>1) & 0xFFFFFFF8 ;                if (tmpValue < z) // ok looking for floor data                {                    smallestValue =  z - tmpValue;                    if (smallestValue  < smallestDist)                    {                        smallestDist = smallestValue;                        nearestLayer = i;                    }                }            }            subcell = new GeoSubCell (((multiLevelDetailedCell)(cell)).NSEW_Z[x][y].layer[nearestLayer]);            return subcell;        }        return null;    }    private GeoSubCell getNearestLayer(Cell cell,int x, int y, short z, short layer)    {        GeoSubCell subcell;        x = (x & 127) >>>4;                y = (y & 127) >>> 4;                if (cell instanceof CoarseCell)                {                    if (layer == 0)                    {                        subcell = new GeoSubCell ();                        subcell.Z =  ((CoarseCell)(cell)).minZ_NSEW;                        subcell.NSEW = 15;                        return subcell;                    }                    else return null;                }                else if (cell instanceof DetailedCell  )                {                    if (layer == 0)                    {                        subcell = new GeoSubCell (((DetailedCell)(cell)).NSEW_Z[x][y]);                        return subcell;                    }                    else return null;                }                else if ( cell instanceof multiLevelDetailedCell )                {                    int layers;                    layers = ((multiLevelDetailedCell)(cell)).NSEW_Z[x][y].layer.length;                    if (layer < layers)                    {                        subcell = new GeoSubCell (((multiLevelDetailedCell)(cell)).NSEW_Z[x][y].layer[layer]);                        return subcell;                    }                    else return null;                }                return null;    }}