New characters now utilise the MakeCharInfo.img data in the WZ files

This commit is contained in:
Silwhoon
2024-02-05 16:03:41 +00:00
parent 799cb97564
commit a7931c3e4d
7 changed files with 204 additions and 59 deletions

View File

@@ -47,19 +47,19 @@ public abstract class CharacterFactory {
return -1;
}
Character newchar = Character.getDefault(c);
newchar.setWorld(c.getWorld());
newchar.setSkinColor(SkinColor.getById(skin));
newchar.setGender(gender);
newchar.setName(name);
newchar.setHair(hair);
newchar.setFace(face);
Character newCharacter = Character.getDefault(c);
newCharacter.setWorld(c.getWorld());
newCharacter.setSkinColor(SkinColor.getById(skin));
newCharacter.setGender(gender);
newCharacter.setName(name);
newCharacter.setHair(hair);
newCharacter.setFace(face);
newchar.setLevel(recipe.getLevel());
newchar.setJob(recipe.getJob());
newchar.setMapId(recipe.getMap());
newCharacter.setLevel(recipe.getLevel());
newCharacter.setJob(recipe.getJob());
newCharacter.setMapId(recipe.getMap());
Inventory equipped = newchar.getInventory(InventoryType.EQUIPPED);
Inventory equipped = newCharacter.getInventory(InventoryType.EQUIPPED);
ItemInformationProvider ii = ItemInformationProvider.getInstance();
int top = recipe.getTop(), bottom = recipe.getBottom(), shoes = recipe.getShoes(), weapon = recipe.getWeapon();
@@ -88,12 +88,17 @@ public abstract class CharacterFactory {
equipped.addItemFromDB(eq_weapon.copy());
}
if (!newchar.insertNewChar(recipe)) {
if (!MakeCharInfoHandler.isNewCharacterValid(newCharacter)) {
log.warn("Owner from account {} tried to packet edit in character creation", c.getAccountName());
return -2;
}
c.sendPacket(PacketCreator.addNewCharEntry(newchar));
Server.getInstance().createCharacterEntry(newchar);
if (!newCharacter.insertNewChar(recipe)) {
return -2;
}
c.sendPacket(PacketCreator.addNewCharEntry(newCharacter));
Server.getInstance().createCharacterEntry(newCharacter);
Server.getInstance().broadcastGMMessage(c.getWorld(), PacketCreator.sendYellowTip("[New Char]: " + c.getAccountName() + " has created a new character with IGN " + name));
log.info("Account {} created chr with name {}", c.getAccountName(), name);

View File

@@ -0,0 +1,140 @@
package client.creator;
import client.Character;
import client.Job;
import client.inventory.InventoryType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import provider.Data;
import provider.DataTool;
import java.util.ArrayList;
import java.util.List;
public class MakeCharInfo {
private static final Logger log = LoggerFactory.getLogger(MakeCharInfo.class);
private static final String FACE_ID = "0";
private static final String HAIR_ID = "1";
private static final String HAIR_COLOR_ID = "2";
private static final String SKIN_ID = "3";
private static final String TOP_ID = "4";
private static final String BOTTOM_ID = "5";
private static final String SHOE_ID = "6";
private static final String WEAPON_ID = "7";
private final List<Integer> charFaces = new ArrayList<>();
private final List<Integer> charHairs = new ArrayList<>();
private final List<Integer> charHairColors = new ArrayList<>();
private final List<Integer> charSkins = new ArrayList<>();
private final List<Integer> charTops = new ArrayList<>();
private final List<Integer> charBottoms = new ArrayList<>();
private final List<Integer> charShoes = new ArrayList<>();
private final List<Integer> charWeapons = new ArrayList<>();
public MakeCharInfo(Data charInfoData) {
for (Data data : charInfoData.getChildren()) {
switch (data.getName()) {
case FACE_ID -> {
for (Data faceData : data) {
charFaces.add(DataTool.getInt(faceData));
}
}
case HAIR_ID -> {
for (Data hairData : data) {
charHairs.add(DataTool.getInt(hairData));
}
}
case HAIR_COLOR_ID -> {
for (Data hairColorData : data) {
charHairColors.add(DataTool.getInt(hairColorData));
}
}
case SKIN_ID -> {
for (Data skinData : data) {
charSkins.add(DataTool.getInt(skinData));
}
}
case TOP_ID -> {
for (Data topData : data) {
charTops.add(DataTool.getInt(topData));
}
}
case BOTTOM_ID -> {
for (Data bottomData : data) {
charBottoms.add(DataTool.getInt(bottomData));
}
}
case SHOE_ID -> {
for (Data shoeData : data) {
charShoes.add(DataTool.getInt(shoeData));
}
}
case WEAPON_ID -> {
for (Data weaponData : data) {
charWeapons.add(DataTool.getInt(weaponData));
}
}
default -> log.error("Unhandled node inside MakeCharInfo.img.xml: '" + data.getName() + "'");
}
}
}
public boolean verifyFaceId(int id) {
return this.charFaces.contains(id);
}
public boolean verifyHairId(int id) {
if (id % 10 != 0) {
return this.charHairs.contains(id - (id % 10));
}
return this.charHairs.contains(id);
}
public boolean verifyHairColorId(int id) {
return this.charHairColors.contains(id % 10);
}
public boolean verifySkinId(int id) {
return this.charSkins.contains(id);
}
public boolean verifyTopId(int id) {
return this.charTops.contains(id);
}
public boolean verifyBottomId(int id) {
return this.charBottoms.contains(id);
}
public boolean verifyShoeId(int id) {
return this.charShoes.contains(id);
}
public boolean verifyWeaponId(int id) {
return this.charWeapons.contains(id);
}
public boolean verifyCharacter(Character character) {
if (!verifyFaceId(character.getFace())) return false;
if (!verifyHairId(character.getHair())) return false;
if (!verifyHairColorId(character.getHair())) return false;
if (!verifySkinId(character.getSkinColor().getId())) return false;
// Here we only verify the equipment if the character that's being created is of type 'Beginner'
// This is because when the Maple Life A or Maple Life B items are used, the client does not send any data
// regarding what equipment the character should be wearing (as it's all handled server-side)
Job characterJob = character.getJob();
if (characterJob == Job.BEGINNER || characterJob == Job.NOBLESSE || characterJob == Job.LEGEND) {
if (!verifyTopId(character.getInventory(InventoryType.EQUIPPED).getItem((short) -5).getItemId()))
return false;
if (!verifyBottomId(character.getInventory(InventoryType.EQUIPPED).getItem((short) -6).getItemId()))
return false;
if (!verifyShoeId(character.getInventory(InventoryType.EQUIPPED).getItem((short) -7).getItemId()))
return false;
if (!verifyWeaponId(character.getInventory(InventoryType.EQUIPPED).getItem((short) -11).getItemId()))
return false;
}
return true;
}
}

View File

@@ -0,0 +1,41 @@
package client.creator;
import client.Character;
import provider.Data;
import provider.DataProviderFactory;
import provider.wz.WZFiles;
public class MakeCharInfoHandler {
private static final MakeCharInfo charFemale;
private static final MakeCharInfo charMale;
private static final MakeCharInfo orientCharFemale;
private static final MakeCharInfo orientCharMale;
private static final MakeCharInfo premiumCharFemale;
private static final MakeCharInfo premiumCharMale;
static {
Data data = DataProviderFactory.getDataProvider(WZFiles.ETC).getData("MakeCharInfo.img");
charFemale = new MakeCharInfo(data.getChildByPath("Info/CharFemale"));
charMale = new MakeCharInfo(data.getChildByPath("Info/CharMale"));
orientCharFemale = new MakeCharInfo(data.getChildByPath("OrientCharFemale"));
orientCharMale = new MakeCharInfo(data.getChildByPath("OrientCharMale"));
premiumCharFemale = new MakeCharInfo(data.getChildByPath("PremiumCharFemale"));
premiumCharMale = new MakeCharInfo(data.getChildByPath("PremiumCharMale"));
}
private static MakeCharInfo getMakeCharInfo(Character character) {
return switch (character.getJob()) {
case BEGINNER, WARRIOR, MAGICIAN, BOWMAN, THIEF, PIRATE -> character.isMale() ? charMale : charFemale;
case NOBLESSE -> character.isMale() ? premiumCharMale : premiumCharFemale;
case LEGEND -> character.isMale() ? orientCharMale : orientCharFemale;
default -> null;
};
}
public static boolean isNewCharacterValid(Character character) {
MakeCharInfo makeCharInfo = getMakeCharInfo(character);
if (makeCharInfo == null) return false;
return makeCharInfo.verifyCharacter(character);
}
}

View File

@@ -43,7 +43,6 @@ public class BeginnerCreator extends CharacterFactory {
}
public static int createCharacter(Client c, String name, int face, int hair, int skin, int top, int bottom, int shoes, int weapon, int gender) {
int status = createNewCharacter(c, name, face, hair, skin, gender, createRecipe(Job.BEGINNER, 1, MapId.MUSHROOM_TOWN, top, bottom, shoes, weapon));
return status;
return createNewCharacter(c, name, face, hair, skin, gender, createRecipe(Job.BEGINNER, 1, MapId.MUSHROOM_TOWN, top, bottom, shoes, weapon));
}
}

