1
0
mirror of https://github.com/Rogiel/l2jserver2 synced 2025-12-09 08:52:51 +00:00

Base AI, new Cache system, DAO changes and better geometry handling

Signed-off-by: Rogiel <rogiel@rogiel.com>
This commit is contained in:
2011-05-27 02:49:15 -03:00
parent aabe375b49
commit 73f51e53c0
95 changed files with 3079 additions and 1884 deletions

View File

@@ -18,7 +18,7 @@ package com.l2jserver;
import com.google.inject.AbstractModule;
import com.google.inject.Module;
import com.l2jserver.db.dao.H2DAOModule;
import com.l2jserver.db.H2DAOModule;
import com.l2jserver.model.id.provider.IDProviderModule;
import com.l2jserver.service.ServiceModule;

View File

@@ -0,0 +1,40 @@
/*
* This file is part of l2jserver <l2jserver.com>.
*
* l2jserver 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 3 of the License, or
* (at your option) any later version.
*
* l2jserver 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 l2jserver. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jserver;
import com.l2jserver.service.ServiceManager;
import com.l2jserver.service.database.DatabaseService;
/**
* @author <a href="http://www.rogiel.com">Rogiel</a>
*
*/
public class Installer {
public static void main(String[] args) {
final L2JGameServer server = new L2JGameServer();
try {
final ServiceManager serviceManager = server.getInjector()
.getInstance(ServiceManager.class);
serviceManager.start(DatabaseService.class).install();
} catch (Exception e) {
System.out.println("GameServer could not be installed!");
e.printStackTrace();
System.exit(0);
}
}
}

View File

@@ -23,16 +23,20 @@ package com.l2jserver.game;
*/
public enum ProtocolVersion {
/**
* Release version
* The Release version, this is acctually a pseudo version. It never really
* existed.
*/
RELEASE(0),
/**
* Freya(216)
* The Interlude(200) version
*/
INTERLUDE(200, RELEASE),
/**
* The Freya(216) version
*/
FREYA(216, RELEASE),
/**
* High5(268)
* The High5(268) version
*/
HIGH5(268, FREYA);

View File

@@ -0,0 +1,39 @@
/*
* This file is part of l2jserver <l2jserver.com>.
*
* l2jserver 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 3 of the License, or
* (at your option) any later version.
*
* l2jserver 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 l2jserver. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jserver.game.ai;
import com.l2jserver.game.ai.desires.Desire;
import com.l2jserver.game.ai.desires.DesireQueue;
import com.l2jserver.model.world.Actor;
/**
* @author <a href="http://www.rogiel.com">Rogiel</a>
* @param <T>
* the {@link Actor} type for this {@link AI}
*/
public abstract class AI<T extends Actor> {
protected DesireQueue desireQueue = new DesireQueue();
protected final T creature;
protected AI(T creature) {
this.creature = creature;
}
protected void handleDesire(Desire desire) {
desire.handleDesire(this);
}
}

View File

@@ -0,0 +1,74 @@
/*
* This file is part of l2jserver <l2jserver.com>.
*
* l2jserver 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 3 of the License, or
* (at your option) any later version.
*
* l2jserver 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 l2jserver. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jserver.game.ai.desires;
/**
* This class implements basic functionality common for each desire
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
* @see com.l2jserver.game.ai.desires.Desire
* @see com.l2jserver.game.ai.desires.DesireQueue
* @see com.l2jserver.game.ai.AI
* @see com.l2jserver.game.ai.AI#handleDesire(Desire)
*/
public abstract class AbstractDesire implements Desire {
/**
* Desire power. It's used to calculate what npc whants to do most of all.
*/
protected int desirePower;
/**
* Creates new desire. By design any desire should have desire power. So
* constructor accepts basic amout.
*
* @param desirePower
* basic amount of desirePower
*/
protected AbstractDesire(int desirePower) {
this.desirePower = desirePower;
}
/**
* Compares this desire with another, used by
* {@link com.l2jserver.game.ai.desires.DesireQueue} to keep track of desire
* priorities.
*
* @param o
* desire to compare with
* @return result of desire comparation
*/
@Override
public int compareTo(Desire o) {
return o.getDesirePower() - getDesirePower();
}
@Override
public int getDesirePower() {
return desirePower;
}
@Override
public synchronized void increaseDesirePower(int desirePower) {
this.desirePower = this.desirePower + desirePower;
}
@Override
public synchronized void reduceDesirePower(int desirePower) {
this.desirePower = this.desirePower - desirePower;
}
}

View File

@@ -0,0 +1,76 @@
/*
* This file is part of l2jserver <l2jserver.com>.
*
* l2jserver 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 3 of the License, or
* (at your option) any later version.
*
* l2jserver 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 l2jserver. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jserver.game.ai.desires;
import com.l2jserver.game.ai.AI;
import com.l2jserver.model.world.Actor;
/**
* This class indicates that character wants to attack somebody
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
public final class AttackDesire extends AbstractDesire {
/**
* Target of this desire
*/
protected final Actor target;
/**
* Creates new attack desire, target can't be changed
*
* @param target
* whom to attack
* @param desirePower
* initial attack power
*/
protected AttackDesire(Actor target, int desirePower) {
super(desirePower);
this.target = target;
}
@Override
public void handleDesire(AI<?> ai) {
// TODO: Implement
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (!(o instanceof AttackDesire))
return false;
AttackDesire that = (AttackDesire) o;
return target.equals(that.target);
}
@Override
public int hashCode() {
return target.hashCode();
}
/**
* Returns target of this desire
*
* @return target of this desire
*/
public Actor getTarget() {
return target;
}
}

View File

@@ -0,0 +1,93 @@
/*
* This file is part of l2jserver <l2jserver.com>.
*
* l2jserver 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 3 of the License, or
* (at your option) any later version.
*
* l2jserver 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 l2jserver. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jserver.game.ai.desires;
import com.l2jserver.game.ai.AI;
/**
* This interface represents basic desire functions.<br>
* Each desire should implement {@link #handleDesire(com.l2jserver.game.ai.AI)}
* method with default behavior.<br>
* AI can override {@link com.l2jserver.game.ai.AI#handleDesire(Desire)} to
* implement custom behavior of desire.<br>
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
* @see com.l2jserver.game.ai.AI
* @see com.l2jserver.game.ai.AI#handleDesire(Desire)
* @see com.l2jserver.game.ai.desires.AbstractDesire
*/
public interface Desire extends Comparable<Desire> {
/**
* Invokes default desire action. AI can override invocation of this method
* to handle desire in it's own way
*
* @param ai
* actor that is doing this desire
*/
void handleDesire(AI<?> ai);
/**
* Returns hashcode for this object, must be overrided by child
*
* @return hashcode for this object
*/
int hashCode();
/**
* Compares this Desire with another object, must overriden by child
*
* @param obj
* another object to compare with
* @return result of object comparation
*/
boolean equals(Object obj);
/**
* Returns desire power of this object
*
* @return desire power of the object
*/
int getDesirePower();
/**
* Adds desire power to this desire, this call is synchronized.<br>
* <br>
* <b>WARNING!!! Changing desire power after adding it to queue will not
* affect it's position, you have to call
* {@link com.l2jserver.game.ai.desires.DesireQueue#addDesire(Desire)}
* passing this instance as argument</b>
*
* @param desirePower
* amount of desirePower to add
* @see DesireQueue#addDesire(Desire)
*/
void increaseDesirePower(int desirePower);
/**
* Reduces desire power by give amount.<br>
* <br>
* <b>WARNING!!! Changing desire power after adding it to queue will not
* affect it's position, you have to call
* {@link com.l2jserver.game.ai.desires.DesireQueue#addDesire(Desire)}
* passing this instance as argument</b>
*
* @param desirePower
* amount of desirePower to substract
* @see DesireQueue#addDesire(Desire)
*/
void reduceDesirePower(int desirePower);
}

View File

@@ -0,0 +1,45 @@
/*
* This file is part of l2jserver <l2jserver.com>.
*
* l2jserver 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 3 of the License, or
* (at your option) any later version.
*
* l2jserver 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 l2jserver. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jserver.game.ai.desires;
/**
* This class represents simple filter for desire iterations.
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
public interface DesireIteratorFilter {
/**
* This method is called each time for every desire that is in the queue.<br>
* <br> {@link java.util.ConcurrentModificationException} will be thrown by
* {@link com.l2jserver.game.ai.desires.DesireQueue#iterateDesires(DesireIteratorHandler, DesireIteratorFilter[])}
* if any of the following methods will be called from here:
* <ul>
* <li>{@link com.l2jserver.game.ai.desires.DesireQueue#addDesire(Desire)}</li>
* <li>{@link com.l2jserver.game.ai.desires.DesireQueue#poll()}</li>
* <li>
* {@link com.l2jserver.game.ai.desires.DesireQueue#removeDesire(Desire)}</li>
* </ul>
* <p/>
* However {@link com.l2jserver.game.ai.desires.DesireQueue#clear()} can be
* called.
*
* @param desire
* current element of iteration that is beeing filtered
* @return true if this filter accepted desire, false otherwise
*/
public boolean isOk(Desire desire);
}

View File

@@ -0,0 +1,55 @@
/*
* This file is part of l2jserver <l2jserver.com>.
*
* l2jserver 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 3 of the License, or
* (at your option) any later version.
*
* l2jserver 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 l2jserver. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jserver.game.ai.desires;
import java.util.Iterator;
/**
* This class is designed to be a helper class for desires.<br>
* Direct access to desire list is not allowed, however this interface can be
* used for iteration.<br>
* <br>
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
* @see com.l2jserver.game.ai.desires.DesireIteratorFilter
* @see com.l2jserver.game.ai.desires.DesireQueue#iterateDesires(DesireIteratorHandler,
* DesireIteratorFilter[])
*/
public interface DesireIteratorHandler {
/**
* This method is called each time for every desire that is in the queue.<br>
* Remove of desire must be handeled by <b>iterator.remove();</b><br>
* <br> {@link java.util.ConcurrentModificationException} will be thrown by
* {@link com.l2jserver.game.ai.desires.DesireQueue#iterateDesires(DesireIteratorHandler, DesireIteratorFilter[])}
* if any of the following methods will be called from here:
* <ul>
* <li>{@link com.l2jserver.game.ai.desires.DesireQueue#addDesire(Desire)}</li>
* <li>{@link com.l2jserver.game.ai.desires.DesireQueue#poll()}</li>
* <li>
* {@link com.l2jserver.game.ai.desires.DesireQueue#removeDesire(Desire)}</li>
* </ul>
* <p/>
* However {@link com.l2jserver.game.ai.desires.DesireQueue#clear()} can be
* called.
*
* @param desire
* current element of iteration
* @param iterator
* iterator object
*/
public void next(Desire desire, Iterator<Desire> iterator);
}

View File

