services.travel.TravelService.java Source code

Java tutorial

Introduction

Here is the source code for services.travel.TravelService.java

Source

/*******************************************************************************
 * Copyright (c) 2013 <Project SWG>
 * 
 * This File is part of NGECore2.
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 * 
 * Using NGEngine to work with NGECore2 is making a combined work based on NGEngine. 
 * Therefore all terms and conditions of the GNU Lesser General Public License cover the combination.
 ******************************************************************************/
package services.travel;

import java.nio.ByteOrder;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Vector;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import org.apache.commons.lang3.text.WordUtils;
import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.IoSession;

import protocol.swg.PlanetTravelPointListRequest;
import protocol.swg.PlanetTravelPointListResponse;
import engine.clientdata.ClientFileManager;
import engine.clientdata.visitors.DatatableVisitor;
import engine.clients.Client;
import engine.resources.container.Traverser;
import engine.resources.objects.SWGObject;
import engine.resources.scene.Planet;
import engine.resources.scene.Point3D;
import engine.resources.scene.Quaternion;
import engine.resources.service.INetworkDispatch;
import engine.resources.service.INetworkRemoteEvent;
import main.NGECore;
import resources.common.Console;
import resources.common.Opcodes;
import resources.common.SpawnPoint;
import resources.datatables.DisplayType;
import resources.objects.creature.CreatureObject;
import resources.objects.tangible.TangibleObject;
import services.playercities.PlayerCity;
import services.sui.SUIService.ListBoxType;
import services.sui.SUIService.MessageBoxType;
import services.sui.SUIWindow.SUICallback;
import services.sui.SUIWindow.Trigger;
import services.sui.SUIWindow;

public class TravelService implements INetworkDispatch {

    private NGECore core;
    private Map<Planet, Vector<TravelPoint>> travelMap = new ConcurrentHashMap<Planet, Vector<TravelPoint>>();
    private Map<Planet, Map<String, Integer>> fareMap = new ConcurrentHashMap<Planet, Map<String, Integer>>();

    public TravelService(NGECore core) {
        this.core = core;
    }

    @Override
    public void insertOpcodes(Map<Integer, INetworkRemoteEvent> swgOpcodes,
            Map<Integer, INetworkRemoteEvent> objControllerOpcodes) {
        swgOpcodes.put(Opcodes.PlanetTravelPointListRequest, new INetworkRemoteEvent() {

            @Override
            public void handlePacket(IoSession session, IoBuffer data) throws Exception {

                data.order(ByteOrder.LITTLE_ENDIAN);

                PlanetTravelPointListRequest request = new PlanetTravelPointListRequest();
                request.deserialize(data);

                Client client = core.getClient(session);

                if (client == null || client.getSession() == null)
                    return;

                SWGObject object = client.getParent();

                if (object == null)
                    return;

                TravelPoint travelPoint = getNearestTravelPoint(object);

                if (travelPoint == null)
                    return;

                if (travelPoint.isStarport()) {

                    List<Planet> planetList = core.terrainService.getPlanetList();

                    for (Planet planet : planetList) {
                        String planetString = planet.getName();

                        if (request.getPlanet().equals(planetString)) {

                            Vector<TravelPoint> correctTravelPoints = new Vector<TravelPoint>();

                            for (TravelPoint tp : travelMap.get(planet)) {
                                if (tp.isStarport()
                                        || tp.getPlanetName().equalsIgnoreCase(object.getPlanet().getName())) {
                                    correctTravelPoints.add(tp);
                                }
                            }
                            PlanetTravelPointListResponse response = new PlanetTravelPointListResponse(planetString,
                                    correctTravelPoints);
                            client.getSession().write(response.serialize());

                            break;

                        }
                    }

                } else {

                    Planet planet = object.getPlanet();

                    PlanetTravelPointListResponse response = new PlanetTravelPointListResponse(planet.getName(),
                            travelMap.get(planet));
                    client.getSession().write(response.serialize());

                }

            }
        });

    }

