|
|
|
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
|
|
|
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
|
|
|
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
|
|
|
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
|
|
|
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
|
|
|
// Magicbane Emulator Project © 2013 - 2022
|
|
|
|
// www.magicbane.com
|
|
|
|
|
|
|
|
|
|
|
|
package engine.net.client.msg;
|
|
|
|
|
|
|
|
import engine.Enum;
|
|
|
|
import engine.math.Vector3fImmutable;
|
|
|
|
import engine.net.*;
|
|
|
|
import engine.net.client.ClientConnection;
|
|
|
|
import engine.net.client.Protocol;
|
|
|
|
import engine.objects.Zone;
|
|
|
|
import org.pmw.tinylog.Logger;
|
|
|
|
|
|
|
|
import java.util.ArrayList;
|
|
|
|
import java.util.Collections;
|
|
|
|
import java.util.HashMap;
|
|
|
|
import java.util.Map;
|
|
|
|
|
|
|
|
public class PlaceAssetMsg extends ClientNetMsg {
|
|
|
|
|
|
|
|
/*
|
|
|
|
Client -> Server
|
|
|
|
//Type 1
|
|
|
|
//940962DF 00000001 00000000 0A400000 03903DC1 00000000 00000000 00000000 3F800000 00000000 00000000 00000000 00
|
|
|
|
//00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00
|
|
|
|
//00000000
|
|
|
|
//00000000
|
|
|
|
//00000000
|
|
|
|
//Type3
|
|
|
|
//940962DF 00000003 00000000 00000000 00000000 00000000 00000000 00000000 3F800000 00000000 00000000 00000000 00
|
|
|
|
//00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 01
|
|
|
|
//00000000
|
|
|
|
//00000001
|
|
|
|
// 00000000 0013FF24 475765FD 417BD060 C794FF75 B33BBD2E 00000000 3F800000 00000000 <-placement info
|
|
|
|
//00000000
|
|
|
|
|
|
|
|
|
|
|
|
Server -> Client
|
|
|
|
//Type 2 (Asset list / walls)
|
|
|
|
//940962DF 00000002 00000000 00000000 00000000 00000000 00000000 00000000 3F800000 00000000 00000000 00000000 01
|
|
|
|
//475725EC 412BD080 C794DF86 44600000 44600000 44600000 43000000 43000000 43000000 445AC000 445AC000 01
|
|
|
|
//00000000
|
|
|
|
//00000000
|
|
|
|
//00000006 <-building list for walls
|
|
|
|
// 00000000 0013FA74 00061A80 <-wall ID and cost
|
|
|
|
// 00000000 0013FBA0 000249F0
|
|
|
|
// 00000000 0013FCCC 000186A0
|
|
|
|
// 00000000 0013FDF8 0007A120
|
|
|
|
// 00000000 0013FF24 0007A120
|
|
|
|
// 00000000 004D5FD0 0007A120
|
|
|
|
//Type 2 (Single asset)
|
|
|
|
//940962DF 00000002 00000000 00000000 00000000 00000000 00000000 00000000 3F800000 00000000 00000000 00000000 01
|
|
|
|
//475725EC 412BD080 C794DF86 44600000 44600000 44600000 43000000 43000000 43000000 445AC000 445AC000 00
|
|
|
|
//00000001
|
|
|
|
// 00000000 00063060 00000001 <-blueprintUUID, 1 Building
|
|
|
|
//00000000
|
|
|
|
//00000000
|
|
|
|
//Type 0 (Response Error)
|
|
|
|
//940962DF 00000000 00000006 0000001b
|
|
|
|
//430061006e006e006f007400200070006c00610063006500200061007300730065007400200069006e00200077006100740065007200
|
|
|
|
//00000000 00000000 00000000 00000000 00000000 3F800000 00000000 00000000 00000000 00
|
|
|
|
//00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00
|
|
|
|
//00000000
|
|
|
|
//00000000
|
|
|
|
//00000000
|
|
|
|
//Type 4 (Response Success (place asset))
|
|
|
|
//940962DF 00000000 00000002 0000000D 00460065007500640061006C0020004300680075007200630068
|
|
|
|
//00000000 00000000 00000000 00000000 00000000 3F800000 00000000 00000000 00000000 00
|
|
|
|
//00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00
|
|
|
|
//00000000
|
|
|
|
//00000000
|
|
|
|
//00000000
|
|
|
|
*/
|
|
|
|
|
|
|
|
//UseItem(C->S)->Type 2(S->C)->Type 1(C->S) <-close placement window, no response
|
|
|
|
//UseItem(C->S)->Type 2(S->C)->Type 3(C->S)->Type 0(S->C) <-Attempt place asset, with error response
|
|
|
|
//UseItem(C->S)->Type 2(S->C)->Type 3(C->S)->Type 4(S->C) <-Attempt place asset, with success response
|
|
|
|
|
|
|
|
/* Error msg codes
|
|
|
|
//1 "msg append here" <- what's in msg string.
|
|
|
|
//2 Conflict with "msg append here"
|
|
|
|
//3 Conflict between proposed assets
|
|
|
|
//4 Asset "msg append here" Cannot be isolated.
|
|
|
|
//5 Asset "msg append here" is outside the fortress zone.
|
|
|
|
//6 Cannot place the asset in water.
|
|
|
|
//7 Cannot place asset on land.
|
|
|
|
//8 NULL template for asset
|
|
|
|
//9 You must be a guild member to place this asset
|
|
|
|
//10 You must be a guild leader to place this asset
|
|
|
|
//11 No city asset template
|
|
|
|
//12 Only leaders of your guild can place fortresses
|
|
|
|
//13 Your guild cannot place fortress placements here
|
|
|
|
//14 This city architechture cannot be placed in this zone
|
|
|
|
//15 Cannot place assets in peace zone
|
|
|
|
//16 You do not belong to a guild
|
|
|
|
//17 Yours is not an errant or swarn guild
|
|
|
|
//18 There are no guild trees to be found
|
|
|
|
//19 NULL tree city asset
|
|
|
|
//20 You cannot place a bane circle on a tree your affiliated with
|
|
|
|
//21 This tree cannot be affected by bane circles
|
|
|
|
//22 Bane circles cannot effect dead trees
|
|
|
|
//23 A bane circle is already attached to nearest tree
|
|
|
|
//24 Banecircle is too far from guild
|
|
|
|
//25 Banecircle is too close to guild tree
|
|
|
|
//26 Cannot find deed in inventory
|
|
|
|
//27 Target object is not a deed
|
|
|
|
//28 You do not have enough gold to complete this request
|
|
|
|
//29 You apparently do not have access to some of these assets
|
|
|
|
//30 Insufficient deeds
|
|
|
|
//31 Unable to locate deed to this asset
|
|
|
|
//32 Unknown error occurred: 32
|
|
|
|
//33 Unknown error occurred: 33
|
|
|
|
//34 Unknown error occurred: 34
|
|
|
|
//35 Unknown error occurred: 35
|
|
|
|
//36 Unknown error occurred: 36
|
|
|
|
//37 Unknown error occurred: 37
|
|
|
|
//38 Unknown error occurred: 38
|
|
|
|
//39 Too close to another tree
|
|
|
|
//40 Cannot place into occupied guild zone
|
|
|
|
//41 Cannot place outisde a guild zone
|
|
|
|
//42 Tree cannot support anymore shrines
|
|
|
|
//43 The city already has a shrine of that type
|
|
|
|
//44 You must be in a player guild to place a bane circle
|
|
|
|
//45 Tree cannot support anymore spires
|
|
|
|
//46 A spire of that type already exists
|
|
|
|
//47 Tree cannot support anymore barracks
|
|
|
|
//48 Assets (except walls) must be placed one at a time
|
|
|
|
//49 The city cannot support a warehouse at its current rank
|
|
|
|
//50 You can only have one warehouse
|
|
|
|
//51 This asset cannot be placed on city grid
|
|
|
|
//52 No city to associate asset with
|
|
|
|
//53 Buildings of war cannot be placed around a city grid unless there is an active bane
|
|
|
|
//54 You must belong to the nation of the Bane Circle or the Tree to place buildings of war.
|
|
|
|
//55 You must belong to a nation to place a bane circle
|
|
|
|
//56 The building of war must be placed closer to the city
|
|
|
|
//57 No building may be placed within this territory
|
|
|
|
//58 This territory is full, it can support no more then "msg append here" trees.
|
|
|
|
//59 No city to siege at this location.
|
|
|
|
//60 This scroll's rank is too low to bane this city
|
|
|
|
//61 The bane circle cannot support any more buildings of war
|
|
|
|
//62 The tree cannot support any more buildings of war
|
|
|
|
//63 Failure in guild tree claiming phase
|
|
|
|
//64 Your nation is already at war and your limit has been reached
|
|
|
|
//65 Unable to find a tree to target
|
|
|
|
//66 There is no bane circle to support this building of war
|
|
|
|
//67 There is no tree to support this building of war
|
|
|
|
//68 There is not tree or bane circle to support this building of war
|
|
|
|
//69 Trees must be placed within a territory
|
|
|
|
//70 Unknown error occurred: 38
|
|
|
|
//71 This building of war may not be placed on a city grid by attackers
|
|
|
|
//72 You cannot place a bane circle while you are in a non player nation
|
|
|
|
//73 Only the guild leader or inner council may place a bane circle
|
|
|
|
//74 Only buildings of war may be placed during a bane
|
|
|
|
//75 This current vigor of the tree withstands your attempt to place a bane circle. Minutes remaining: "msg appended here"
|
|
|
|
//76 This tree cannot support towers or gatehouses
|
|
|
|
//77 This tree cannot support more towers or gatehouses
|
|
|
|
//78 This tree cannot support walls.
|
|
|
|
//79 This tree cannot support more walls.
|
|
|
|
*/
|
|
|
|
|
|
|
|
private static final Map<Integer, Integer> wallToCost;
|
|
|
|
private static final Map<Integer, Integer> wallToUseId;
|
|
|
|
private static final Map<Integer, Map<Integer, Integer>> useIdToWallCostMaps;
|
|
|
|
private static final int NONE = 0;
|
|
|
|
private static final int CLIENTREQ_UNKNOWN = 1;
|
|
|
|
private static final int SERVER_OPENWINDOW = 2;
|
|
|
|
private static final int CLIENTREQ_NEWBUILDING = 3; // Request to place asset
|
|
|
|
private static final int SERVER_CLOSEWINDOW = 4;
|
|
|
|
|
|
|
|
static {
|
|
|
|
Map<Integer, Integer> map = new HashMap<>();
|
|
|
|
map.put(454700, 100000); //Straight Outer Wall
|
|
|
|
map.put(1309900, 100000); //Irekei Outer Straight Wall
|
|
|
|
map.put(1348900, 100000); //Invorri Outer Straight Wall
|
|
|
|
map.put(454650, 150000); //Outer Wall with Stairs
|
|
|
|
map.put(455000, 150000); //Outer Wall with Tower
|
|
|
|
map.put(454550, 150000); //Outer Wall Gate
|
|
|
|
map.put(455700, 150000); //Small Gate House
|
|
|
|
map.put(1309600, 150000); //Irekei Outer Wall with Stairs
|
|
|
|
map.put(1309300, 150000); //Irekei Outer Wall Gate
|
|
|
|
map.put(1331200, 150000); //Elven Straight Outer Wall
|
|
|
|
map.put(1330900, 150000); //Elven Outer Wall with Stairs
|
|
|
|
map.put(1332100, 150000); //Elven Outer Wall with Tower
|
|
|
|
map.put(1330300, 150000); //Elven Outer Wall Gate
|
|
|
|
map.put(1348600, 150000); //Invorri Outer Wall with Stairs
|
|
|
|
map.put(1348300, 150000); //Invorri Outer Wall Gate
|
|
|
|
map.put(454750, 300000); //Concave Tower
|
|
|
|
map.put(458100, 300000); //Artillery Tower
|
|
|
|
map.put(455300, 300000); //Tower Junction
|
|
|
|
map.put(454800, 300000); //Convex Tower (inside corner)
|
|
|
|
map.put(1310200, 300000); //Irekei Concave Tower
|
|
|
|
map.put(5070800, 300000); //Irekei Artillery Tower
|
|
|
|
map.put(1310500, 300000); //Irekei Convex Tower
|
|
|
|
map.put(1330600, 300000); //Elven Gate House
|
|
|
|
map.put(1331500, 300000); //Elven Concave Tower
|
|
|
|
map.put(5070200, 300000); //Elven Artillery Tower
|
|
|
|
map.put(1332400, 300000); //Elven Tower Junction
|
|
|
|
map.put(1331800, 300000); //Elven Convex Tower
|
|
|
|
map.put(1349200, 300000); //Invorri Concave Tower
|
|
|
|
map.put(5071400, 300000); //Invorri Artillery Tower
|
|
|
|
map.put(1349500, 300000); //Invorri Convex Tower
|
|
|
|
wallToCost = Collections.unmodifiableMap(map);
|
|
|
|
}
|
|
|
|
|
|
|
|
static {
|
|
|
|
Map<Integer, Integer> map = new HashMap<>();
|
|
|
|
///Feudal Outer Walls
|
|
|
|
map.put(454700, 1); //Straight Outer Wall
|
|
|
|
map.put(454650, 1); //Outer Wall with Stairs
|
|
|
|
map.put(455000, 1); //Outer Wall with Tower
|
|
|
|
map.put(454550, 1); //Outer Wall Gate
|
|
|
|
map.put(455700, 1); //Small Gate House
|
|
|
|
map.put(454750, 1); //Concave Tower
|
|
|
|
map.put(458100, 1); //Artillery Tower
|
|
|
|
map.put(455300, 1); //Tower Junction
|
|
|
|
map.put(454800, 1); //Convex Tower (inside corner)
|
|
|
|
//map.put(1, 454000, 1); //Gate House (giant gatehouse) NOT USE IN GAME
|
|
|
|
//Feudal Inner Walls
|
|
|
|
/*
|
|
|
|
map.put(454100, 2); //Inner Archway
|
|
|
|
map.put(454200, 2); //Inner Wall Corner
|
|
|
|
map.put(454250, 2); //Inner Wall Gate
|
|
|
|
map.put(454300, 2); //Inner Straight Wall
|
|
|
|
map.put(454350, 2); //Inner Wall T-Junction
|
|
|
|
map.put(454400, 2); //Inner Wall Cross Junction
|
|
|
|
map.put(454850, 2); //Tower-Inner Wall Junction (T-East) Stuck inside left
|
|
|
|
map.put(454900, 2); //Tower-Inner Wall Junction (T-South) stuck inside right
|
|
|
|
map.put(454950, 2); //Tower-Inner Wall Junction (4-way) stuck inside
|
|
|
|
*/
|
|
|
|
//Irekei Outer Walls
|
|
|
|
map.put(1309900, 3); //Irekei Outer Straight Wall
|
|
|
|
map.put(1309600, 3); //Irekei Outer Wall with Stairs
|
|
|
|
map.put(1309300, 3); //Irekei Outer Wall Gate
|
|
|
|
map.put(1310200, 3); //Irekei Concave Tower
|
|
|
|
map.put(5070800, 3); //Irekei Artillery Tower
|
|
|
|
map.put(1310500, 3); //Irekei Convex Tower
|
|
|
|
//Elven Outer Walls
|
|
|
|
map.put(1331200, 4); //Elven Straight Outer Wall
|
|
|
|
map.put(1330900, 4); //Elven Outer Wall with Stairs
|
|
|
|
map.put(1332100, 4); //Elven Outer Wall with Tower
|
|
|
|
map.put(1330300, 4); //Elven Outer Wall Gate
|
|
|
|
map.put(1330600, 4); //Elven Gate House
|
|
|
|
map.put(1331500, 4); //Elven Concave Tower
|
|
|
|
map.put(5070200, 4); //Elven Artillery Tower
|
|
|
|
map.put(1332400, 4); //Elven Tower Junction
|
|
|
|
map.put(1331800, 4); //Elven Convex Tower
|
|
|
|
//Invorri Outer Walls
|
|
|
|
map.put(1348900, 5); //Invorri Outer Straight Wall
|
|
|
|
map.put(1348600, 5); //Invorri Outer Wall with Stairs
|
|
|
|
map.put(1348300, 5); //Invorri Outer Wall Gate
|
|
|
|
map.put(1349200, 5); //Invorri Concave Tower
|
|
|
|
map.put(5071400, 5); //Invorri Artillery Tower
|
|
|
|
map.put(1349500, 5); //Invorri Convex Tower
|
|
|
|
wallToUseId = Collections.unmodifiableMap(map);
|
|
|
|
}
|
|
|
|
|
|
|
|
static {
|
|
|
|
//autoloaded based on wallToUseId and wallToCost
|
|
|
|
Map<Integer, Map<Integer, Integer>> map = new HashMap<>();
|
|
|
|
for (Map.Entry<Integer, Integer> entry : wallToUseId.entrySet()) {
|
|
|
|
int wallId = entry.getKey();
|
|
|
|
int useId = entry.getValue();
|
|
|
|
int cost = 0;
|
|
|
|
Integer costCheck = wallToCost.get(wallId);
|
|
|
|
if (costCheck != null) {
|
|
|
|
cost = costCheck;
|
|
|
|
} else {
|
|
|
|
throw new Error("PlaceAssetMsg: WallId '" + wallId + "' has no cost in 'wallToCost' but exists in 'useIdToWall'.");
|
|
|
|
}
|
|
|
|
if (!map.containsKey(useId)) {
|
|
|
|
map.put(useId, new HashMap<>());
|
|
|
|
}
|
|
|
|
map.get(useId).put(wallId, cost);
|
|
|
|
}
|
|
|
|
for (Map.Entry<Integer, Map<Integer, Integer>> entry : map.entrySet()) {
|
|
|
|
map.put(entry.getKey(), Collections.unmodifiableMap(entry.getValue()));
|
|
|
|
}
|
|
|
|
useIdToWallCostMaps = Collections.unmodifiableMap(map);
|
|
|
|
}
|
|
|
|
|
|
|
|
private int actionType; //1,3 (recv), 0,2 (send)
|
|
|
|
private int msgID; //used on type 0, 0 on all other types
|
|
|
|
private String msg; //used on type 0
|
|
|
|
private int contractType; //used on type 1
|
|
|
|
private int contractID; //used on type 1
|
|
|
|
private byte unknown01; //0x01 on type 2 (send city data). 0x00 otherwise
|
|
|
|
private float x;
|
|
|
|
private float y;
|
|
|
|
private float z;
|
|
|
|
private byte unknown02; //0x01 if data follow, 0x00 otherwise. Best guess
|
|
|
|
private ArrayList<PlacementInfo> placementInfo;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* This is the general purpose constructor.
|
|
|
|
*/
|
|
|
|
public PlaceAssetMsg() {
|
|
|
|
super(Protocol.PLACEASSET);
|
|
|
|
this.placementInfo = new ArrayList<>();
|
|
|
|
this.actionType = SERVER_OPENWINDOW;
|
|
|
|
this.msgID = 0;
|
|
|
|
this.msg = "";
|
|
|
|
this.contractType = 0;
|
|
|
|
this.contractID = 0;
|
|
|
|
this.unknown01 = (byte) 0x00;
|
|
|
|
this.x = 0f;
|
|
|
|
this.y = 0f;
|
|
|
|
this.z = 0f;
|
|
|
|
this.unknown02 = (byte) 0x01;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* This constructor is used by NetMsgFactory. It attempts to deserialize the
|
|
|
|
* ByteBuffer into a message. If a BufferUnderflow occurs (based on reading
|
|
|
|
* past the limit) then this constructor Throws that Exception to the
|
|
|
|
* caller.
|
|
|
|
*/
|
|
|
|
public PlaceAssetMsg(AbstractConnection origin, ByteBufferReader reader) {
|
|
|
|
super(Protocol.PLACEASSET, origin, reader);
|
|
|
|
}
|
|
|
|
|
|
|
|
private static Map<Integer, Integer> getBuildingList(int buildingID) {
|
|
|
|
if (useIdToWallCostMaps.containsKey(buildingID)) {
|
|
|
|
return useIdToWallCostMaps.get(buildingID);
|
|
|
|
}
|
|
|
|
return new HashMap<>(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
public static int getWallCost(int blueprintUUID) {
|
|
|
|
if (wallToCost.containsKey(blueprintUUID)) {
|
|
|
|
return wallToCost.get(blueprintUUID);
|
|
|
|
}
|
|
|
|
Logger.warn("Cost of Wall '" + blueprintUUID + "' was requested but no cost is configured for that wallId.");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static void sendPlaceAssetError(ClientConnection origin, int errorID, String stringData) {
|
|
|
|
|
|
|
|
PlaceAssetMsg outMsg;
|
|
|
|
|
|
|
|
outMsg = new PlaceAssetMsg();
|
|
|
|
outMsg.actionType = 0;
|
|
|
|
outMsg.msgID = errorID;
|
|
|
|
outMsg.msg = stringData;
|
|
|
|
|
|
|
|
Dispatch dispatch = Dispatch.borrow(origin.getPlayerCharacter(), outMsg);
|
|
|
|
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
|
|
|
}
|
|
|
|
|
|
|
|
public static void sendPlaceAssetConfirmWall(ClientConnection origin, Zone zone) {
|
|
|
|
|
|
|
|
PlaceAssetMsg outMsg = new PlaceAssetMsg();
|
|
|
|
outMsg.actionType = 0;
|
|
|
|
outMsg.msgID = 0;
|
|
|
|
outMsg.msg = "";
|
|
|
|
outMsg.x = zone.getLoc().x + 64;
|
|
|
|
outMsg.y = zone.getLoc().y;
|
|
|
|
outMsg.z = zone.getLoc().z + 64;
|
|
|
|
|
|
|
|
|
|
|
|
Dispatch dispatch = Dispatch.borrow(origin.getPlayerCharacter(), outMsg);
|
|
|
|
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Serializes the subclass specific items to the supplied NetMsgWriter.
|
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
protected void _serialize(ByteBufferWriter writer) {
|
|
|
|
|
|
|
|
writer.putInt(this.actionType);
|
|
|
|
|
|
|
|
if (this.actionType == NONE) {
|
|
|
|
writer.putInt(this.msgID);
|
|
|
|
if (this.msgID != 0)
|
|
|
|
writer.putString(this.msg);
|
|
|
|
} else if (this.actionType == SERVER_CLOSEWINDOW) {
|
|
|
|
//writer.putInt(1); //Qty of assets placed?? A 0 will crash the client. Any value >0 seems to do the same thing.
|
|
|
|
writer.putInt(0);
|
|
|
|
} else {
|
|
|
|
writer.putInt(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
writer.putInt(this.contractType);
|
|
|
|
writer.putInt(this.contractID);
|
|
|
|
writer.putInt(0);
|
|
|
|
writer.putInt(0);
|
|
|
|
writer.putInt(0);
|
|
|
|
writer.putFloat(1f);
|
|
|
|
writer.putInt(0);
|
|
|
|
writer.putInt(0);
|
|
|
|
writer.putInt(0);
|
|
|
|
|
|
|
|
if (this.actionType == SERVER_OPENWINDOW || (this.actionType == NONE && this.msgID == 0)) {
|
|
|
|
//send Place Asset Msg
|
|
|
|
writer.put((byte) 0x01);
|
|
|
|
writer.putFloat(x);
|
|
|
|
writer.putFloat(y);
|
|
|
|
writer.putFloat(z);
|
|
|
|
for (int i = 0; i < 3; i++)
|
|
|
|
writer.putFloat(896); // city Bounds full extent.
|
|
|
|
for (int i = 0; i < 3; i++)
|
|
|
|
writer.putFloat(128); //grid dimensions
|
|
|
|
PlacementInfo pi = (this.placementInfo.size() > 0) ? this.placementInfo.get(0) : null;
|
|
|
|
int buildingID = (pi != null) ? pi.getBlueprintUUID() : 0;
|
|
|
|
if (buildingID == 24200) {
|
|
|
|
writer.putFloat(875);
|
|
|
|
writer.putFloat(875);
|
|
|
|
} else {
|
|
|
|
writer.putFloat(576);
|
|
|
|
writer.putFloat(576);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (buildingID < 6) {
|
|
|
|
//place wall lists
|
|
|
|
writer.put((byte) 0x01);
|
|
|
|
writer.putInt(0);
|
|
|
|
writer.putInt(0);
|
|
|
|
Map<Integer, Integer> buildings = getBuildingList(buildingID);
|
|
|
|
writer.putInt(buildings.size());
|
|
|
|
for (int bID : buildings.keySet()) {
|
|
|
|
writer.putInt(0);
|
|
|
|
writer.putInt(bID);
|
|
|
|
writer.putInt(buildings.get(bID));
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
//send individual building
|
|
|
|
writer.put((byte) 0x00);
|
|
|
|
writer.putInt(1);
|
|
|
|
writer.putInt(0);
|
|
|
|
writer.putInt(buildingID);
|
|
|
|
writer.putInt(1);
|
|
|
|
writer.putInt(0);
|
|
|
|
writer.putInt(0);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
//Send Server response to client placing asset
|
|
|
|
writer.put((byte) 0x00);
|
|
|
|
for (int i = 0; i < 11; i++)
|
|
|
|
writer.putFloat(0f);
|
|
|
|
writer.put((byte) 0x00);
|
|
|
|
writer.putInt(0);
|
|
|
|
if (this.placementInfo == null)
|
|
|
|
writer.putInt(0);
|
|
|
|
else {
|
|
|
|
writer.putInt(this.placementInfo.size());
|
|
|
|
for (PlacementInfo placementInfo : this.placementInfo) {
|
|
|
|
writer.putInt(0);
|
|
|
|
writer.putInt(placementInfo.blueprintUUID);
|
|
|
|
writer.putVector3f(placementInfo.loc);
|
|
|
|
writer.putFloat(placementInfo.w);
|
|
|
|
writer.putVector3f(placementInfo.rot);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
writer.putInt(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Deserializes the subclass specific items from the supplied NetMsgReader.
|
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
protected void _deserialize(ByteBufferReader reader) {
|
|
|
|
this.placementInfo = new ArrayList<>();
|
|
|
|
this.actionType = reader.getInt();
|
|
|
|
reader.getInt();
|
|
|
|
this.contractType = reader.getInt();
|
|
|
|
this.contractID = reader.getInt();
|
|
|
|
for (int i = 0; i < 7; i++)
|
|
|
|
reader.getInt();
|
|
|
|
reader.get();
|
|
|
|
for (int i = 0; i < 11; i++)
|
|
|
|
reader.getInt();
|
|
|
|
reader.get();
|
|
|
|
reader.getInt();
|
|
|
|
int placementInfo = reader.getInt();
|
|
|
|
for (int i = 0; i < placementInfo; i++) {
|
|
|
|
reader.getInt();
|
|
|
|
PlacementInfo pi = new PlacementInfo(reader.getInt(), reader.getFloat(), reader.getFloat(),
|
|
|
|
reader.getFloat(), reader.getFloat(), reader.getFloat(), reader.getFloat(), reader.getFloat());
|
|
|
|
this.placementInfo.add(pi);
|
|
|
|
}
|
|
|
|
reader.getInt();
|
|
|
|
}
|
|
|
|
|
|
|
|
public int getActionType() {
|
|
|
|
return this.actionType;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setActionType(int value) {
|
|
|
|
this.actionType = value;
|
|
|
|
}
|
|
|
|
|
|
|
|
public int getID() {
|
|
|
|
return this.msgID;
|
|
|
|
}
|
|
|
|
|
|
|
|
public String getMsg() {
|
|
|
|
return msg;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setMsg(String value) {
|
|
|
|
this.msg = value;
|
|
|
|
}
|
|
|
|
|
|
|
|
public int getContractType() {
|
|
|
|
return this.contractType;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setContractType(int value) {
|
|
|
|
this.contractType = value;
|
|
|
|
}
|
|
|
|
|
|
|
|
public int getContractID() {
|
|
|
|
return this.contractID;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setContractID(int value) {
|
|
|
|
this.contractID = value;
|
|
|
|
}
|
|
|
|
|
|
|
|
public byte getUnknown01() {
|
|
|
|
return this.unknown01;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setUnknown01(byte value) {
|
|
|
|
this.unknown01 = value;
|
|
|
|
}
|
|
|
|
|
|
|
|
public float getX() {
|
|
|
|
return this.x;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setX(float value) {
|
|
|
|
this.x = value;
|
|
|
|
}
|
|
|
|
|
|
|
|
public float getY() {
|
|
|
|
return this.y;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setY(float value) {
|
|
|
|
this.y = value;
|
|
|
|
}
|
|
|
|
|
|
|
|
public float getZ() {
|
|
|
|
return this.z;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setZ(float value) {
|
|
|
|
this.z = value;
|
|
|
|
}
|
|
|
|
|
|
|
|
public byte getUnknown02() {
|
|
|
|
return this.unknown02;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setUnknown02(byte value) {
|
|
|
|
this.unknown02 = value;
|
|
|
|
}
|
|
|
|
|
|
|
|
public ArrayList<PlacementInfo> getPlacementInfo() {
|
|
|
|
return this.placementInfo;
|
|
|
|
}
|
|
|
|
|
|
|
|
public PlacementInfo getFirstPlacementInfo() {
|
|
|
|
if (this.placementInfo.size() > 0)
|
|
|
|
return this.placementInfo.get(0);
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setMsgID(int value) {
|
|
|
|
this.msgID = value;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void addPlacementInfo(int ID) {
|
|
|
|
PlacementInfo pi = new PlacementInfo(ID, 0f, 0f, 0f, 0f, 0f, 0f, 0f);
|
|
|
|
this.placementInfo.add(pi);
|
|
|
|
}
|
|
|
|
|
|
|
|
public static class PlacementInfo {
|
|
|
|
int blueprintUUID;
|
|
|
|
Vector3fImmutable loc;
|
|
|
|
float w;
|
|
|
|
Vector3fImmutable rot;
|
|
|
|
|
|
|
|
public PlacementInfo(int blueprintUUID, float locX, float locY, float locZ, float w, float rotX, float rotY, float rotZ) {
|
|
|
|
this.blueprintUUID = blueprintUUID;
|
|
|
|
this.loc = new Vector3fImmutable(locX, locY, locZ);
|
|
|
|
this.w = w;
|
|
|
|
this.rot = new Vector3fImmutable(rotX, rotY, rotZ);
|
|
|
|
}
|
|
|
|
|
|
|
|
public int getBlueprintUUID() {
|
|
|
|
return this.blueprintUUID;
|
|
|
|
}
|
|
|
|
|
|
|
|
public Vector3fImmutable getLoc() {
|
|
|
|
return this.loc;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setLoc(Vector3fImmutable loc) {
|
|
|
|
this.loc = loc;
|
|
|
|
}
|
|
|
|
|
|
|
|
public float getW() {
|
|
|
|
return this.w;
|
|
|
|
}
|
|
|
|
|
|
|
|
public Vector3fImmutable getRot() {
|
|
|
|
return this.rot;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|