Compare commits

...

5 Commits

Author SHA1 Message Date
Ponk
830df4e5ca Merge pull request #218 from Silwhoon/makecharinfo #minor
Utilize the MakeCharInfo.img data in the WZ files
2024-02-05 18:09:12 +01:00
Silwhoon
6f68f4edfd Addressed nitpicks and removed unused item ID constants 2024-02-05 17:00:18 +00:00
Silwhoon
a7931c3e4d New characters now utilise the MakeCharInfo.img data in the WZ files 2024-02-05 16:03:41 +00:00
Ponk
799cb97564 Merge pull request #217 from P0nk/fix/210-clean-slate-scroll #minor
Fix able to gain infinite slots with clean slate scroll
2024-02-05 08:39:25 +01:00
P0nk
851b57e8ef Fix able to gain infinite slots with clean slate scroll
And remove a GM config option.
Thanks Crabo for the suggested solution.
2024-02-05 08:34:36 +01:00
12 changed files with 259 additions and 130 deletions

View File

@@ -347,7 +347,6 @@ server:
USE_PERFECT_SCROLLING: false #Scrolls doesn't use slots upon failure. USE_PERFECT_SCROLLING: false #Scrolls doesn't use slots upon failure.
USE_ENHANCED_CHSCROLL: false #Equips even more powerful with chaos upgrade. USE_ENHANCED_CHSCROLL: false #Equips even more powerful with chaos upgrade.
USE_ENHANCED_CRAFTING: false #Apply chaos scroll on every equip crafted. USE_ENHANCED_CRAFTING: false #Apply chaos scroll on every equip crafted.
USE_ENHANCED_CLNSLATE: false #Clean slates can be applied to recover successfully used slots as well.
SCROLL_CHANCE_ROLLS: 1 #Number of rolls for success on a scroll, set 1 for default. SCROLL_CHANCE_ROLLS: 1 #Number of rolls for success on a scroll, set 1 for default.
CHSCROLL_STAT_RATE: 1 #Number of rolls of stat upgrade on a successfully applied chaos scroll, set 1 for default. CHSCROLL_STAT_RATE: 1 #Number of rolls of stat upgrade on a successfully applied chaos scroll, set 1 for default.
CHSCROLL_STAT_RANGE: 6 #Stat upgrade range (-N, N) on chaos scrolls. CHSCROLL_STAT_RANGE: 6 #Stat upgrade range (-N, N) on chaos scrolls.

View File

@@ -47,19 +47,19 @@ public abstract class CharacterFactory {
return -1; return -1;
} }
Character newchar = Character.getDefault(c); Character newCharacter = Character.getDefault(c);
newchar.setWorld(c.getWorld()); newCharacter.setWorld(c.getWorld());
newchar.setSkinColor(SkinColor.getById(skin)); newCharacter.setSkinColor(SkinColor.getById(skin));
newchar.setGender(gender); newCharacter.setGender(gender);
newchar.setName(name); newCharacter.setName(name);
newchar.setHair(hair); newCharacter.setHair(hair);
newchar.setFace(face); newCharacter.setFace(face);
newchar.setLevel(recipe.getLevel()); newCharacter.setLevel(recipe.getLevel());
newchar.setJob(recipe.getJob()); newCharacter.setJob(recipe.getJob());
newchar.setMapId(recipe.getMap()); newCharacter.setMapId(recipe.getMap());
Inventory equipped = newchar.getInventory(InventoryType.EQUIPPED); Inventory equipped = newCharacter.getInventory(InventoryType.EQUIPPED);
ItemInformationProvider ii = ItemInformationProvider.getInstance(); ItemInformationProvider ii = ItemInformationProvider.getInstance();
int top = recipe.getTop(), bottom = recipe.getBottom(), shoes = recipe.getShoes(), weapon = recipe.getWeapon(); 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()); equipped.addItemFromDB(eq_weapon.copy());
} }
if (!newchar.insertNewChar(recipe)) { if (!MakeCharInfoValidator.isNewCharacterValid(newCharacter)) {
log.warn("Owner from account {} tried to packet edit in character creation", c.getAccountName());
return -2; 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)); 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); 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.HashSet;
import java.util.Set;
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 Set<Integer> charFaces = new HashSet<>();
private final Set<Integer> charHairs = new HashSet<>();
private final Set<Integer> charHairColors = new HashSet<>();
private final Set<Integer> charSkins = new HashSet<>();
private final Set<Integer> charTops = new HashSet<>();
private final Set<Integer> charBottoms = new HashSet<>();
private final Set<Integer> charShoes = new HashSet<>();
private final Set<Integer> charWeapons = new HashSet<>();
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 MakeCharInfoValidator {
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) { 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 createNewCharacter(c, name, face, hair, skin, gender, createRecipe(Job.BEGINNER, 1, MapId.MUSHROOM_TOWN, top, bottom, shoes, weapon));
return status;
} }
} }

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) { 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 createNewCharacter(c, name, face, hair, skin, gender, createRecipe(Job.LEGEND, 1, MapId.ARAN_TUTORIAL_START, top, bottom, shoes, weapon));
return status;
} }
} }

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) { 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 createNewCharacter(c, name, face, hair, skin, gender, createRecipe(Job.NOBLESSE, 1, MapId.STARTING_MAP_NOBLESSE, top, bottom, shoes, weapon));
return status;
} }
} }