View File

@@ -43,7 +43,6 @@ public class LegendCreator extends CharacterFactory {
}
public static int createCharacter(Client c, String name, int face, int hair, int skin, int top, int bottom, int shoes, int weapon, int gender) {
int status = createNewCharacter(c, name, face, hair, skin, gender, createRecipe(Job.LEGEND, 1, MapId.ARAN_TUTORIAL_START, top, bottom, shoes, weapon));
return status;
return createNewCharacter(c, name, face, hair, skin, gender, createRecipe(Job.LEGEND, 1, MapId.ARAN_TUTORIAL_START, top, bottom, shoes, weapon));
}
}

View File

@@ -43,7 +43,6 @@ public class NoblesseCreator extends CharacterFactory {
}
public static int createCharacter(Client c, String name, int face, int hair, int skin, int top, int bottom, int shoes, int weapon, int gender) {
int status = createNewCharacter(c, name, face, hair, skin, gender, createRecipe(Job.NOBLESSE, 1, MapId.STARTING_MAP_NOBLESSE, top, bottom, shoes, weapon));
return status;
return createNewCharacter(c, name, face, hair, skin, gender, createRecipe(Job.NOBLESSE, 1, MapId.STARTING_MAP_NOBLESSE, top, bottom, shoes, weapon));
}
}