@@ -0,0 +1,212 @@
/*
* This file is part of l2jserver <l2jserver.com>.
*
* l2jserver 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 3 of the License, or
* (at your option) any later version.
*
* l2jserver 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 l2jserver. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jserver.game.ai.desires;
import java.util.ConcurrentModificationException;
import java.util.Iterator;
import java.util.PriorityQueue;
/**
* This class represents desire queue, it's thread-safe. Desires can be added
* and removed. If desire is added - previous desires will be checked, if same
* desire found then desire previous one will be removed from the queue
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
* @see com.l2jserver.game.ai.desires.Desire
* @see com.l2jserver.game.ai.desires.AbstractDesire
*/
public class DesireQueue {
/**
* Prioritized Queue of desires, lazy initialization.
*/
protected PriorityQueue<Desire> queue;
/**
* Returns first element of this queue not removing it. Returns null if
* there is no elements.
*
* @return first element or null
*/
public synchronized Desire peek() {
return queue != null ? queue.peek() : null;
}
/**
* Removes first element from the desires list and removes it. Returns null
* if there are no elements.
*
* @return first element from the desires list or null.
*/
public synchronized Desire poll() {
if (queue != null) {
return queue.poll();
}
return null;
}
/**
* Adds desire to the queue.
* <p/>
* <p/>
* When adding object this method checks first for the same object by
* {@link AbstractDesire#equals(Object)}, if such object found, next actions
* will be done:<br>
* <br>
* 1). Remove old desire instance from the list.<br>
* 2). Check if those desires are same instances by "==".<br>
* 3). If they are not the same instances, add desire power from old
* instance to new instance, if they are - do nothing.<br>
* <br>
* After all add new desire instance to the list.
*
* @param desire
* desire instance to add
*/
public synchronized void addDesire(Desire desire) {
// Lazy initialization of desire queue
if (queue == null) {
queue = new PriorityQueue<Desire>();
}
// Iterate over the list to find similar desires
Iterator<Desire> iterator = queue.iterator();
while (iterator.hasNext()) {
Desire iterated = iterator.next();
// Find similar desires by #equals method, they can be different
// instances.
if (desire.equals(iterated)) {
// Remove the old desire from the list
iterator.remove();
// If current desire instance was not at the list - increase
// it's power by the value of another instance power
// and after that add it to the list
if (desire != iterated) {
desire.increaseDesirePower(iterated.getDesirePower());
}
// Break iteration, desire list can't contain two same desires
break;
}
}
// finally add desire to the list
queue.add(desire);
}
/**
* Removes desire from this desireQueue. If desire was removed successfully
* this method return true, false otherwise
*
* @param desire
* what desire to remove
* @return result of desire removal
*/
public synchronized boolean removeDesire(Desire desire) {
return queue != null && queue.remove(desire);
}
/**
* Iterates over desires, you have to provide iteration handler and
* optionally filters.<br>
* <br>
* Handlers and filters can't call following methods:
* <ul>
* <li>{@link #addDesire(Desire)}</li>
* <li>{@link #poll()}</li>
* <li>{@link #removeDesire(Desire)}</li>
* </ul>
* <p/>
* However, method {@link #clear() can be called}.
*
* @param handler
* DesireIterationhandler that will be called on the iteration
* @param filters
* optional filters that will prevent passing unneeded desires to
* the handler
* @throws java.util.ConcurrentModificationException
* only if called handler or filter modified this queue
* @see com.l2jserver.game.ai.desires.DesireIteratorFilter
* @see com.l2jserver.game.ai.desires.DesireIteratorFilter#isOk(Desire)
* @see com.l2jserver.game.ai.desires.DesireIteratorHandler
* @see com.l2jserver.game.ai.desires.DesireIteratorHandler#next(Desire ,
* java.util.Iterator)
*/
public synchronized void iterateDesires(DesireIteratorHandler handler,
DesireIteratorFilter... filters)
throws ConcurrentModificationException {
if (queue == null) {
return;
}
Iterator<Desire> iterator = queue.iterator();
outer: while (iterator.hasNext()) {
Desire desire = iterator.next();
if (filters != null && filters.length > 0) {
for (DesireIteratorFilter filter : filters) {
if (!filter.isOk(desire)) {
continue outer;
}
}
}
handler.next(desire, iterator);
}
}
/**
* Returns true if this desire list contains same desire. Desires are
* compared by {@link AbstractDesire#equals(Object)} method.
*
* @param desire
* what desire to search
* @return true if there is equal desire, false in other case.
*/
public synchronized boolean contains(Desire desire) {
return queue.contains(desire);
}
/**
* Returns true if this NPC has no any desires added
*
* @return true if this NPC has no any desires added
*/
public synchronized boolean isEmpty() {
return queue == null || queue.isEmpty();
}
/**
* Clears all desires
*/
public synchronized void clear() {
if (queue != null) {
queue.clear();
}
}
/**
* Returns size of the desire list
*
* @return size of remaining desires
*/
public synchronized int size() {
return queue == null ? 0 : queue.size();
}
}

View File

@@ -0,0 +1,83 @@
/*
* This file is part of l2jserver <l2jserver.com>.
*
* l2jserver 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 3 of the License, or
* (at your option) any later version.
*
* l2jserver 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 l2jserver. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jserver.game.ai.desires;
import com.l2jserver.game.ai.AI;
import com.l2jserver.model.world.Actor;
import com.l2jserver.util.geometry.Point3D;
/**
* This class indicates that {@link Actor} wants to move somewhere
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
public final class MoveDesire extends AbstractDesire {
/**
* Target of this desire
*/
protected final Point3D point;
/**
* Creates new move desire. Target can't be changed
*
* @param point
* where to move
* @param desirePower
* initial attack power
*/
protected MoveDesire(Point3D point, int desirePower) {
super(desirePower);
this.point = point;
}
@Override
public void handleDesire(AI<?> ai) {
// TODO: Implement
}
/**
* {@inheritDoc}
*/
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (!(o instanceof MoveDesire))
return false;
MoveDesire that = (MoveDesire) o;
return point.equals(that.point);
}
/**
* {@inheritDoc}
*/
@Override
public int hashCode() {
return point.hashCode();
}
/**
* Returns target of this desire
*
* @return target of this desire
*/
public Point3D getTarget() {
return point;
}
}

View File