    public TravelPoint getNearestTravelPoint(SWGObject obj, int distance) {
        TravelPoint returnedPoint = null;
        Vector<TravelPoint> planetTp = travelMap.get(obj.getPlanet());

        synchronized (travelMap) {
            for (TravelPoint tp : planetTp) {
                //System.out.println("Distance for point " + tp.getName() + " is " + tp.getLocation().getDistance2D(obj.getWorldPosition()));
                if (tp.getLocation().getDistance2D(obj.getWorldPosition()) <= distance) {
                    if (returnedPoint != null) {
                        float returnPointDistance = returnedPoint.getLocation()
                                .getDistance2D(obj.getWorldPosition());
                        float tpDistance = tp.getLocation().getDistance2D(obj.getWorldPosition());
                        //Console.println("Current point: " + returnedPoint.getName());
                        //Console.println("Return point distance: " + returnPointDistance + " for " + returnedPoint.getName());
                        //Console.println("tp point distance: " + tpDistance + " for " + tp.getName());
                        if (tpDistance < returnPointDistance) {
                            returnedPoint = tp;
                        }
                    } else {
                        returnedPoint = tp;
                    }
                }
            }
        }
        // Some transport obj's were used as deco (ex: ACLO bunker on Talus shared_player_transport). A null check should be performed before tp is used.
        /*if (returnedPoint == null) {
           //System.out.println("Could not find travel point for " + obj.getTemplate() + " at " + obj.getPlanet().name + " Position: " + obj.getPosition().x + " " + obj.getPosition().z);
           //Console.println("Travel Point NULL: " + returnedPoint.getName());
        }*/

        return returnedPoint;
    }

    public TravelPoint getNearestTravelPoint(SWGObject obj) {
        return getNearestTravelPoint(obj, 125);
    }

    public TravelPoint getTravelPointByName(String planet, String tpName) {
        Planet planetObj = core.terrainService.getPlanetByName(planet.toLowerCase());

        Vector<TravelPoint> tpMap = travelMap.get(planetObj);

        TravelPoint returnedPoint = null;

        synchronized (travelMap) {
            for (TravelPoint tp : tpMap) {
                if (tp.getName().equals(tpName)) {
                    returnedPoint = tp;
                }
            }
        }

        if (returnedPoint == null) {
            System.out.println("Couldn't find a travelpoint w/ name " + tpName);
        }
        return returnedPoint;
    }

    public void addPlanet(Planet planet) {
        Vector<TravelPoint> travelPointVector = new Vector<TravelPoint>();
        travelMap.put(planet, travelPointVector);
        core.scriptService.callScript("scripts/", "static_travel_points", "addPoints", core, planet);
    }

    public void addTravelPoint(Planet planet, String name, float x, float y, float z) {
        // z should be y for 2d map
        TravelPoint travelPoint = new TravelPoint(name, x, y, z, 150);

        travelPoint.setPlanetName(WordUtils.capitalize(planet.getName()));

        synchronized (travelMap) {
            if (travelMap.containsKey(planet)) {

                travelMap.get(planet).add(travelPoint);
                System.out.println("Added travel point " + travelPoint.getName());

            } else {
                Vector<TravelPoint> travelPointVector = new Vector<TravelPoint>();
                travelMap.put(planet, travelPointVector);
                travelMap.get(planet).add(travelPoint);
                System.out.println("Added planet " + planet.getName() + " to TravelMap.");
                System.out.println("Added travel point " + travelPoint.getName());
            }
        }
    }

    public void removeTravelPointByName(Planet planet, String name) {
        if (travelMap.containsKey(planet)) {
            Vector<TravelPoint> travelVector = travelMap.get(planet);

            for (TravelPoint point : travelVector) {
                if (point.getName() == name) {
                    travelMap.get(planet).removeElement(point);
                    break;
                }
            }
        }
    }

    public void loadTravelPoints() {
        List<Planet> planetList = core.terrainService.getPlanetList();
        planetList.forEach(this::addPlanet);
        populateTravelFares();
    }

    public SWGObject createTravelTicket(String departurePlanet, String departureLoc, String arrivalPlanet,
            String arrivalLoc) {

        Planet planet = core.terrainService.getPlanetByName(departurePlanet.toLowerCase());
        SWGObject travelTicket = core.objectService
                .createObject("object/tangible/travel/travel_ticket/base/shared_base_travel_ticket.iff", planet);

        travelTicket.setStringAttribute("@obj_attr_n:travel_departure_planet",
                WordUtils.capitalize(departurePlanet));
        travelTicket.setStringAttribute("@obj_attr_n:travel_departure_point", departureLoc);

        travelTicket.setStringAttribute("@obj_attr_n:travel_arrival_planet", WordUtils.capitalize(arrivalPlanet));
        travelTicket.setStringAttribute("@obj_attr_n:travel_arrival_point", arrivalLoc);

        travelTicket.setAttachment("objType", "ticket");

        return travelTicket;
    }