View File

@@ -195,7 +195,6 @@ public class ServerConfig {
public boolean USE_PERFECT_SCROLLING; public boolean USE_PERFECT_SCROLLING;
public boolean USE_ENHANCED_CHSCROLL; public boolean USE_ENHANCED_CHSCROLL;
public boolean USE_ENHANCED_CRAFTING; public boolean USE_ENHANCED_CRAFTING;
public boolean USE_ENHANCED_CLNSLATE;
public int SCROLL_CHANCE_ROLLS; public int SCROLL_CHANCE_ROLLS;
public int CHSCROLL_STAT_RATE; public int CHSCROLL_STAT_RATE;
public int CHSCROLL_STAT_RANGE; public int CHSCROLL_STAT_RANGE;

View File

@@ -95,46 +95,6 @@ public class ItemId {
public static final int BEGINNERS_GUIDE = 4161001; public static final int BEGINNERS_GUIDE = 4161001;
public static final int LEGENDS_GUIDE = 4161048; public static final int LEGENDS_GUIDE = 4161048;
public static final int NOBLESSE_GUIDE = 4161047; public static final int NOBLESSE_GUIDE = 4161047;
public static final int SWORD = 1302000; // Weapon
public static final int HAND_AXE = 1312004;
public static final int WOODEN_CLUB = 1322005;
public static final int BASIC_POLEARM = 1442079;
public static final int WHITE_UNDERSHIRT = 1040002; // Top
public static final int UNDERSHIRT = 1040006;
public static final int GREY_TSHIRT = 1040010;
public static final int WHITE_TUBETOP = 1041002;
public static final int YELLOW_TSHIRT = 1041006;
public static final int GREEN_TSHIRT = 1041010;
public static final int RED_STRIPED_TOP = 1041011;
public static final int SIMPLE_WARRIOR_TOP = 1042167;
public static final int BLUE_JEAN_SHORTS = 1060002; // Bottom
public static final int BROWN_COTTON_SHORTS = 1060006;
public static final int RED_MINISKIRT = 1061002;
public static final int INDIGO_MINISKIRT = 1061008;
public static final int SIMPLE_WARRIOR_PANTS = 1062115;
public static final int RED_RUBBER_BOOTS = 1072001;
public static final int LEATHER_SANDALS = 1072005;
public static final int YELLOW_RUBBER_BOOTS = 1072037;
public static final int BLUE_RUBBER_BOOTS = 1072038;
public static final int AVERAGE_MUSASHI_SHOES = 1072383;
public static final int BLACK_TOBEN = 30000; // Hair
public static final int ZETA = 30010;
public static final int BLACK_REBEL = 30020;
public static final int BLACK_BUZZ = 30030;
public static final int BLACK_SAMMY = 31000;
public static final int BLACK_EDGY = 31040;
public static final int BLACK_CONNIE = 31050;
public static final int MOTIVATED_LOOK_M = 20000; // Face
public static final int PERPLEXED_STARE = 20001;
public static final int LEISURE_LOOK_M = 20002;
public static final int MOTIVATED_LOOK_F = 21000;
public static final int FEARFUL_STARE_M = 21001;
public static final int LEISURE_LOOK_F = 21002;
public static final int FEARFUL_STARE_F = 21201;
public static final int PERPLEXED_STARE_HAZEL = 20401;
public static final int LEISURE_LOOK_HAZEL = 20402;
public static final int MOTIVATED_LOOK_AMETHYST = 21700;
public static final int MOTIVATED_LOOK_BLUE = 20100;
// Warrior // Warrior
public static final int RED_HWARANG_SHIRT = 1040021; public static final int RED_HWARANG_SHIRT = 1040021;

View File

@@ -25,8 +25,12 @@ import client.Character;
import client.Client; import client.Client;
import client.Skill; import client.Skill;
import client.SkillFactory; import client.SkillFactory;
import client.inventory.*; import client.inventory.Equip;
import client.inventory.Equip.ScrollResult; import client.inventory.Equip.ScrollResult;
import client.inventory.Inventory;
import client.inventory.InventoryType;
import client.inventory.Item;
import client.inventory.ModifyInventory;
import client.inventory.manipulator.InventoryManipulator; import client.inventory.manipulator.InventoryManipulator;
import constants.id.ItemId; import constants.id.ItemId;
import constants.inventory.ItemConstants; import constants.inventory.ItemConstants;
@@ -37,7 +41,6 @@ import tools.PacketCreator;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map;
/** /**
* @author Matze * @author Matze
@@ -50,8 +53,8 @@ public final class ScrollHandler extends AbstractPacketHandler {
if (c.tryacquireClient()) { if (c.tryacquireClient()) {
try { try {
p.readInt(); // whatever... p.readInt(); // whatever...
short slot = p.readShort(); short scrollSlot = p.readShort();
short dst = p.readShort(); short equipSlot = p.readShort();
byte ws = (byte) p.readShort(); byte ws = (byte) p.readShort();
boolean whiteScroll = false; // white scroll being used? boolean whiteScroll = false; // white scroll being used?
boolean legendarySpirit = false; // legendary spirit skill boolean legendarySpirit = false; // legendary spirit skill
@@ -61,24 +64,21 @@ public final class ScrollHandler extends AbstractPacketHandler {
ItemInformationProvider ii = ItemInformationProvider.getInstance(); ItemInformationProvider ii = ItemInformationProvider.getInstance();
Character chr = c.getPlayer(); Character chr = c.getPlayer();
Equip toScroll = (Equip) chr.getInventory(InventoryType.EQUIPPED).getItem(dst); Equip toScroll = (Equip) chr.getInventory(InventoryType.EQUIPPED).getItem(equipSlot);
Skill LegendarySpirit = SkillFactory.getSkill(1003); Skill LegendarySpirit = SkillFactory.getSkill(1003);
if (chr.getSkillLevel(LegendarySpirit) > 0 && dst >= 0) { if (chr.getSkillLevel(LegendarySpirit) > 0 && equipSlot >= 0) {
legendarySpirit = true; legendarySpirit = true;
toScroll = (Equip) chr.getInventory(InventoryType.EQUIP).getItem(dst); toScroll = (Equip) chr.getInventory(InventoryType.EQUIP).getItem(equipSlot);
} }
byte oldLevel = toScroll.getLevel(); byte oldLevel = toScroll.getLevel();
byte oldSlots = toScroll.getUpgradeSlots(); byte oldSlots = toScroll.getUpgradeSlots();
Inventory useInventory = chr.getInventory(InventoryType.USE); Inventory useInventory = chr.getInventory(InventoryType.USE);
Item scroll = useInventory.getItem(slot); Item scroll = useInventory.getItem(scrollSlot);
Item wscroll = null; Item wscroll = null;
if (ItemConstants.isCleanSlate(scroll.getItemId())) { if (ItemConstants.isCleanSlate(scroll.getItemId()) && !ii.canUseCleanSlate(toScroll)) {
Map<String, Integer> eqStats = ii.getEquipStats(toScroll.getItemId()); // clean slate issue found thanks to Masterrulax announceCannotScroll(c, legendarySpirit);
if (eqStats == null || eqStats.get("tuc") == 0) { return;
announceCannotScroll(c, legendarySpirit);
return;
}
} else if (!ItemConstants.isModifierScroll(scroll.getItemId()) && toScroll.getUpgradeSlots() < 1) { } else if (!ItemConstants.isModifierScroll(scroll.getItemId()) && toScroll.getUpgradeSlots() < 1) {
announceCannotScroll(c, legendarySpirit); // thanks onechord for noticing zero upgrade slots freezing Legendary Scroll UI announceCannotScroll(c, legendarySpirit); // thanks onechord for noticing zero upgrade slots freezing Legendary Scroll UI
return; return;
@@ -103,11 +103,6 @@ public final class ScrollHandler extends AbstractPacketHandler {
} }
} }
if (ItemConstants.isCleanSlate(scroll.getItemId()) && !ii.canUseCleanSlate(toScroll)) {
announceCannotScroll(c, legendarySpirit);
return;
}
Equip scrolled = (Equip) ii.scrollEquipWithId(toScroll, scroll.getItemId(), whiteScroll, 0, chr.isGM()); Equip scrolled = (Equip) ii.scrollEquipWithId(toScroll, scroll.getItemId(), whiteScroll, 0, chr.isGM());
ScrollResult scrollSuccess = Equip.ScrollResult.FAIL; // fail ScrollResult scrollSuccess = Equip.ScrollResult.FAIL; // fail
if (scrolled == null) { if (scrolled == null) {
@@ -141,7 +136,7 @@ public final class ScrollHandler extends AbstractPacketHandler {
if (scrollSuccess == Equip.ScrollResult.CURSE) { if (scrollSuccess == Equip.ScrollResult.CURSE) {
if (!ItemId.isWeddingRing(toScroll.getItemId())) { if (!ItemId.isWeddingRing(toScroll.getItemId())) {
mods.add(new ModifyInventory(3, toScroll)); mods.add(new ModifyInventory(3, toScroll));
if (dst < 0) { if (equipSlot < 0) {
Inventory inv = chr.getInventory(InventoryType.EQUIPPED); Inventory inv = chr.getInventory(InventoryType.EQUIPPED);
inv.lockInventory(); inv.lockInventory();
@@ -174,7 +169,7 @@ public final class ScrollHandler extends AbstractPacketHandler {
} }
c.sendPacket(PacketCreator.modifyInventory(true, mods)); c.sendPacket(PacketCreator.modifyInventory(true, mods));
chr.getMap().broadcastMessage(PacketCreator.getScrollEffect(chr.getId(), scrollSuccess, legendarySpirit, whiteScroll)); chr.getMap().broadcastMessage(PacketCreator.getScrollEffect(chr.getId(), scrollSuccess, legendarySpirit, whiteScroll));
if (dst < 0 && (scrollSuccess == Equip.ScrollResult.SUCCESS || scrollSuccess == Equip.ScrollResult.CURSE)) { if (equipSlot < 0 && (scrollSuccess == Equip.ScrollResult.SUCCESS || scrollSuccess == Equip.ScrollResult.CURSE)) {
chr.equipChanged(); chr.equipChanged();
} }
} finally { } finally {

View File

@@ -25,43 +25,14 @@ import client.Client;
import client.creator.novice.BeginnerCreator; import client.creator.novice.BeginnerCreator;
import client.creator.novice.LegendCreator; import client.creator.novice.LegendCreator;
import client.creator.novice.NoblesseCreator; import client.creator.novice.NoblesseCreator;
import constants.id.ItemId;
import net.AbstractPacketHandler; import net.AbstractPacketHandler;
import net.packet.InPacket; import net.packet.InPacket;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import tools.PacketCreator; import tools.PacketCreator;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
public final class CreateCharHandler extends AbstractPacketHandler { 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 @Override
public final void handlePacket(InPacket p, Client c) { public void handlePacket(InPacket p, Client c) {
String name = p.readString(); String name = p.readString();
int job = p.readInt(); int job = p.readInt();
int face = p.readInt(); int face = p.readInt();
@@ -76,15 +47,6 @@ public final class CreateCharHandler extends AbstractPacketHandler {
int weapon = p.readInt(); int weapon = p.readInt();
int gender = p.readByte(); 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; int status;
switch (job) { switch (job) {
case 0: // Knights of Cygnus case 0: // Knights of Cygnus

View File

@@ -22,9 +22,16 @@
package server; package server;
import client.Character; import client.Character;
import client.*; import client.Client;
import client.Job;
import client.Skill;
import client.SkillFactory;
import client.autoban.AutobanFactory; import client.autoban.AutobanFactory;
import client.inventory.*; import client.inventory.Equip;
import client.inventory.Inventory;
import client.inventory.InventoryType;
import client.inventory.Item;
import client.inventory.WeaponType;
import config.YamlConfig; import config.YamlConfig;
import constants.id.ItemId; import constants.id.ItemId;
import constants.inventory.EquipSlot; import constants.inventory.EquipSlot;
@@ -35,19 +42,36 @@ import constants.skills.NightWalker;
import net.server.Server; import net.server.Server;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import provider.*; import provider.Data;
import provider.DataDirectoryEntry;
import provider.DataFileEntry;
import provider.DataProvider;
import provider.DataProviderFactory;
import provider.DataTool;
import provider.wz.WZFiles; import provider.wz.WZFiles;
import server.MakerItemFactory.MakerItemCreateEntry; import server.MakerItemFactory.MakerItemCreateEntry;
import server.life.LifeFactory; import server.life.LifeFactory;
import server.life.MonsterInformationProvider; import server.life.MonsterInformationProvider;
import tools.*; import tools.DatabaseConnection;
import tools.PacketCreator;
import tools.Pair;
import tools.Randomizer;
import tools.StringUtil;
import java.sql.Connection; import java.sql.Connection;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.*; import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.Set;
/** /**
* @author Matze * @author Matze
@@ -1025,9 +1049,16 @@ public class ItemInformationProvider {
Issue with clean slate found thanks to Masterrulax Issue with clean slate found thanks to Masterrulax
Vicious added in the clean slate check thanks to Crypter (CrypterDEV) Vicious added in the clean slate check thanks to Crypter (CrypterDEV)
*/ */
public boolean canUseCleanSlate(Equip nEquip) { public boolean canUseCleanSlate(Equip equip) {
Map<String, Integer> eqstats = this.getEquipStats(nEquip.getItemId()); Map<String, Integer> eqStats = getEquipStats(equip.getItemId());
return YamlConfig.config.server.USE_ENHANCED_CLNSLATE || nEquip.getUpgradeSlots() < (byte) (eqstats.get("tuc") + nEquip.getVicious()); if (eqStats == null || eqStats.get("tuc") == 0 ) {
return false;
}
int totalUpgradeCount = eqStats.get("tuc");
int freeUpgradeCount = equip.getUpgradeSlots();
int viciousCount = equip.getVicious();
int appliedScrollCount = equip.getLevel();
return freeUpgradeCount + appliedScrollCount < totalUpgradeCount + viciousCount;
} }
public Item scrollEquipWithId(Item equip, int scrollId, boolean usingWhiteScroll, int vegaItemId, boolean isGM) { public Item scrollEquipWithId(Item equip, int scrollId, boolean usingWhiteScroll, int vegaItemId, boolean isGM) {