@@ -27,7 +27,7 @@ import com.l2jserver.service.game.spawn.CharacterAlreadyTeleportingServiceExcept
import com.l2jserver.service.game.spawn.NotSpawnedServiceException;
import com.l2jserver.service.game.spawn.SpawnService;
import com.l2jserver.util.BufferUtils;
import com.l2jserver.util.dimensional.Coordinate;
import com.l2jserver.util.geometry.Coordinate;
/**
* Executes an administrator action

View File

@@ -27,7 +27,7 @@ import com.l2jserver.model.id.object.provider.ObjectIDResolver;
import com.l2jserver.model.world.NPC;
import com.l2jserver.service.game.npc.ActionServiceException;
import com.l2jserver.service.game.npc.NPCService;
import com.l2jserver.util.dimensional.Coordinate;
import com.l2jserver.util.geometry.Coordinate;
/**
* Executes an action from an character to an NPC

View File

@@ -33,7 +33,7 @@ import com.l2jserver.service.game.character.ActorIsNotAttackableServiceException
import com.l2jserver.service.game.character.CannotSetTargetServiceException;
import com.l2jserver.service.game.character.CharacterService;
import com.l2jserver.service.game.npc.NotAttackableNPCServiceException;
import com.l2jserver.util.dimensional.Coordinate;
import com.l2jserver.util.geometry.Coordinate;
/**
* Completes the creation of an character. Creates the object, inserts into the

View File

@@ -26,7 +26,7 @@ import com.l2jserver.game.net.packet.AbstractClientPacket;
import com.l2jserver.game.net.packet.server.CharacterStopMovePacket;
import com.l2jserver.model.world.L2Character;
import com.l2jserver.service.game.character.CharacterService;
import com.l2jserver.util.dimensional.Coordinate;
import com.l2jserver.util.geometry.Coordinate;
/**
* This packet notifies the server which character the player has chosen to use.

View File

@@ -22,7 +22,7 @@ import com.google.inject.Inject;
import com.l2jserver.game.net.Lineage2Connection;
import com.l2jserver.game.net.packet.AbstractClientPacket;
import com.l2jserver.service.game.character.CharacterService;
import com.l2jserver.util.dimensional.Point;
import com.l2jserver.util.geometry.Point3D;
/**
* This packet notifies the server which character the player has chosen to use.
@@ -40,7 +40,7 @@ public class CharacterValidatePositionPacket extends AbstractClientPacket {
*/
private final CharacterService charService;
private Point point;
private Point3D point;
@SuppressWarnings("unused")
private int extra; // vehicle id
@@ -51,7 +51,7 @@ public class CharacterValidatePositionPacket extends AbstractClientPacket {
@Override
public void read(Lineage2Connection conn, ChannelBuffer buffer) {
point = Point.fromXYZA(buffer.readInt(), buffer.readInt(),
point = Point3D.fromXYZA(buffer.readInt(), buffer.readInt(),
buffer.readInt(), buffer.readInt());
extra = buffer.readInt();
}

View File

@@ -21,7 +21,7 @@ import org.jboss.netty.buffer.ChannelBuffer;
import com.l2jserver.game.net.Lineage2Connection;
import com.l2jserver.game.net.packet.AbstractServerPacket;
import com.l2jserver.model.world.Actor;
import com.l2jserver.util.dimensional.Coordinate;
import com.l2jserver.util.geometry.Coordinate;
/**
* This packet notifies the client that the character is moving to an certain

View File

@@ -22,7 +22,7 @@ import com.l2jserver.game.net.Lineage2Connection;
import com.l2jserver.game.net.packet.AbstractServerPacket;
import com.l2jserver.game.net.packet.server.CharacterCreateFailPacket.Reason;
import com.l2jserver.model.world.L2Character;
import com.l2jserver.util.dimensional.Point;
import com.l2jserver.util.geometry.Point3D;
/**
* This packet notifies the client that the chosen character has been
@@ -44,9 +44,9 @@ public class CharacterTeleportPacket extends AbstractServerPacket {
/**
* The teleportation point
*/
private final Point point;
private final Point3D point;
public CharacterTeleportPacket(L2Character character, Point point) {
public CharacterTeleportPacket(L2Character character, Point3D point) {
super(OPCODE);
this.character = character;
this.point = point;

View File

@@ -28,7 +28,7 @@ import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import com.l2jserver.model.id.template.ItemTemplateID;
import com.l2jserver.model.id.template.TeleportationTemplateID;
import com.l2jserver.util.dimensional.Coordinate;
import com.l2jserver.util.geometry.Coordinate;
import com.l2jserver.util.jaxb.CoordinateAdapter;
import com.l2jserver.util.jaxb.ItemTemplateIDAdapter;
import com.l2jserver.util.jaxb.TeleportationTemplateIDAdapter;

View File

@@ -31,7 +31,7 @@ import com.l2jserver.model.world.character.CharacterFriendList;
import com.l2jserver.model.world.character.CharacterInventory;
import com.l2jserver.model.world.character.CharacterShortcutContainer;
import com.l2jserver.model.world.character.CharacterStats;
import com.l2jserver.util.dimensional.Point;
import com.l2jserver.util.geometry.Point3D;
/**
* This class represents a playable character in Lineage II world.
@@ -179,7 +179,7 @@ public class L2Character extends Player {
/**
* The point the player is moving, teleporting etc...
*/
private transient Point targetLocation;
private transient Point3D targetLocation;
/**
* Creates a new instance
@@ -502,7 +502,7 @@ public class L2Character extends Player {
/**
* @return the targetLocation
*/
public Point getTargetLocation() {
public Point3D getTargetLocation() {
return targetLocation;
}
@@ -510,7 +510,7 @@ public class L2Character extends Player {
* @param targetLocation
* the targetLocation to set
*/
public void setTargetLocation(Point targetLocation) {
public void setTargetLocation(Point3D targetLocation) {
this.targetLocation = targetLocation;
}

View File

@@ -16,8 +16,8 @@
*/
package com.l2jserver.model.world;
import com.l2jserver.util.dimensional.Coordinate;
import com.l2jserver.util.dimensional.Point;
import com.l2jserver.util.geometry.Coordinate;
import com.l2jserver.util.geometry.Point3D;
/**
* This is an abstract object that objects that can be placed in world should
@@ -29,12 +29,12 @@ public abstract class PositionableObject extends AbstractObject {
/**
* The point this object is currently in
*/
private Point point;
private Point3D point;
/**
* @return the coordinate point
*/
public Point getPoint() {
public Point3D getPoint() {
return point;
}
@@ -42,7 +42,7 @@ public abstract class PositionableObject extends AbstractObject {
* @param point
* the coordinate point to set
*/
public void setPoint(Point point) {
public void setPoint(Point3D point) {
this.point = point;
}
@@ -51,6 +51,6 @@ public abstract class PositionableObject extends AbstractObject {
}
public void setPosition(Coordinate coord) {
this.point = new Point(coord, (point != null ? point.getAngle() : 0));
this.point = new Point3D(coord, (point != null ? point.getAngle() : 0));
}
}

View File

@@ -20,7 +20,7 @@ import com.l2jserver.model.id.ObjectID;
import com.l2jserver.model.world.Actor;
import com.l2jserver.model.world.WorldObject;
import com.l2jserver.model.world.event.SpawnEvent;
import com.l2jserver.util.dimensional.Point;
import com.l2jserver.util.geometry.Point3D;
/**
* Event dispatcher once an actor has spawned in the world
@@ -35,7 +35,7 @@ public class ActorSpawnEvent implements ActorEvent, SpawnEvent {
/**
* The spawning point
*/
private final Point point;
private final Point3D point;
/**
* Creates a new instance
@@ -45,7 +45,7 @@ public class ActorSpawnEvent implements ActorEvent, SpawnEvent {
* @param point
* the spawn point
*/
public ActorSpawnEvent(Actor actor, Point point) {
public ActorSpawnEvent(Actor actor, Point3D point) {
this.actor = actor;
this.point = point;
}
@@ -61,7 +61,7 @@ public class ActorSpawnEvent implements ActorEvent, SpawnEvent {
}
@Override
public Point getPoint() {
public Point3D getPoint() {
return point;
}

View File

@@ -21,7 +21,7 @@ import com.l2jserver.model.world.Actor;
import com.l2jserver.model.world.L2Character;
import com.l2jserver.model.world.Player;
import com.l2jserver.model.world.WorldObject;
import com.l2jserver.util.dimensional.Point;
import com.l2jserver.util.geometry.Point3D;
/**
* Event triggered once a character moves
@@ -36,7 +36,7 @@ public class CharacterMoveEvent implements CharacterEvent {
/**
* The old point of the character
*/
private final Point point;
private final Point3D point;
/**
* Creates a new instance
@@ -46,7 +46,7 @@ public class CharacterMoveEvent implements CharacterEvent {
* @param point
* the character point before moving
*/
public CharacterMoveEvent(L2Character character, Point point) {
public CharacterMoveEvent(L2Character character, Point3D point) {
this.character = character;
this.point = point;
}
@@ -54,7 +54,7 @@ public class CharacterMoveEvent implements CharacterEvent {
/**
* @return the old point
*/
public Point getPoint() {
public Point3D getPoint() {
return point;
}

View File

@@ -21,7 +21,7 @@ import com.l2jserver.model.world.Actor;
import com.l2jserver.model.world.L2Character;
import com.l2jserver.model.world.Player;
import com.l2jserver.model.world.WorldObject;
import com.l2jserver.util.dimensional.Point;
import com.l2jserver.util.geometry.Point3D;
/**
* Event triggered once a character moves
@@ -36,7 +36,7 @@ public class CharacterStopMoveEvent implements CharacterEvent {
/**
* The new point of the character
*/
private final Point point;
private final Point3D point;
/**
* Creates a new instance
@@ -46,7 +46,7 @@ public class CharacterStopMoveEvent implements CharacterEvent {
* @param point
* the character point
*/
public CharacterStopMoveEvent(L2Character character, Point point) {
public CharacterStopMoveEvent(L2Character character, Point3D point) {
this.character = character;
this.point = point;
}
@@ -54,7 +54,7 @@ public class CharacterStopMoveEvent implements CharacterEvent {
/**
* @return the point
*/
public Point getPoint() {
public Point3D getPoint() {
return point;
}

View File

@@ -17,7 +17,7 @@
package com.l2jserver.model.world.event;
import com.l2jserver.service.game.world.event.WorldEvent;
import com.l2jserver.util.dimensional.Point;
import com.l2jserver.util.geometry.Point3D;
/**
* Event for objects spawning
@@ -28,5 +28,5 @@ public interface SpawnEvent extends WorldEvent {
/**
* @return the spawning point
*/
Point getPoint();
Point3D getPoint();
}

View File

@@ -18,7 +18,7 @@ package com.l2jserver.model.world.npc.event;
import com.l2jserver.model.world.NPC;
import com.l2jserver.model.world.actor.event.ActorSpawnEvent;
import com.l2jserver.util.dimensional.Point;
import com.l2jserver.util.geometry.Point3D;
/**
* Event dispatched once a {@link NPC} has spawned in the world.
@@ -32,7 +32,7 @@ public class NPCSpawnEvent extends ActorSpawnEvent implements NPCEvent {
* @param point
* the spawn point
*/
public NPCSpawnEvent(NPC npc, Point point) {
public NPCSpawnEvent(NPC npc, Point3D point) {
super(npc, point);
}

View File

@@ -18,7 +18,7 @@ package com.l2jserver.model.world.player.event;
import com.l2jserver.model.world.Player;
import com.l2jserver.model.world.actor.event.ActorSpawnEvent;
import com.l2jserver.util.dimensional.Point;
import com.l2jserver.util.geometry.Point3D;
/**
* Event dispatcher once an player has spawned in the world
@@ -32,7 +32,7 @@ public class PlayerSpawnEvent extends ActorSpawnEvent implements PlayerEvent {
* @param point
* the spawn point
*/
public PlayerSpawnEvent(Player player, Point point) {
public PlayerSpawnEvent(Player player, Point3D point) {
super(player, point);
}

View File

@@ -17,7 +17,7 @@
package com.l2jserver.model.world.player.event;
import com.l2jserver.model.world.Player;
import com.l2jserver.util.dimensional.Point;
import com.l2jserver.util.geometry.Point3D;
/**
* Event dispatched once an player has completed its teleportation to another
@@ -34,7 +34,7 @@ public class PlayerTeleportedEvent extends PlayerSpawnEvent {
* @param point
* the teleport point
*/
public PlayerTeleportedEvent(Player player, Point point) {
public PlayerTeleportedEvent(Player player, Point3D point) {
super(player, point);
}
}

View File

@@ -20,7 +20,7 @@ import com.l2jserver.model.id.ObjectID;
import com.l2jserver.model.world.Actor;
import com.l2jserver.model.world.Player;
import com.l2jserver.model.world.WorldObject;
import com.l2jserver.util.dimensional.Point;
import com.l2jserver.util.geometry.Point3D;
/**
* Event dispatched once an player has started his teleported to another
@@ -30,7 +30,7 @@ import com.l2jserver.util.dimensional.Point;
*/
public class PlayerTeleportingEvent implements PlayerEvent {
private final Player player;
private final Point point;
private final Point3D point;
/**
* Creates a new instance
@@ -40,7 +40,7 @@ public class PlayerTeleportingEvent implements PlayerEvent {
* @param point
* the teleport point
*/
public PlayerTeleportingEvent(Player player, Point point) {
public PlayerTeleportingEvent(Player player, Point3D point) {
this.player = player;
this.point = point;
}
@@ -65,7 +65,7 @@ public class PlayerTeleportingEvent implements PlayerEvent {
*
* @return the teleported point
*/
public Point getPoint() {
public Point3D getPoint() {
return point;
}

View File

@@ -0,0 +1,113 @@
/*
* This file is part of l2jserver <l2jserver.com>.
*
* l2jserver 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 3 of the License, or
* (at your option) any later version.
*
* l2jserver 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 l2jserver. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jserver.service.cache;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.l2jserver.service.cache.SoftCacheService.SoftCache;
import com.l2jserver.util.factory.CollectionFactory;
import com.sun.beans.WeakCache;
/**
* Base class for {@link WeakCache} and {@link SoftCache}
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*
* @param <K>
* the key type
* @param <V>
* the value type
*/
abstract class AbstractReferenceCache<K, V> implements Cache<K, V> {
protected final Logger log = LoggerFactory.getLogger(this.getClass());
/**
* The cache name
*/
protected final String cacheName;
/**
* Map storing references to cached objects
*/
protected final Map<K, Reference<V>> cacheMap = CollectionFactory.newMap();
/**
* The reference queue
*/
protected final ReferenceQueue<V> refQueue = CollectionFactory
.newReferenceQueue();
/**
* @param cacheName
* the cache name
*/
protected AbstractReferenceCache(String cacheName) {
this.cacheName = cacheName;
}
@Override
public void put(K key, V value) {
cleanQueue();
Reference<V> entry = newReference(key, value, refQueue);
cacheMap.put(key, entry);
log.debug("{}: added for key: {}", cacheName, key);
}
@Override
public V get(K key) {
cleanQueue();
Reference<V> reference = cacheMap.get(key);
if (reference == null)
return null;
V res = reference.get();
if (res != null)
log.debug("{}: obtained for key: {}", cacheName, key);
return res;
}
@Override
public boolean contains(K key) {
cleanQueue();
return cacheMap.containsKey(key);
}
protected abstract void cleanQueue();
@Override
public void remove(K key) {
cacheMap.remove(key);
log.debug("{}: removed for key: {}", cacheName, key);
}
@Override
public void clear() {
cacheMap.clear();
log.debug("{}: cleared", cacheName);
}
protected abstract Reference<V> newReference(K key, V value,
ReferenceQueue<V> queue);
}

View File

@@ -0,0 +1,64 @@
/*
* This file is part of l2jserver <l2jserver.com>.
*
* l2jserver 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 3 of the License, or
* (at your option) any later version.
*
* l2jserver 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 l2jserver. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jserver.service.cache;
/**
* This interface represents a Map structure for cache usage.
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
public interface Cache<K, V> {
/**
* Adds a pair <key,value> to cache.<br>
* <br>
*
* <font color='red'><b>NOTICE:</b> </font> if there is already a value with
* given id in the map, {@link IllegalArgumentException} will be thrown.
*
* @param key
* @param value
*/
void put(K key, V value);
/**
* Returns cached value correlated to given key.
*
* @param key
* @return
*/
V get(K key);
/**
* Checks whether this map contains a value related to given key.
*
* @param key
* @return
*/
boolean contains(K key);
/**
* Removes an entry from the map, that has given key.
*
* @param key
*/
void remove(K key);
/**
* Clears this cache
*/
void clear();
}

View File

@@ -16,8 +16,6 @@
*/
package com.l2jserver.service.cache;
import net.sf.ehcache.Cache;
import com.l2jserver.service.Service;
/**
@@ -31,7 +29,6 @@ import com.l2jserver.service.Service;
* {@link IgnoreCaching}
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*
*/
public interface CacheService extends Service {
/**
@@ -50,39 +47,60 @@ public interface CacheService extends Service {
/**
* Creates a new cache with default configurations. Eviction mode is LRU
* (Last Recently Used). If you wish more customization, you should manually
* create the cache and register it using {@link #register(Cache)}.
* (Last Recently Used). The size is only a guarantee that you can store
* <b>at least</b> <tt>n</tt> items.
*
* @param <K>
* the cache key type
* @param <V>
* the cache value type
* @param name
* the cache name
* @size the maximum cache size
* @return the created cache
*/
Cache createCache(String name, int size);
<K, V> Cache<K, V> createCache(String name, int size);
/**
* Creates a new eternal cache with default configurations. An eternal cache
* is guaranteed to never automatically expire items. The size is only a
* guarantee that you can store <b>at least</b> <tt>n</tt> items.
*
* @param <K>
* the cache key type
* @param <V>
* the cache value type
* @param name
* the cache name
* @size the maximum cache size
* @return the created cache
*/
<K, V> Cache<K, V> createEternalCache(String name, int size);
/**
* Creates a new cache with default configurations. The default cache size
* is 200.
* is 200. The size is only a guarantee that you can store <b>at least</b>
* 200 items.
*
* @param <K>
* the cache key type
* @param <V>
* the cache value type
* @param name
* the cache name
* @return the created cache
*/
Cache createCache(String name);
<K, V> Cache<K, V> createCache(String name);
/**
* Registers a new cache
* Disposes the cache. Once the cache is disposed it cannot be used anymore.
*
* @param <K>
* the cache key type
* @param <V>
* the cache value type
* @param cache
* the cache
*/
void register(Cache cache);
/**
* Unregisters an already registered cache
*
* @param cache
* the cache
*/
void unregister(Cache cache);
<K, V> void dispose(Cache<K, V> cache);
}

View File

@@ -20,9 +20,7 @@ import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Element;
import net.sf.ehcache.config.CacheConfiguration;
@@ -48,7 +46,7 @@ public class EhCacheService extends AbstractService implements CacheService {
/**
* The interface cache
*/
private Cache interfaceCache;
private Cache<MethodInvocation, Object> interfaceCache;
@Override
protected void doStart() throws ServiceStartException {
@@ -76,10 +74,7 @@ public class EhCacheService extends AbstractService implements CacheService {
return method.invoke(instance, args);
final MethodInvocation invocation = new MethodInvocation(
method, args);
Element element = interfaceCache.get(invocation);
if (element == null)
return doInvoke(invocation, proxy, method, args);
Object result = element.getObjectValue();
Object result = interfaceCache.get(invocation);
if (result == null)
return doInvoke(invocation, proxy, method, args);
return result;
@@ -90,43 +85,94 @@ public class EhCacheService extends AbstractService implements CacheService {
throws IllegalArgumentException,
IllegalAccessException, InvocationTargetException {
Object result = method.invoke(instance, args);
interfaceCache.put(new Element(invocation, result));
interfaceCache.put(invocation, result);
return result;
}
});
return proxy;
}
// @Override
// public Cache createCache(String name, int size) {
// Preconditions.checkNotNull(name, "name");
// Preconditions.checkArgument(size > 0, "size <= 0");
//
// Cache cache = new Cache(new CacheConfiguration(name, size)
// .memoryStoreEvictionPolicy(MemoryStoreEvictionPolicy.LRU)
// .overflowToDisk(true).eternal(false).timeToLiveSeconds(60)
// .timeToIdleSeconds(30).diskPersistent(false)
// .diskExpiryThreadIntervalSeconds(0));
// register(cache);
// return cache;
// }
//
// @Override
// public Cache createCache(String name) {
// Preconditions.checkNotNull(name, "name");
// return createCache(name, 200);
// }
//
// @Override
// public void register(Cache cache) {
// Preconditions.checkNotNull(cache, "cache");
// manager.addCache(cache);
// }
//
// @Override
// public void unregister(Cache cache) {
// Preconditions.checkNotNull(cache, "cache");
// manager.removeCache(cache.getName());
// }
@Override
public Cache createCache(String name, int size) {
public <K, V> Cache<K, V> createCache(String name, int size) {
Preconditions.checkNotNull(name, "name");
Preconditions.checkArgument(size > 0, "size <= 0");
Cache cache = new Cache(new CacheConfiguration(name, size)
.memoryStoreEvictionPolicy(MemoryStoreEvictionPolicy.LRU)
.overflowToDisk(true).eternal(false).timeToLiveSeconds(60)
.timeToIdleSeconds(30).diskPersistent(false)
.diskExpiryThreadIntervalSeconds(0));
register(cache);
return cache;
}
@Override
public Cache createCache(String name) {
Preconditions.checkNotNull(name, "name");
return createCache(name, 200);
}
@Override
public void register(Cache cache) {
Preconditions.checkNotNull(cache, "cache");
net.sf.ehcache.Cache cache = new net.sf.ehcache.Cache(
new CacheConfiguration(name, size)
.memoryStoreEvictionPolicy(
MemoryStoreEvictionPolicy.LRU)
.overflowToDisk(true).eternal(false)
.timeToLiveSeconds(60).timeToIdleSeconds(30)
.diskPersistent(false)
.diskExpiryThreadIntervalSeconds(0));
manager.addCache(cache);
return new EhCacheFacade<K, V>(cache);
}
@Override
public void unregister(Cache cache) {
Preconditions.checkNotNull(cache, "cache");
manager.removeCache(cache.getName());
public <K, V> Cache<K, V> createEternalCache(String name, int size) {
Preconditions.checkNotNull(name, "name");
Preconditions.checkArgument(size > 0, "size <= 0");
net.sf.ehcache.Cache cache = new net.sf.ehcache.Cache(
new CacheConfiguration(name, size)
.memoryStoreEvictionPolicy(
MemoryStoreEvictionPolicy.LRU)
.overflowToDisk(true).eternal(true)
.diskExpiryThreadIntervalSeconds(0));
manager.addCache(cache);
return new EhCacheFacade<K, V>(cache);
}
@Override
public <K, V> Cache<K, V> createCache(String name) {
net.sf.ehcache.Cache cache = new net.sf.ehcache.Cache(
new CacheConfiguration(name, 200)
.memoryStoreEvictionPolicy(
MemoryStoreEvictionPolicy.LRU)
.overflowToDisk(true).eternal(true)
.diskExpiryThreadIntervalSeconds(0));
manager.addCache(cache);
return new EhCacheFacade<K, V>(cache);
}
@Override
public <K, V> void dispose(Cache<K, V> cache) {
if (cache instanceof EhCacheFacade) {
manager.removeCache(((EhCacheFacade<K, V>) cache).cache.getName());
}
}
@Override
@@ -136,42 +182,40 @@ public class EhCacheService extends AbstractService implements CacheService {
interfaceCache = null;
}
private static class MethodInvocation {
private final Method method;
private final Object[] args;
private class EhCacheFacade<K, V> implements Cache<K, V> {
private final net.sf.ehcache.Cache cache;
public MethodInvocation(Method method, Object[] args) {
this.method = method;
this.args = args;
public EhCacheFacade(net.sf.ehcache.Cache cache) {
this.cache = cache;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + Arrays.hashCode(args);
result = prime * result
+ ((method == null) ? 0 : method.hashCode());
return result;
public void put(K key, V value) {
cache.put(new Element(key, value));
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
MethodInvocation other = (MethodInvocation) obj;
if (!Arrays.equals(args, other.args))
return false;
if (method == null) {
if (other.method != null)
return false;
} else if (!method.equals(other.method))
return false;
return true;
@SuppressWarnings("unchecked")
public V get(K key) {
final Element element = cache.get(key);
if (element == null)
return null;
return (V) element.getValue();
}
@Override
public boolean contains(K key) {
return cache.get(key) != null;
}
@Override
public void remove(K key) {
cache.remove(key);
}
@Override
public void clear() {
cache.removeAll();
}
}
}

View File

@@ -0,0 +1,87 @@
/*
* This file is part of l2jserver <l2jserver.com>.
*
* l2jserver 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 3 of the License, or
* (at your option) any later version.
*
* l2jserver 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 l2jserver. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jserver.service.cache;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.l2jserver.util.factory.CollectionFactory;
/**
* Cache class for an eternal cache
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*
* @param <K>
* the key type
* @param <V>
* the value type
*/
class EternalCache<K, V> implements Cache<K, V> {
protected final Logger log = LoggerFactory.getLogger(this.getClass());
/**
* The cache name
*/
protected final String cacheName;
/**
* Map storing references to cached objects
*/
protected final Map<K, V> cacheMap = CollectionFactory.newMap();
/**
* @param cacheName
* the cache name
*/
protected EternalCache(String cacheName) {
this.cacheName = cacheName;
}
@Override
public void put(K key, V value) {
cacheMap.put(key, value);
log.debug("{}: added for key: {}", cacheName, key);
}
@Override
public V get(K key) {
V obj = cacheMap.get(key);
if (obj != null)
log.debug("{}: obtained for key: {}", cacheName, key);
return obj;
}
@Override
public boolean contains(K key) {
return cacheMap.containsKey(key);
}
@Override
public void remove(K key) {
cacheMap.remove(key);
log.debug("{}: removed for key: {}", cacheName, key);
}
@Override
public void clear() {
cacheMap.clear();
log.debug("{}: cleared", cacheName);
}
}

View File

@@ -0,0 +1,69 @@
/*
* This file is part of l2jserver <l2jserver.com>.
*
* l2jserver 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 3 of the License, or
* (at your option) any later version.
*
* l2jserver 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 l2jserver. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jserver.service.cache;
import java.lang.reflect.Method;
import java.util.Arrays;
/**
* Simple class used to store method invocations for the proxied cache.
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
class MethodInvocation {
/**
* The invoked method
*/
private final Method method;
/**
* The invocation arguments
*/
private final Object[] args;
public MethodInvocation(Method method, Object[] args) {
this.method = method;
this.args = args;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + Arrays.hashCode(args);
result = prime * result + ((method == null) ? 0 : method.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
MethodInvocation other = (MethodInvocation) obj;
if (!Arrays.equals(args, other.args))
return false;
if (method == null) {
if (other.method != null)
return false;
} else if (!method.equals(other.method))
return false;
return true;
}
}

View File

@@ -0,0 +1,164 @@
/*
* This file is part of l2jserver <l2jserver.com>.
*
* l2jserver 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 3 of the License, or
* (at your option) any later version.
*
* l2jserver 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 l2jserver. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jserver.service.cache;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import com.google.common.base.Preconditions;
import com.l2jserver.service.AbstractService;
import com.l2jserver.service.ServiceStartException;
import com.l2jserver.service.ServiceStopException;
/**
* This {@link Cache} service implementation uses a {@link SoftReference} to
* store values.
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
public class SoftCacheService extends AbstractService implements CacheService {
/**
* The interface cache
*/
private Cache<MethodInvocation, Object> interfaceCache;
@Override
protected void doStart() throws ServiceStartException {
interfaceCache = createCache("interface-cache");
}
@Override
public <T extends Cacheable> T decorate(final Class<T> interfaceType,
final T instance) {
Preconditions.checkNotNull(interfaceType, "interfaceType");
Preconditions.checkNotNull(instance, "instance");
if (!interfaceType.isInterface())
return null;
@SuppressWarnings("unchecked")
final T proxy = (T) Proxy.newProxyInstance(this.getClass()
.getClassLoader(), new Class[] { interfaceType },
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method,
Object[] args) throws Throwable {
if (method.isAnnotationPresent(IgnoreCaching.class))
return method.invoke(instance, args);
final MethodInvocation invocation = new MethodInvocation(
method, args);
Object result = interfaceCache.get(invocation);
if (result == null)
return doInvoke(invocation, proxy, method, args);
return result;
}
private Object doInvoke(MethodInvocation invocation,
Object proxy, Method method, Object[] args)
throws IllegalArgumentException,
IllegalAccessException, InvocationTargetException {
Object result = method.invoke(instance, args);
interfaceCache.put(invocation, result);
return result;
}
});
return proxy;
}
@Override
public <K, V> Cache<K, V> createCache(String name, int size) {
return new SoftCache<K, V>(name);
}
@Override
public <K, V> Cache<K, V> createEternalCache(String name, int size) {
return new EternalCache<K, V>(name);
}
@Override
public <K, V> Cache<K, V> createCache(String name) {
return new SoftCache<K, V>(name);
}
@Override
public <K, V> void dispose(Cache<K, V> cache) {
cache.clear();
}
@Override
protected void doStop() throws ServiceStopException {
dispose(interfaceCache);
interfaceCache = null;
}
/**
* This class is a simple map implementation for cache usage.<br>
* <br>
* Value may be stored in map really long, but it for sure will be removed
* if there is low memory (and of course there isn't any strong reference to
* value object)
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
public class SoftCache<K, V> extends AbstractReferenceCache<K, V> implements
Cache<K, V> {
/**
* This class is a {@link SoftReference} with additional responsibility
* of holding key object
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
private class SoftEntry extends SoftReference<V> {
private K key;
SoftEntry(K key, V referent, ReferenceQueue<? super V> q) {
super(referent, q);
this.key = key;
}
K getKey() {
return key;
}
}
public SoftCache(String cacheName) {
super(cacheName);
}
@Override
@SuppressWarnings("unchecked")
protected synchronized void cleanQueue() {
SoftEntry en = null;
while ((en = (SoftEntry) refQueue.poll()) != null) {
K key = en.getKey();
if (log.isDebugEnabled())
log.debug("{} : cleaned up {} for key: {}", cacheName, key);
cacheMap.remove(key);
}
}
@Override
protected Reference<V> newReference(K key, V value,
ReferenceQueue<V> vReferenceQueue) {
return new SoftEntry(key, value, vReferenceQueue);
}
}
}

View File

@@ -0,0 +1,164 @@
/*
* This file is part of l2jserver <l2jserver.com>.
*
* l2jserver 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 3 of the License, or
* (at your option) any later version.
*
* l2jserver 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 l2jserver. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jserver.service.cache;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import com.google.common.base.Preconditions;
import com.l2jserver.service.AbstractService;
import com.l2jserver.service.ServiceStartException;
import com.l2jserver.service.ServiceStopException;
/**
* This {@link Cache} service implementation uses a {@link SoftReference} to
* store values.
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
public class WeakCacheService extends AbstractService implements CacheService {
/**
* The interface cache
*/
private Cache<MethodInvocation, Object> interfaceCache;
@Override
protected void doStart() throws ServiceStartException {
interfaceCache = createCache("interface-cache");
}
@Override
public <T extends Cacheable> T decorate(final Class<T> interfaceType,
final T instance) {
Preconditions.checkNotNull(interfaceType, "interfaceType");
Preconditions.checkNotNull(instance, "instance");
if (!interfaceType.isInterface())
return null;
@SuppressWarnings("unchecked")
final T proxy = (T) Proxy.newProxyInstance(this.getClass()
.getClassLoader(), new Class[] { interfaceType },
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method,
Object[] args) throws Throwable {
if (method.isAnnotationPresent(IgnoreCaching.class))
return method.invoke(instance, args);
final MethodInvocation invocation = new MethodInvocation(
method, args);
Object result = interfaceCache.get(invocation);
if (result == null)
return doInvoke(invocation, proxy, method, args);
return result;
}
private Object doInvoke(MethodInvocation invocation,
Object proxy, Method method, Object[] args)
throws IllegalArgumentException,
IllegalAccessException, InvocationTargetException {
Object result = method.invoke(instance, args);
interfaceCache.put(invocation, result);
return result;
}
});
return proxy;
}
@Override
public <K, V> Cache<K, V> createCache(String name, int size) {
return new WeakCache<K, V>(name);
}
@Override
public <K, V> Cache<K, V> createEternalCache(String name, int size) {
return new EternalCache<K, V>(name);
}
@Override
public <K, V> Cache<K, V> createCache(String name) {
return new WeakCache<K, V>(name);
}
@Override
public <K, V> void dispose(Cache<K, V> cache) {
cache.clear();
}
@Override
protected void doStop() throws ServiceStopException {
dispose(interfaceCache);
interfaceCache = null;
}
/**
* This class is a simple map implementation for cache usage.<br>
* <br>
* Values from the map will be removed after the first garbage collector run
* if there isn't any strong reference to the value object.
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
private class WeakCache<K, V> extends AbstractReferenceCache<K, V>
implements Cache<K, V> {
/**
* This class is a {@link WeakReference} with additional responsibility
* of holding key object
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
private class Entry extends WeakReference<V> {
private K key;
Entry(K key, V referent, ReferenceQueue<? super V> q) {
super(referent, q);
this.key = key;
}
K getKey() {
return key;
}
}
WeakCache(String cacheName) {
super(cacheName);
}
@Override
@SuppressWarnings("unchecked")
protected synchronized void cleanQueue() {
Entry en = null;
while ((en = (Entry) refQueue.poll()) != null) {
K key = en.getKey();
if (log.isDebugEnabled())
log.debug("{}: cleaned up for key: {}", cacheName, key);
cacheMap.remove(key);
}
}
@Override
protected Reference<V> newReference(K key, V value,
ReferenceQueue<V> vReferenceQueue) {
return new Entry(key, value, vReferenceQueue);
}
}
}

View File

@@ -28,11 +28,6 @@ import java.util.List;
import javax.sql.DataSource;
import net.sf.ehcache.Cache;
import net.sf.ehcache.Element;
import net.sf.ehcache.config.CacheConfiguration;
import net.sf.ehcache.store.MemoryStoreEvictionPolicy;
import org.apache.commons.dbcp.ConnectionFactory;
import org.apache.commons.dbcp.DriverManagerConnectionFactory;
import org.apache.commons.dbcp.PoolableConnectionFactory;
@@ -53,6 +48,7 @@ import com.l2jserver.service.AbstractService;
import com.l2jserver.service.AbstractService.Depends;
import com.l2jserver.service.ServiceStartException;
import com.l2jserver.service.ServiceStopException;
import com.l2jserver.service.cache.Cache;
import com.l2jserver.service.cache.CacheService;
import com.l2jserver.service.configuration.ConfigurationService;
import com.l2jserver.service.core.LoggingService;
@@ -105,7 +101,7 @@ public class JDBCDatabaseService extends AbstractService implements
/**
* An cache object
*/
private Cache objectCache;
private Cache<Object, Object> objectCache;
@Inject
public JDBCDatabaseService(ConfigurationService configService,
@@ -125,12 +121,8 @@ public class JDBCDatabaseService extends AbstractService implements
// cache must be large enough for all world objects, to avoid
// duplication... this would endanger non-persistent states
objectCache = new Cache(new CacheConfiguration("database-service",
IDAllocator.ALLOCABLE_IDS)
.memoryStoreEvictionPolicy(MemoryStoreEvictionPolicy.LRU)
.overflowToDisk(true).eternal(true).diskPersistent(false)
.diskExpiryThreadIntervalSeconds(0));
cacheService.register(objectCache);
objectCache = cacheService.createEternalCache("database-service",
IDAllocator.ALLOCABLE_IDS);
}
@Override
@@ -186,21 +178,18 @@ public class JDBCDatabaseService extends AbstractService implements
public Object getCachedObject(Object id) {
Preconditions.checkNotNull(id, "id");
final Element element = objectCache.get(id);
if (element == null)
return null;
return element.getObjectValue();
return objectCache.get(id);
}
public boolean hasCachedObject(Object id) {
Preconditions.checkNotNull(id, "id");
return objectCache.get(id) != null;
return objectCache.contains(id);
}
public void updateCache(Object key, Object value) {
Preconditions.checkNotNull(key, "key");
Preconditions.checkNotNull(value, "value");
objectCache.put(new Element(key, value));
objectCache.put(key, value);
}
public void removeCache(Object key) {
@@ -210,8 +199,7 @@ public class JDBCDatabaseService extends AbstractService implements
@Override
protected void doStop() throws ServiceStopException {
if (objectCache != null)
objectCache.dispose();
cacheService.dispose(objectCache);
objectCache = null;
try {

View File

@@ -18,7 +18,7 @@ package com.l2jserver.service.game.ai;
import com.l2jserver.model.world.Actor;
import com.l2jserver.service.Service;
import com.l2jserver.util.dimensional.Coordinate;
import com.l2jserver.util.geometry.Coordinate;
/**
* This service executes AI operations

View File

@@ -27,7 +27,7 @@ import com.l2jserver.service.game.template.TemplateService;
import com.l2jserver.service.game.world.WorldService;
import com.l2jserver.service.game.world.event.WorldEventDispatcher;
import com.l2jserver.service.network.NetworkService;
import com.l2jserver.util.dimensional.Coordinate;
import com.l2jserver.util.geometry.Coordinate;
/**
* Default implementation for {@link AIService}.

View File

@@ -18,7 +18,7 @@ package com.l2jserver.service.game.ai.script;
import com.l2jserver.model.world.PositionableObject;
import com.l2jserver.service.game.ai.AIScript;
import com.l2jserver.util.dimensional.Coordinate;
import com.l2jserver.util.geometry.Coordinate;
/**
* @author <a href="http://www.rogiel.com">Rogiel</a

View File

@@ -23,8 +23,8 @@ import com.l2jserver.service.game.npc.NotAttackableNPCServiceException;
import com.l2jserver.service.game.spawn.AlreadySpawnedServiceException;
import com.l2jserver.service.game.spawn.NotSpawnedServiceException;
import com.l2jserver.service.game.spawn.SpawnPointNotFoundServiceException;
import com.l2jserver.util.dimensional.Coordinate;
import com.l2jserver.util.dimensional.Point;
import com.l2jserver.util.geometry.Coordinate;
import com.l2jserver.util.geometry.Point3D;
/**
* This service manages {@link L2Character} instances
@@ -132,7 +132,7 @@ public interface CharacterService extends Service {
* @param point
* the validated point
*/
void validate(L2Character character, Point point);
void validate(L2Character character, Point3D point);
/**
* Called when received the validation of the position of an character
@@ -142,7 +142,7 @@ public interface CharacterService extends Service {
* @param point
* the validated point
*/
void receivedValidation(L2Character character, Point point);
void receivedValidation(L2Character character, Point3D point);
/**
* Set the character to walking mode

View File

@@ -74,8 +74,8 @@ import com.l2jserver.service.game.world.filter.impl.IDFilter;
import com.l2jserver.service.game.world.filter.impl.KnownListFilter;
import com.l2jserver.service.game.world.filter.impl.KnownListUpdateFilter;
import com.l2jserver.service.network.NetworkService;
import com.l2jserver.util.dimensional.Coordinate;
import com.l2jserver.util.dimensional.Point;
import com.l2jserver.util.geometry.Coordinate;
import com.l2jserver.util.geometry.Point3D;
/**
* Default implementation for {@link CharacterService}.
@@ -417,21 +417,21 @@ public class CharacterServiceImpl extends AbstractService implements
}
@Override
public void validate(L2Character character, Point point) {
public void validate(L2Character character, Point3D point) {
Preconditions.checkNotNull(character, "character");
Preconditions.checkNotNull(point, "point");
// TODO implement position validation
}
@Override
public void receivedValidation(L2Character character, Point point) {
public void receivedValidation(L2Character character, Point3D point) {
Preconditions.checkNotNull(character, "character");
Preconditions.checkNotNull(point, "point");
if (character.isTeleporting())
// ignore while teleporting, for some reason the client sends a
// validation just before teleport packet
return;
final Point old = character.getPoint();
final Point3D old = character.getPoint();
character.setPoint(point);
eventDispatcher.dispatch(new CharacterMoveEvent(character, old));

View File

@@ -37,8 +37,8 @@ import com.l2jserver.service.game.character.CharacterService;
import com.l2jserver.service.game.world.WorldService;
import com.l2jserver.service.game.world.event.TypedWorldListener;
import com.l2jserver.service.game.world.event.WorldEventDispatcher;
import com.l2jserver.util.dimensional.Coordinate;
import com.l2jserver.util.dimensional.Point;
import com.l2jserver.util.geometry.Coordinate;
import com.l2jserver.util.geometry.Point3D;
/**
* <h1>This implementation does not validate pathing!</h1>
@@ -97,7 +97,7 @@ public class MapperPathingService extends AbstractService implements
CharacterMoveEvent.class) {
@Override
protected boolean dispatch(CharacterMoveEvent e) {
final Point point = e.getPoint();
final Point3D point = e.getPoint();
final CoordinateStruct struct = CoordinateStruct
.fromCoordinate(point.getCoordinate());
try {

View File

@@ -24,8 +24,8 @@ import com.l2jserver.model.world.event.SpawnEvent;
import com.l2jserver.model.world.player.event.PlayerTeleportedEvent;
import com.l2jserver.model.world.player.event.PlayerTeleportingEvent;
import com.l2jserver.service.Service;
import com.l2jserver.util.dimensional.Coordinate;
import com.l2jserver.util.dimensional.Point;
import com.l2jserver.util.geometry.Coordinate;
import com.l2jserver.util.geometry.Point3D;
/**
* This service is responsible for spawning monsters, npcs and players.
@@ -50,7 +50,7 @@ public interface SpawnService extends Service {
* @throws AlreadySpawnedServiceException
* if the object is already spawned in the world
*/
void spawn(PositionableObject object, Point point)
void spawn(PositionableObject object, Point3D point)
throws SpawnPointNotFoundServiceException,
AlreadySpawnedServiceException;

View File

@@ -37,8 +37,8 @@ import com.l2jserver.service.AbstractService.Depends;
import com.l2jserver.service.game.world.WorldService;
import com.l2jserver.service.game.world.event.WorldEventDispatcher;
import com.l2jserver.service.network.NetworkService;
import com.l2jserver.util.dimensional.Coordinate;
import com.l2jserver.util.dimensional.Point;
import com.l2jserver.util.geometry.Coordinate;
import com.l2jserver.util.geometry.Point3D;
/**
* Default implementation for {@link SpawnService}
@@ -69,7 +69,7 @@ public class SpawnServiceImpl extends AbstractService implements SpawnService {
}
@Override
public void spawn(PositionableObject object, Point point)
public void spawn(PositionableObject object, Point3D point)
throws SpawnPointNotFoundServiceException {
Preconditions.checkNotNull(object, "object");
// sanitize

View File

@@ -96,11 +96,6 @@ public class ScriptTemplateService extends AbstractService implements
// TODO templates.remove(t);
}
@Override
public void reload() {
context.reload();
}
@Override
protected void doStop() throws ServiceStopException {
if (context.isInitialized())

View File

@@ -31,9 +31,4 @@ public interface TemplateService extends Service {
* @return the template
*/
<T extends Template<?>> T getTemplate(TemplateID<T, ?> id);
/**
* Reload the template list.
*/
void reload();
}

View File

@@ -19,7 +19,6 @@ package com.l2jserver.service.game.template;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Map;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
@@ -46,22 +45,25 @@ import com.l2jserver.service.AbstractService;
import com.l2jserver.service.AbstractService.Depends;
import com.l2jserver.service.ServiceStartException;
import com.l2jserver.service.ServiceStopException;
import com.l2jserver.service.cache.Cache;
import com.l2jserver.service.cache.CacheService;
import com.l2jserver.service.configuration.ConfigurationService;
import com.l2jserver.service.core.LoggingService;
import com.l2jserver.service.core.vfs.VFSService;
import com.l2jserver.util.factory.CollectionFactory;
import com.l2jserver.util.jaxb.CharacterTemplateIDAdapter;
import com.l2jserver.util.jaxb.ItemTemplateIDAdapter;
import com.l2jserver.util.jaxb.NPCTemplateIDAdapter;
import com.l2jserver.util.jaxb.TeleportationTemplateIDAdapter;
import com.l2jserver.util.vfs.ExtensionFileSelector;
@Depends({ LoggingService.class, VFSService.class, ConfigurationService.class })
@Depends({ LoggingService.class, VFSService.class, CacheService.class,
ConfigurationService.class })
public class XMLTemplateService extends AbstractService implements
TemplateService {
private final Logger log = LoggerFactory.getLogger(this.getClass());
private final VFSService vfsService;
private final CacheService cacheService;
private final XMLTemplateServiceConfiguration config;
private final NPCTemplateIDAdapter npcTemplateIdAdapter;
@@ -73,16 +75,17 @@ public class XMLTemplateService extends AbstractService implements
private Unmarshaller unmarshaller;
@SuppressWarnings("rawtypes")
private Map<TemplateID, Template> templates = CollectionFactory.newMap();
private Cache<TemplateID, Template> templates;
@Inject
public XMLTemplateService(final VFSService vfsService,
ConfigurationService configService,
CacheService cacheService, ConfigurationService configService,
NPCTemplateIDAdapter npcTemplateIdAdapter,
ItemTemplateIDAdapter itemTemplateIdAdapter,
CharacterTemplateIDAdapter charIdTemplateAdapter,
TeleportationTemplateIDAdapter teleportationIdTemplateAdapter) {
this.vfsService = vfsService;
this.cacheService = cacheService;
this.config = configService.get(XMLTemplateServiceConfiguration.class);
this.npcTemplateIdAdapter = npcTemplateIdAdapter;
this.itemTemplateIdAdapter = itemTemplateIdAdapter;
@@ -92,6 +95,7 @@ public class XMLTemplateService extends AbstractService implements
@Override
protected void doStart() throws ServiceStartException {
templates = cacheService.createEternalCache("templates", 100 * 1000);
try {
log.debug("Creating JAXBContext instance");
context = JAXBContext.newInstance(CharacterTemplate.class,
@@ -112,9 +116,9 @@ public class XMLTemplateService extends AbstractService implements
final FileObject root = vfsService.resolve(config
.getTemplateDirectory());
log.info("Scanning {} for XML templates", root);
FileObject[] files = root.findFiles(ExtensionFileSelector
.ext("xml"));
@@ -167,15 +171,10 @@ public class XMLTemplateService extends AbstractService implements
templates.remove(template.getID());
}
@Override
public void reload() {
// TODO Auto-generated method stub
}
@Override
protected void doStop() throws ServiceStopException {
templates.clear();
cacheService.dispose(templates);
templates = null;
unmarshaller = null;
context = null;
}

View File

@@ -18,11 +18,6 @@ package com.l2jserver.service.game.world;
import java.util.Collection;
import net.sf.ehcache.Cache;
import net.sf.ehcache.Element;
import net.sf.ehcache.config.CacheConfiguration;
import net.sf.ehcache.store.MemoryStoreEvictionPolicy;
import com.google.common.base.Preconditions;
import com.google.inject.Inject;
import com.l2jserver.db.dao.CharacterDAO;
@@ -35,6 +30,7 @@ import com.l2jserver.service.AbstractService;
import com.l2jserver.service.AbstractService.Depends;
import com.l2jserver.service.ServiceStartException;
import com.l2jserver.service.ServiceStopException;
import com.l2jserver.service.cache.Cache;
import com.l2jserver.service.cache.CacheService;
import com.l2jserver.service.database.DatabaseService;
@@ -73,7 +69,7 @@ public class CachedWorldIDService extends AbstractService implements
/**
* The ID cache
*/
private Cache cache;
private Cache<Integer, ObjectID<?>> cache;
/**
* The loaded state
@@ -94,12 +90,8 @@ public class CachedWorldIDService extends AbstractService implements
@Override
protected void doStart() throws ServiceStartException {
// we allocate an cache which can fit all ids
cache = new Cache(new CacheConfiguration("id-cache",
IDAllocator.ALLOCABLE_IDS)
.memoryStoreEvictionPolicy(MemoryStoreEvictionPolicy.LRU)
.overflowToDisk(true).eternal(true).diskPersistent(false)
.diskExpiryThreadIntervalSeconds(0));
cacheService.register(cache);
cache = cacheService.createEternalCache("id-cache",
IDAllocator.ALLOCABLE_IDS);
}
@Override
@@ -112,7 +104,7 @@ public class CachedWorldIDService extends AbstractService implements
@Override
public void unload() {
cache.removeAll();
cache.clear();
}
/**
@@ -137,17 +129,13 @@ public class CachedWorldIDService extends AbstractService implements
// ignore resolving before all IDs are loaded
return null;
}
final Element element = cache.get(id);
if (element == null)
return null;
return (I) element.getObjectValue();
return (I) cache.get(id);
}
@Override
public <I extends ObjectID<?>> void add(I id) {
Preconditions.checkNotNull(id, "id");
cache.put(new Element(id.getID(), id));
cache.put(id.getID(), id);
}
@Override
@@ -158,7 +146,7 @@ public class CachedWorldIDService extends AbstractService implements
@Override
protected void doStop() throws ServiceStopException {
cacheService.unregister(cache);
cacheService.dispose(cache);
cache = null;
allocator.clear();
}

View File

@@ -20,7 +20,7 @@ import com.l2jserver.model.world.PositionableObject;
import com.l2jserver.model.world.WorldObject;
import com.l2jserver.service.game.world.filter.AndFilter;
import com.l2jserver.service.game.world.filter.NotFilter;
import com.l2jserver.util.dimensional.Point;
import com.l2jserver.util.geometry.Point3D;
/**
* This filter will only accept {@link WorldObject} which are in vision of
@@ -32,7 +32,7 @@ public class KnownListUpdateFilter extends AndFilter<PositionableObject> {
public static final int KNOWNLIST_RANGE = 2000;
@SuppressWarnings("unchecked")
public KnownListUpdateFilter(PositionableObject object, Point old) {
public KnownListUpdateFilter(PositionableObject object, Point3D old) {
super(new KnownListFilter(object), new NotFilter<PositionableObject>(
new RangePointFilter(old, KNOWNLIST_RANGE)));
}

View File

@@ -19,7 +19,7 @@ package com.l2jserver.service.game.world.filter.impl;
import com.google.common.base.Preconditions;
import com.l2jserver.model.world.PositionableObject;
import com.l2jserver.service.game.world.filter.WorldObjectFilter;
import com.l2jserver.util.dimensional.Point;
import com.l2jserver.util.geometry.Point3D;
/**
* Filter objects that are in the <tt>range</tt> of <tt>coordinate</tt>
@@ -30,7 +30,7 @@ public class RangePointFilter implements WorldObjectFilter<PositionableObject> {
/**
* The coordinate point
*/
private final Point point;
private final Point3D point;
/**
* The desired maximum distance of the object
*/
@@ -44,7 +44,7 @@ public class RangePointFilter implements WorldObjectFilter<PositionableObject> {
* @param range
* the desired maximum distance of the object
*/
public RangePointFilter(final Point point, final int range) {
public RangePointFilter(final Point3D point, final int range) {
Preconditions.checkNotNull(point, "point");
Preconditions.checkState(range >= 0, "range < 0");
this.point = point;

View File

@@ -0,0 +1,211 @@
/*
* This file is part of l2jserver <l2jserver.com>.
*
* l2jserver 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 3 of the License, or
* (at your option) any later version.
*
* l2jserver 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 l2jserver. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jserver.util;
import com.l2jserver.util.geometry.Point;
import com.l2jserver.util.geometry.Point3D;
/**
* Class with basic math.<br>
* Thanks to:
* <ul>
* <li>http://geom-java.sourceforge.net/</li>
* <li>
* http://local.wasp.uwa.edu.au/~pbourke/geometry/pointline/DistancePoint.java</li>
* </ul>
* <br>
* <br>
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
public class MathUtil {
/**
* Returns distance between two 2D points
*
* @param point1
* first point
* @param point2
* second point
* @return distance between points
*/
public static double getDistance(Point point1, Point point2) {
return getDistance(point1.x, point1.y, point2.x, point2.y);
}
/**
* Returns distance between two sets of coords
*
* @param x1
* first x coord
* @param y1
* first y coord
* @param x2
* second x coord
* @param y2
* second y coord
* @return distance between sets of coords
*/
public static double getDistance(int x1, int y1, int x2, int y2) {
// using long to avoid possible overflows when multiplying
long dx = x2 - x1;
long dy = y2 - y1;
// return Math.hypot(x2 - x1, y2 - y1); // Extremely slow
// return Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)); // 20 times faster
// than hypot
return Math.sqrt(dx * dx + dy * dy); // 10 times faster then previous
// line
}
/**
* Returns distance between two 3D points
*
* @param point1
* first point
* @param point2
* second point
* @return distance between points
*/
public static double getDistance(Point3D point1, Point3D point2) {
return getDistance(point1.getX(), point1.getY(), point1.getZ(),
point2.getX(), point2.getY(), point2.getZ());
}
/**
* Returns distance between 3D set of coords
*
* @param x1
* first x coord
* @param y1
* first y coord
* @param z1
* first z coord
* @param x2
* second x coord
* @param y2
* second y coord
* @param z2
* second z coord
* @return distance between coords
*/
public static double getDistance(float x1, float y1, float z1, float x2,
float y2, float z2) {
float dx = x1 - x2;
float dy = y1 - y2;
float dz = z1 - z2;
// We should avoid Math.pow or Math.hypot due to performance reasons
return Math.sqrt(dx * dx + dy * dy + dz * dz);
}
/**
* Returns closest point on segment to point
*
* @param ss
* segment start point
* @param se
* segment end point
* @param p
* point to found closest point on segment
* @return closest point on segment to p
*/
public static Point getClosestPointOnSegment(Point ss, Point se, Point p) {
return getClosestPointOnSegment(ss.x, ss.y, se.x, se.y, p.x, p.y);
}
/**
* Returns closest point on segment to point
*
* @param sx1
* segment x coord 1
* @param sy1
* segment y coord 1
* @param sx2
* segment x coord 2
* @param sy2
* segment y coord 2
* @param px
* point x coord
* @param py
* point y coord
* @return closets point on segment to point
*/
public static Point getClosestPointOnSegment(int sx1, int sy1, int sx2,
int sy2, int px, int py) {
double xDelta = sx2 - sx1;
double yDelta = sy2 - sy1;
if ((xDelta == 0) && (yDelta == 0)) {
throw new IllegalArgumentException(
"Segment start equals segment end");
}
double u = ((px - sx1) * xDelta + (py - sy1) * yDelta)
/ (xDelta * xDelta + yDelta * yDelta);
final Point closestPoint;
if (u < 0) {
closestPoint = new Point(sx1, sy1);
} else if (u > 1) {
closestPoint = new Point(sx2, sy2);
} else {
closestPoint = new Point((int) Math.round(sx1 + u * xDelta),
(int) Math.round(sy1 + u * yDelta));
}
return closestPoint;
}
/**
* Returns distance to segment
*
* @param ss
* segment start point
* @param se
* segment end point
* @param p
* point to found closest point on segment
* @return distance to segment
*/
public static double getDistanceToSegment(Point ss, Point se, Point p) {
return getDistanceToSegment(ss.x, ss.y, se.x, se.y, p.x, p.y);
}
/**
* Returns distance to segment
*
* @param sx1
* segment x coord 1
* @param sy1
* segment y coord 1
* @param sx2
* segment x coord 2
* @param sy2
* segment y coord 2
* @param px
* point x coord
* @param py
* point y coord
* @return distance to segment
*/
public static double getDistanceToSegment(int sx1, int sy1, int sx2,
int sy2, int px, int py) {
Point closestPoint = getClosestPointOnSegment(sx1, sy1, sx2, sy2, px,
py);
return getDistance(closestPoint.x, closestPoint.y, px, py);
}
}

View File

@@ -16,6 +16,7 @@
*/
package com.l2jserver.util.factory;
import java.lang.ref.ReferenceQueue;
import java.util.Collection;
import java.util.List;
import java.util.Map;
@@ -81,6 +82,15 @@ public class CollectionFactory {
return new PriorityQueue<T>();
}
/**
* Creates a new reference queue of type <tt>T</tt>
*
* @return the created queue
*/
public static final <T> ReferenceQueue<T> newReferenceQueue() {
return new ReferenceQueue<T>();
}
/**
* Creates a new map.
*

View File

@@ -0,0 +1,125 @@
/*
* This file is part of l2jserver <l2jserver.com>.
*
* l2jserver 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 3 of the License, or
* (at your option) any later version.
*
* l2jserver 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 l2jserver. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jserver.util.geometry;
/**
* Class with basic method implementation for areas.<br>
* If possible it should be subclassed. <br>
* In other case {@link Area} should be implemented directly
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
public abstract class AbstractArea implements Area {
/**
* Minimal z of area
*/
private final int minZ;
/**
* Maximal Z of area
*/
private final int maxZ;
/**
* Creates new AbstractArea with min and max z
*
* @param minZ
* min z
* @param maxZ
* max z
*/
protected AbstractArea(int minZ, int maxZ) {
if (minZ > maxZ) {
throw new IllegalArgumentException("minZ(" + minZ + ") > maxZ("
+ maxZ + ")");
}
this.minZ = minZ;
this.maxZ = maxZ;
}
@Override
public boolean isInside2D(Point point) {
return isInside2D(point.x, point.y);
}
@Override
public boolean isInside3D(Point3D point) {
return isInside3D(point.getX(), point.getY(), point.getZ());
}
@Override
public boolean isInside3D(int x, int y, int z) {
return isInsideZ(z) && isInside2D(x, y);
}
@Override
public boolean isInsideZ(Point3D point) {
return isInsideZ(point.getZ());
}
@Override
public boolean isInsideZ(int z) {
return z >= getMinZ() && z <= getMaxZ();
}
@Override
public double getDistance2D(Point point) {
return getDistance2D(point.x, point.y);
}
@Override
public double getDistance3D(Point3D point) {
return getDistance3D(point.getX(), point.getY(), point.getZ());
}
@Override
public Point getClosestPoint(Point point) {
return getClosestPoint(point.x, point.y);
}
@Override
public Point3D getClosestPoint(Point3D point) {
return getClosestPoint(point.getX(), point.getY(), point.getZ());
}
@Override
public Point3D getClosestPoint(int x, int y, int z) {
Point closest2d = getClosestPoint(x, y);
int zCoord;
if (isInsideZ(z)) {
zCoord = z;
} else if (z < getMinZ()) {
zCoord = getMinZ();
} else {
zCoord = getMaxZ();
}
return new Point3D(closest2d.x, closest2d.y, zCoord);
}
@Override
public int getMinZ() {
return minZ;
}
@Override
public int getMaxZ() {
return maxZ;
}
}

View File

@@ -0,0 +1,196 @@
/*
* This file is part of l2jserver <l2jserver.com>.
*
* l2jserver 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 3 of the License, or
* (at your option) any later version.
*
* l2jserver 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 l2jserver. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jserver.util.geometry;
/**
* Basic interface for all areas.<br>
* It should be implemented in different ways for performance reasons.<br>
* For instance, we don't need complex math for squares or circles, but we need
* it for more complex polygons.
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
public interface Area {
/**
* Returns true if point is inside area ignoring z value
*
* @param point
* point to check
* @return point is inside or not
*/
boolean isInside2D(Point point);
/**
* Returns true if coords are inside area ignoring z value
*
* @param x
* x coord
* @param y
* y coord
* @return coords are inside or not
*/
boolean isInside2D(int x, int y);
/**
* Returns true if point is inside area
*
* @param point
* point to check
* @return true if point is inside
*/
boolean isInside3D(Point3D point);
/**
* Returns true if coors are inside area
*
* @param x
* x coord
* @param y
* y coord
* @param z
* z coord
* @return true if coords are inside
*/
boolean isInside3D(int x, int y, int z);
/**
* Checks if z coord is insize
*
* @param point
* point to check
* @return is z inside or not
*/
boolean isInsideZ(Point3D point);
/**
* Checks is z coord is inside
*
* @param z
* z coord
* @return is z inside or not
*/
boolean isInsideZ(int z);
/**
* Returns distance from point to closest point of this area ignoring z.<br>
* Returns 0 if point is inside area.
*
* @param point
* point to calculate distance from
* @return distance or 0 if is inside area
*/
double getDistance2D(Point point);
/**
* Returns distance from point to closest point of this area ignoring z.<br>
* Returns 0 point is inside area.
*
* @param x
* x coord
* @param y
* y coord
* @return distance or 0 if is inside area
*/
double getDistance2D(int x, int y);
/**
* Returns distance from point to this area.<br>
* Returns 0 if is inside.
*
* @param point
* point to check
* @return distance or 0 if is inside
*/
double getDistance3D(Point3D point);
/**
* Returns distance from coords to this area
*
* @param x
* x coord
* @param y
* y coord
* @param z
* z coord
* @return distance or 0 if is inside
*/
double getDistance3D(int x, int y, int z);
/**
* Returns closest point of area to given point.<br>
* Returns point with coords = point arg if is inside
*
* @param point
* point to check
* @return closest point
*/
Point getClosestPoint(Point point);
/**
* Returns closest point of area to given coords.<br>
* Returns point with coords x and y if coords are inside
*
* @param x
* x coord
* @param y
* y coord
* @return closest point
*/
Point getClosestPoint(int x, int y);
/**
* Returns closest point of area to given point.<br>
* Works exactly like {@link #getClosestPoint(int, int)} if
* {@link #isInsideZ(int)} returns true.<br>
* In other case closest z edge is set as z coord.
*
* @param point
* point to check
* @return closest point of area to point
*/
Point3D getClosestPoint(Point3D point);
/**
* Returns closest point of area to given coords.<br>
* Works exactly like {@link #getClosestPoint(int, int)} if
* {@link #isInsideZ(int)} returns true.<br>
* In other case closest z edge is set as z coord.
*
* @param x
* x coord
* @param y
* y coord
* @param z
* z coord
* @return closest point of area to point
*/
Point3D getClosestPoint(int x, int y, int z);
/**
* Return minimal z of this area
*
* @return minimal z of this area
*/
int getMinZ();
/**
* Returns maximal z of this area
*
* @return maximal z of this area
*/
int getMaxZ();
}

View File

@@ -14,7 +14,7 @@
* You should have received a copy of the GNU General Public License
* along with l2jserver. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jserver.util.dimensional;
package com.l2jserver.util.geometry;
import org.apache.commons.math.geometry.Vector3D;
@@ -91,7 +91,7 @@ public class Coordinate {
return "Coordinate [" + vector + "]";
}
public Point toPoint() {
return new Point(this, 0);
public Point3D toPoint() {
return new Point3D(this, 0);
}
}

View File

@@ -0,0 +1,122 @@
/*
* This file is part of l2jserver <l2jserver.com>.
*
* l2jserver 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 3 of the License, or
* (at your option) any later version.
*
* l2jserver 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 l2jserver. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jserver.util.geometry;
import com.l2jserver.util.MathUtil;
/**
* This class implements cylinder area
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
public class CylinderArea extends AbstractArea {
/**
* Center of cylinder
*/
private final int centerX;
/**
* Center of cylinder
*/
private final int centerY;
/**
* Cylinder radius
*/
private final int radius;
/**
* Creates new cylinder with given radius
*
* @param center
* center of the circle
* @param radius
* radius of the circle
* @param minZ
* min z
* @param maxZ
* max z
*/
public CylinderArea(Point center, int radius, int minZ, int maxZ) {
this(center.x, center.y, radius, minZ, maxZ);
}
/**
* Creates new cylider with given radius
*
* @param x
* center coord
* @param y
* center coord
* @param radius
* radius of the circle
* @param minZ
* min z
* @param maxZ
* max z
*/
public CylinderArea(int x, int y, int radius, int minZ, int maxZ) {
super(minZ, maxZ);
this.centerX = x;
this.centerY = y;
this.radius = radius;
}
@Override
public boolean isInside2D(int x, int y) {
return MathUtil.getDistance(centerX, centerY, x, y) < radius;
}
@Override
public double getDistance2D(int x, int y) {
if (isInside2D(x, y)) {
return 0;
} else {
return Math.abs(MathUtil.getDistance(centerX, centerY, x, y)
- radius);
}
}
@Override
public double getDistance3D(int x, int y, int z) {
if (isInside3D(x, y, z)) {
return 0;
} else if (isInsideZ(z)) {
return getDistance2D(x, y);
} else {
if (z < getMinZ()) {
return MathUtil.getDistance(centerX, centerY, getMinZ(), x, y,
z);
} else {
return MathUtil.getDistance(centerX, centerY, getMaxZ(), x, y,
z);
}
}
}
@Override
public Point getClosestPoint(int x, int y) {
if (isInside2D(x, y)) {
return new Point(x, y);
} else {
int vX = x - this.centerX;
int vY = y - this.centerY;
double magV = MathUtil.getDistance(centerX, centerY, x, y);
double pointX = centerX + vX / magV * radius;
double pointY = centerY + vY / magV * radius;
return new Point((int) Math.round(pointX), (int) Math.round(pointY));
}
}
}

View File

@@ -0,0 +1,50 @@
/*
* This file is part of l2jserver <l2jserver.com>.
*
* l2jserver 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 3 of the License, or
* (at your option) any later version.
*
* l2jserver 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 l2jserver. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jserver.util.geometry;
/**
* An two dimensional point
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
public class Point {
/**
* The X axis
*/
public final int x;
/**
* The Y axis
*/
public final int y;
/**
* Creates a new two dimensional point
*
* @param x
* the x axis
* @param y
* the y axis
*/
public Point(int x, int y) {
this.x = x;
this.y = y;
}
public static final Point fromXY(int x, int y) {
return new Point(x, y);
}
}

View File

@@ -14,7 +14,7 @@
* You should have received a copy of the GNU General Public License
* along with l2jserver. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jserver.util.dimensional;
package com.l2jserver.util.geometry;
/**
* An point is composed of an Coordinate and an angle. The angle represents the
@@ -22,7 +22,7 @@ package com.l2jserver.util.dimensional;
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
public class Point {
public class Point3D {
/**
* The point coordinate
*/
@@ -40,14 +40,28 @@ public class Point {
* @param angle
* the angle
*/
public Point(Coordinate coordinate, double angle) {
public Point3D(Coordinate coordinate, double angle) {
this.coordinate = coordinate;
this.angle = angle;
}
/**
* Creates a new point with 3 axis
*
* @param x
* the x axis
* @param y
* the y axis
* @param z
* the z axis
*/
public Point3D(int x, int y, int z) {
this(new Coordinate(x, y, z), 0);
}
/**
* @return the x
* @see com.l2jserver.util.dimensional.Coordinate#getX()
* @see com.l2jserver.util.geometry.Coordinate#getX()
*/
public int getX() {
return coordinate.getX();
@@ -55,7 +69,7 @@ public class Point {
/**
* @return the y
* @see com.l2jserver.util.dimensional.Coordinate#getY()
* @see com.l2jserver.util.geometry.Coordinate#getY()
*/
public int getY() {
return coordinate.getY();
@@ -63,7 +77,7 @@ public class Point {
/**
* @return the z
* @see com.l2jserver.util.dimensional.Coordinate#getZ()
* @see com.l2jserver.util.geometry.Coordinate#getZ()
*/
public int getZ() {
return coordinate.getZ();
@@ -73,7 +87,7 @@ public class Point {
* @param other
* the other coordinate
* @return the distance
* @see com.l2jserver.util.dimensional.Coordinate#getDistance(com.l2jserver.util.dimensional.Coordinate)
* @see com.l2jserver.util.geometry.Coordinate#getDistance(com.l2jserver.util.geometry.Coordinate)
*/
public double getDistance(Coordinate other) {
return coordinate.getDistance(other);
@@ -83,9 +97,9 @@ public class Point {
* @param other
* the other point
* @return the distance
* @see com.l2jserver.util.dimensional.Coordinate#getDistance(com.l2jserver.util.dimensional.Coordinate)
* @see com.l2jserver.util.geometry.Coordinate#getDistance(com.l2jserver.util.geometry.Coordinate)
*/
public double getDistance(Point other) {
public double getDistance(Point3D other) {
return coordinate.getDistance(other.coordinate);
}
@@ -114,10 +128,10 @@ public class Point {
* the z point
* @param angle
* the angle
* @return the new {@link Point} object created
* @return the new {@link Point3D} object created
*/
public static Point fromXYZA(int x, int y, int z, double angle) {
return new Point(Coordinate.fromXYZ(x, y, z), angle);
public static Point3D fromXYZA(int x, int y, int z, double angle) {
return new Point3D(Coordinate.fromXYZ(x, y, z), angle);
}
/**
@@ -129,9 +143,9 @@ public class Point {
* the y point
* @param z
* the z point
* @return the new {@link Point} object created
* @return the new {@link Point3D} object created
*/
public static Point fromXYZ(int x, int y, int z) {
public static Point3D fromXYZ(int x, int y, int z) {
return fromXYZA(x, y, z, 0);
}
}

View File

@@ -0,0 +1,155 @@
/*
* This file is part of l2jserver <l2jserver.com>.
*
* l2jserver 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 3 of the License, or
* (at your option) any later version.
*
* l2jserver 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 l2jserver. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jserver.util.geometry;
import java.awt.Polygon;
import java.util.Collection;
import com.l2jserver.util.MathUtil;
/**
* Area of free form
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
public class PolygonArea extends AbstractArea {
/**
* Collection of x points
*/
private final int[] xPoints;
/**
* Collection of y points
*/
private final int[] yPoints;
/**
* Polygon used to calculate isInside()
*/
private final Polygon poly;
/**
* Creates new area from given points
*
* @param points
* list of points
* @param zMin
* minimal z
* @param zMax
* maximal z
*/
public PolygonArea(Collection<Point> points, int zMin, int zMax) {
this(points.toArray(new Point[points.size()]), zMin, zMax);
}
/**
* Creates new area from given points
*
* @param points
* list of points
* @param zMin
* minimal z
* @param zMax
* maximal z
*/
public PolygonArea(Point[] points, int zMin, int zMax) {
super(zMin, zMax);
if (points.length < 3) {
throw new IllegalArgumentException(
"Not enough points, needed at least 3 but got "
+ points.length);
}
this.xPoints = new int[points.length];
this.yPoints = new int[points.length];
Polygon polygon = new Polygon();
for (int i = 0, n = points.length; i < n; i++) {
Point p = points[i];
polygon.addPoint(p.x, p.y);
xPoints[i] = p.x;
yPoints[i] = p.y;
}
this.poly = polygon;
}
@Override
public boolean isInside2D(int x, int y) {
return poly.contains(x, y);
}
@Override
public double getDistance2D(int x, int y) {
if (isInside2D(x, y)) {
return 0;
} else {
Point cp = getClosestPoint(x, y);
return MathUtil.getDistance(cp.x, cp.y, x, y);
}
}
@Override
public double getDistance3D(int x, int y, int z) {
if (isInside3D(x, y, z)) {
return 0;
} else if (isInsideZ(z)) {
return getDistance2D(x, y);
} else {
Point3D cp = getClosestPoint(x, y, z);
return MathUtil.getDistance(cp.getX(), cp.getY(), cp.getZ(), x, y,
z);
}
}
@Override
public Point getClosestPoint(int x, int y) {
Point closestPoint = null;
double closestDistance = 0;
for (int i = 0; i < xPoints.length; i++) {
int nextIndex = i + 1;
if (nextIndex == xPoints.length) {
nextIndex = 0;
}
int p1x = xPoints[i];
int p1y = yPoints[i];
int p2x = xPoints[nextIndex];
int p2y = yPoints[nextIndex];
Point point = MathUtil.getClosestPointOnSegment(p1x, p1y, p2x, p2y,
x, y);
if (closestPoint == null) {
closestPoint = point;
closestDistance = MathUtil.getDistance(closestPoint.x,
closestPoint.y, x, y);
} else {
double newDistance = MathUtil.getDistance(point.x, point.y, x,
y);
if (newDistance < closestDistance) {
closestPoint = point;
closestDistance = newDistance;
}
}
}
return closestPoint;
}
}

View File

@@ -0,0 +1,177 @@
/*
* This file is part of l2jserver <l2jserver.com>.
*
* l2jserver 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 3 of the License, or
* (at your option) any later version.
*
* l2jserver 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 l2jserver. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jserver.util.geometry;
import java.awt.Rectangle;
import com.l2jserver.util.MathUtil;
/**
* Rectangle area, most wide spread in the game
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
public class RectangleArea extends AbstractArea {
/**
* Min x point
*/
private final int minX;
/**
* Max x point
*/
private final int maxX;
/**
* Min y point
*/
private final int minY;
/**
* Max y point
*/
private final int maxY;
/**
* Creates new area from given points. Point order doesn't matter
*
* @param p1
* point
* @param p2
* point
* @param p3
* point
* @param p4
* point
* @param minZ
* minimal z
* @param maxZ
* maximal z
*/
public RectangleArea(Point p1, Point p2, Point p3, Point p4, int minZ,
int maxZ) {
super(minZ, maxZ);
// we should use a better way to do this
Rectangle r = new Rectangle();
r.add(new java.awt.Point(p1.x, p1.y));
r.add(new java.awt.Point(p2.x, p2.y));
r.add(new java.awt.Point(p3.x, p3.y));
r.add(new java.awt.Point(p4.x, p4.y));
minX = (int) r.getMinX();
maxX = (int) r.getMaxX();
minY = (int) r.getMinY();
maxY = (int) r.getMaxY();
}
/**
* Creates new are from given coords
*
* @param minX
* mimal x point
* @param minY
* minimal y point
* @param maxX
* maximal x point
* @param maxY
* maximal y point
* @param minZ
* minimal z point
* @param maxZ
* maximal z point
*/
public RectangleArea(int minX, int minY, int maxX, int maxY, int minZ,
int maxZ) {
super(minZ, maxZ);
this.minX = minX;
this.maxX = maxX;
this.minY = minY;
this.maxY = maxY;
}
@Override
public boolean isInside2D(int x, int y) {
return x >= minX && x <= maxX && y >= minY && y <= maxY;
}
@Override
public double getDistance2D(int x, int y) {
if (isInside2D(x, y)) {
return 0;
} else {
Point cp = getClosestPoint(x, y);
return MathUtil.getDistance(x, y, cp.x, cp.y);
}
}
@Override
public double getDistance3D(int x, int y, int z) {
if (isInside3D(x, y, z)) {
return 0;
} else if (isInsideZ(z)) {
return getDistance2D(x, y);
} else {
Point3D cp = getClosestPoint(x, y, z);
return MathUtil.getDistance(x, y, z, cp.getX(), cp.getY(),
cp.getZ());
}
}
@Override
public Point getClosestPoint(int x, int y) {
if (isInside2D(x, y)) {
return new Point(x, y);
} else {
// bottom edge
Point closestPoint = MathUtil.getClosestPointOnSegment(minX, minY,
maxX, minY, x, y);
double distance = MathUtil.getDistance(x, y, closestPoint.x,
closestPoint.y);
// top edge
Point cp = MathUtil.getClosestPointOnSegment(minX, maxY, maxX,
maxY, x, y);
double d = MathUtil.getDistance(x, y, cp.x, cp.y);
if (d < distance) {
closestPoint = cp;
distance = d;
}
// left edge
cp = MathUtil
.getClosestPointOnSegment(minX, minY, minX, maxY, x, y);
d = MathUtil.getDistance(x, y, cp.x, cp.y);
if (d < distance) {
closestPoint = cp;
distance = d;
}
// Right edge
cp = MathUtil
.getClosestPointOnSegment(maxX, minY, maxX, maxY, x, y);
d = MathUtil.getDistance(x, y, cp.x, cp.y);
if (d < distance) {
closestPoint = cp;
// distance = d;
}
return closestPoint;
}
}
}

View File

@@ -19,7 +19,7 @@ package com.l2jserver.util.jaxb;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import com.l2jserver.util.dimensional.Coordinate;
import com.l2jserver.util.geometry.Coordinate;
import com.l2jserver.util.jaxb.CoordinateAdapter.CoordinateElement;
/**