    public void purchaseTravelTicket(SWGObject player, String departurePlanet, String departureLoc,
            String arrivalPlanet, String arrivalLoc, String roundTrip) {
        CreatureObject creatureObj = (CreatureObject) player;
        int fare = fareMap.get(player.getPlanet()).get(arrivalPlanet);
        int tax = 0;
        if (roundTrip.equals("1")) {
            fare += fareMap.get(player.getPlanet()).get(arrivalPlanet);
        }
        PlayerCity city = core.playerCityService.getCityObjectIsIn(player);
        if (city != null && city.getTravelTax() != 0) {
            tax = city.getTravelTax();
            fare += tax;
        }

        int playerBankCredits = creatureObj.getBankCredits();
        if (playerBankCredits < fare) {
            int cashDifference = fare - playerBankCredits;

            if (cashDifference > creatureObj.getCashCredits()) {
                SUIWindow window = core.suiService.createMessageBox(MessageBoxType.MESSAGE_BOX_OK,
                        "STAR WARS GALAXIES", "You do not have enough to purchase that.", player, null, 0);
                core.suiService.openSUIWindow(window);
                return;
            }

            creatureObj.setBankCredits(0);
            creatureObj.setCashCredits(creatureObj.getCashCredits() - cashDifference);

        } else {
            creatureObj.setBankCredits(playerBankCredits - fare);

        }
        if (tax != 0) {
            city.addToTreasury(tax);
        }

        if (roundTrip.equals("1")) {
            SWGObject tripTicket = createTravelTicket(arrivalPlanet, arrivalLoc, departurePlanet, departureLoc);
            creatureObj.getSlottedObject("inventory").add(tripTicket);
        }

        SWGObject travelTicket = createTravelTicket(departurePlanet, departureLoc, arrivalPlanet, arrivalLoc);

        creatureObj.getSlottedObject("inventory").add(travelTicket);
        //Console.println("Total cost: " + fare);
        SUIWindow window = core.suiService.createMessageBox(MessageBoxType.MESSAGE_BOX_OK, "STAR WARS GALAXIES",
                "@travel:ticket_purchase_complete", player, null, 0);
        core.suiService.openSUIWindow(window);

        creatureObj.sendSystemMessage(
                "You successfully make a payment of " + fare + " credits to the Galactic Travel Commission.",
                (byte) 0);
    }

    // This returns all ticket objects in a players inventory
    public Vector<SWGObject> getTicketList(SWGObject player) {

        final Vector<SWGObject> ticketList = new Vector<SWGObject>();
        final TravelPoint nearestPoint = getNearestTravelPoint(player);
        TangibleObject playerInventory = (TangibleObject) player.getSlottedObject("inventory");

        playerInventory.viewChildren(player, false, false, new Traverser() {
            //                              ^-topDown-^-recursive
            // topDown - If true, objects that are at the top of the tree are viewed first.
            //    the "viewer" needs to be whatever object wants to know this information (player)
            @Override
            public void process(SWGObject obj) {
                if (obj.getAttachment("objType") != null) {
                    String objType = (String) obj.getAttachment("objType");
                    String ticket = "ticket";
                    //System.out.println("Nearest Point: " + nearestPoint.getName());
                    if (objType.equals(ticket) && obj.getStringAttribute("@obj_attr_n:travel_departure_point")
                            .equals(nearestPoint.getName())) {
                        ticketList.add(obj);
                    }
                }
            }
        });
        return ticketList;
    }

    // TravelPoint = the travelpoint player is going to travel to!
    public void doTransport(SWGObject actor, TravelPoint tp) {

        Planet planet = core.terrainService.getPlanetByName(tp.getPlanetName());
        Point3D spawnLocation = SpawnPoint.getRandomPosition(tp.getLocation(), 5, 20, actor.getPlanetId());
        float positionY = core.terrainService.getHeight(actor.getPlanetId(), spawnLocation.x, spawnLocation.z);
        core.simulationService.transferToPlanet(actor, planet,
                new Point3D(spawnLocation.x, positionY, spawnLocation.z), new Quaternion(0, 0, 0, 0), null);
    }