View File

@@ -25,43 +25,14 @@ import client.Client;
import client.creator.novice.BeginnerCreator;
import client.creator.novice.LegendCreator;
import client.creator.novice.NoblesseCreator;
import constants.id.ItemId;
import net.AbstractPacketHandler;
import net.packet.InPacket;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import tools.PacketCreator;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
public final class CreateCharHandler extends AbstractPacketHandler {
private static final Logger log = LoggerFactory.getLogger(CreateCharHandler.class);
private final static Set<Integer> IDs = new HashSet<>(Arrays.asList(
ItemId.SWORD, ItemId.HAND_AXE, ItemId.WOODEN_CLUB, ItemId.BASIC_POLEARM,// weapons
ItemId.WHITE_UNDERSHIRT, ItemId.UNDERSHIRT, ItemId.GREY_TSHIRT, ItemId.WHITE_TUBETOP, ItemId.YELLOW_TSHIRT,
ItemId.GREEN_TSHIRT, ItemId.RED_STRIPED_TOP, ItemId.SIMPLE_WARRIOR_TOP,// bottom
ItemId.BLUE_JEAN_SHORTS, ItemId.BROWN_COTTON_SHORTS, ItemId.RED_MINISKIRT, ItemId.INDIGO_MINISKIRT,
ItemId.SIMPLE_WARRIOR_PANTS, // top
ItemId.RED_RUBBER_BOOTS, ItemId.LEATHER_SANDALS, ItemId.YELLOW_RUBBER_BOOTS, ItemId.BLUE_RUBBER_BOOTS,
ItemId.AVERAGE_MUSASHI_SHOES,// shoes
ItemId.BLACK_TOBEN, ItemId.ZETA, ItemId.BLACK_REBEL, ItemId.BLACK_BUZZ, ItemId.BLACK_SAMMY,
ItemId.BLACK_EDGY, ItemId.BLACK_CONNIE,// hair
ItemId.MOTIVATED_LOOK_M, ItemId.PERPLEXED_STARE, ItemId.LEISURE_LOOK_M, ItemId.MOTIVATED_LOOK_F,
ItemId.FEARFUL_STARE_M, ItemId.LEISURE_LOOK_F, ItemId.FEARFUL_STARE_F, ItemId.PERPLEXED_STARE_HAZEL,
ItemId.LEISURE_LOOK_HAZEL, ItemId.MOTIVATED_LOOK_AMETHYST, ItemId.MOTIVATED_LOOK_BLUE //face
//#NeverTrustStevenCode
));
private static boolean isLegal(Integer toCompare) {
return IDs.contains(toCompare);
}
@Override
public final void handlePacket(InPacket p, Client c) {
public void handlePacket(InPacket p, Client c) {
String name = p.readString();
int job = p.readInt();
int face = p.readInt();
@@ -76,15 +47,6 @@ public final class CreateCharHandler extends AbstractPacketHandler {
int weapon = p.readInt();
int gender = p.readByte();
int[] items = new int[]{weapon, top, bottom, shoes, hair, face};
for (int item : items) {
if (!isLegal(item)) {
log.warn("Owner from account {} tried to packet edit in chr creation", c.getAccountName());
c.disconnect(true, false);
return;
}
}
int status;
switch (job) {
case 0: // Knights of Cygnus