    public void sendTicketWindow(final CreatureObject creature, SWGObject rangeObject) {

        if (creature == null)
            return;

        Map<Long, String> ticketData = new HashMap<Long, String>();
        Vector<SWGObject> invTickets = getTicketList(creature);

        for (SWGObject ticket : invTickets) {
            ticketData.put(ticket.getObjectId(), ticket.getStringAttribute("@obj_attr_n:travel_arrival_planet")
                    + " -- " + ticket.getStringAttribute("@obj_attr_n:travel_arrival_point"));
        }

        final SUIWindow window = core.suiService.createListBox(ListBoxType.LIST_BOX_OK_CANCEL, "Select Destination",
                "Select Destination", ticketData, creature, rangeObject, 10);
        Vector<String> returnList = new Vector<String>();
        returnList.add("List.lstList:SelectedRow");

        window.addHandler(0, "", Trigger.TRIGGER_OK, returnList, new SUICallback() {

            @Override
            public void process(SWGObject owner, int eventType, Vector<String> returnList) {
                // return list = int number of selected row
                int index = Integer.parseInt(returnList.get(0));

                SWGObject selectedTicket = core.objectService.getObject(window.getObjectIdByIndex(index));

                TravelPoint arrivalPoint = getTravelPointByName(
                        selectedTicket.getStringAttribute("@obj_attr_n:travel_arrival_planet").toLowerCase(),
                        selectedTicket.getStringAttribute("@obj_attr_n:travel_arrival_point"));

                TravelPoint departurePoint = getNearestTravelPoint(creature);

                if (departurePoint.isShuttleAvailable() == true) {
                    selectedTicket.getContainer().remove(selectedTicket);
                    core.objectService.destroyObject(selectedTicket);
                    doTransport(creature, arrivalPoint);
                } else {
                    creature.sendSystemMessage("@travel:shuttle_not_available ", (byte) 0);
                }
            }
        });

        core.suiService.openSUIWindow(window);

    }

    private void populateTravelFares() {
        try {
            DatatableVisitor travelFares = ClientFileManager.loadFile("datatables/travel/travel.iff",
                    DatatableVisitor.class);

            for (int f = 0; f < travelFares.getRowCount(); f++) {
                Planet planet = core.terrainService.getPlanetByName((String) travelFares.getObject(f, 0));
                if (travelMap.containsKey(planet)) {
                    int corellia = ((int) travelFares.getObject(f, 1));
                    int dantooine = ((int) travelFares.getObject(f, 2));
                    int dathomir = ((int) travelFares.getObject(f, 3));
                    int endor = ((int) travelFares.getObject(f, 4));
                    int lok = ((int) travelFares.getObject(f, 5));
                    int naboo = ((int) travelFares.getObject(f, 6));
                    int rori = ((int) travelFares.getObject(f, 7));
                    int talus = ((int) travelFares.getObject(f, 8));
                    int tatooine = ((int) travelFares.getObject(f, 9));
                    int yavin4 = ((int) travelFares.getObject(f, 10));
                    int mustafar = ((int) travelFares.getObject(f, 11));
                    int kashyyyk_main = ((int) travelFares.getObject(f, 12));

                    Map<String, Integer> planetFares = new ConcurrentHashMap<String, Integer>();

                    planetFares.put("corellia", corellia);
                    planetFares.put("dantooine", dantooine);
                    planetFares.put("dathomir", dathomir);
                    planetFares.put("endor", endor);
                    planetFares.put("lok", lok);
                    planetFares.put("naboo", naboo);
                    planetFares.put("rori", rori);
                    planetFares.put("talus", talus);
                    planetFares.put("tatooine", tatooine);
                    planetFares.put("yavin4", yavin4);
                    planetFares.put("mustafar", mustafar);
                    planetFares.put("kashyyyk_main", kashyyyk_main);

                    fareMap.put(planet, planetFares);
                    Console.println("Loaded the travel fares for " + planet.getName());
                }
            }
        } catch (InstantiationException | IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    public Map<Planet, Vector<TravelPoint>> getTravelMap() {
        return this.travelMap;
    }

    //ITV Despawn
    public void checkForItvTimedDespawn(CreatureObject actor, SWGObject object) {

        Executors.newScheduledThreadPool(1).schedule(new Runnable() {
            public void run() {
                try {

                    if (object != null) {
                        core.objectService.destroyObject(object);
                        actor.sendSystemMessage("@travel:pickup_timeout", DisplayType.Broadcast);
                        actor.setAttachment("itv", null);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }, 30, TimeUnit.SECONDS);
    }

    @Override
    public void shutdown() {

    }
}