diff --git a/handbook/Cash.txt b/handbook/Cash.txt index 1ed3d0917c..47f7583827 100644 --- a/handbook/Cash.txt +++ b/handbook/Cash.txt @@ -264,7 +264,7 @@ 5160006 - Sparkling Eyes - On the KeyConfig, configure this expression on a button of your choice. Press the button and watch your character display sparkling eyes. 5160007 - Flaming - On the KeyConfig, configure this expression on a button of your choice. Press the button and watch your character display the look of rage. 5160008 - Ray - On the KeyConfig, configure this expression on a button of your choice. Press the button and watch your character display beaming eyes. -5160009 - Goo Goo - On the KeyConfig, configure this expression on a button of your choice. Press the button and watch your character display the look of “awesome!!!” +5160009 - Goo Goo - On the KeyConfig, configure this expression on a button of your choice. Press the button and watch your character display the look of �awesome!!!� 5160010 - Whoa Whoa - On the KeyConfig, configure this expression on a button of your choice. Press the button and watch your character display the look of being flustered. 5160011 - Constant Sigh - On the KeyConfig, configure this expression on a button of your choice. Press the button and watch your character display the thinking look. 5160012 - Drool - On the KeyConfig, configure this expression on a button of your choice. Press the button and watch your character act like falling asleep. @@ -479,9 +479,9 @@ 5610001 - Vega's Spell(60%) - This winning spell from Vega enables a 90% success rate on a 60% scroll. Please check the scroll description to confirm that Vega's Spell is available for the scroll you choose. 5590000 - High-Five Stamp - Can equip items that are 5 levels above your current level. 5021026 - Gift Box Throwing Stars - A gift box that can be freely thrown around. Using the #cThrowing Star# will create an orbital effect.\n\nThis item cannot be deleted. -5010073 - Miss Popular - Well, lookie here. Someone’s certainly become popular with the guys. Turn this effect on and off by assigning it to a shortcut key from the keyboard settings menu. +5010073 - Miss Popular - Well, lookie here. Someone�s certainly become popular with the guys. Turn this effect on and off by assigning it to a shortcut key from the keyboard settings menu. -5010074 - Mr. Popular - Well, lookie here. Someone’s certainly become popular with the girls. Turn this effect on and off by assigning it to a shortcut key from the keyboard settings menu. +5010074 - Mr. Popular - Well, lookie here. Someone�s certainly become popular with the girls. Turn this effect on and off by assigning it to a shortcut key from the keyboard settings menu. 5240027 - Golden Drumstick - A drumstick that can be consumed only by #cBaby Tiger#. It recovers hunger and #cincreases Closeness by 100.# 5390005 - Cute Tiger Messenger - Shout to everyone in the world your character is on with this megaphone. Now available with your avatar on the top of everyone's screen! Comes with a tiger background for your avatar. diff --git a/handbook/Etc.txt b/handbook/Etc.txt index 903b1ba09b..2c94a8e479 100644 --- a/handbook/Etc.txt +++ b/handbook/Etc.txt @@ -1779,8 +1779,8 @@ 4032103 - The Lost Treasure - The lost treasure that was stolen by the Master of Disguise who brazenly entered Ereve. Let's take it back to Irena. 4032104 - The Lost Treasure - The lost treasure that was stolen by the Master of Disguise who brazenly entered Ereve. Let's take it back to Eckhart. 4032105 - The Lost Treasure - The lost treasure that was stolen by the Master of Disguise who brazenly entered Ereve. Let's take it back to Hawkeye. -4000209 - Co-ke Slime’s Bell - The bell of Co-ke Slime that has been taken off. -4000210 - Co-ke Pig’s Ribbon - A piece of Co-ke Pig’s ribbon. +4000209 - Co-ke Slime�s Bell - The bell of Co-ke Slime that has been taken off. +4000210 - Co-ke Pig�s Ribbon - A piece of Co-ke Pig�s ribbon. 4000211 - Coca-Cola Cube - A cube with a drawing of a Coca-Cola bottle on it. 4000212 - CokePLAY Cube - A cube with the CokePLAY symbol. 4000213 - Coca-Cola Card - A card with a drawing of Coca-Cola. @@ -1802,10 +1802,10 @@ 4001151 - Happy Valley - Happy Valley 4001152 - Ariant - Ariant 4001153 - Magatia - Magatia -4031832 - Sophelia’s Portrait - A portrait of Sophelia. +4031832 - Sophelia�s Portrait - A portrait of Sophelia. 4031833 - Pumpkin Juice - A juice made with pumpkin. It is very fragrant. 4031834 - Perfect Tool - The most perfect tool for making dolls. -4031835 - Lyudmilla’s Earring - The earrings that Lyudmilla lost. They shine with brilliance. +4031835 - Lyudmilla�s Earring - The earrings that Lyudmilla lost. They shine with brilliance. 4031836 - Score - The score that Lyudmilla asked for. No one knows what kind of music is in it. 4031837 - Dumped Doll - A doll that Sophelia used to cherish a long time ago. She threw it away when she got a new doll. 4031838 - Piece of Cloth - A small piece of cloth. If you drag and drop it onto the rag doll, the doll will be completed bit by bit. @@ -1893,26 +1893,26 @@ 4032127 - Proof of Ability - The Proof of Ability that is required to learn a new skill. This proof signifies that you are ready to learn a new skill. 4032128 - Proof of Ability - The Proof of Ability that is required to learn a new skill. This proof signifies that you are ready to learn a new skill. 4032129 - Proof of Ability - The Proof of Ability that is required to learn a new skill. This proof signifies that you are ready to learn a new skill. -4032130 - Pig Doll - An adorable doll that resembles a pig. However, something doesn't seem right… -4032131 - Pig Doll - An adorable doll that resembles a pig. However, something doesn't seem right… +4032130 - Pig Doll - An adorable doll that resembles a pig. However, something doesn't seem right� +4032131 - Pig Doll - An adorable doll that resembles a pig. However, something doesn't seem right� 4032132 - Roca's Mission Report - A mission report written by Roca, the Agent for Henesys. This compiles a list of events that have taken place recently. 4032136 - Bubbling Doll - An adorable doll that was designed based on Bubbling, but something doesn't seem right. The way it smiles just seems a bit off, as if it has hidden agenda. 4032137 - Bubbling Doll - An adorable doll that was designed based on Bubbling, but something doesn't seem right. The way it smiles just seems a bit off, as if it has hidden agenda. -4032138 - Bubbling Doll - An adorable doll that was designed based on Bubbling, but something doesn't seem right. It's in…tears. +4032138 - Bubbling Doll - An adorable doll that was designed based on Bubbling, but something doesn't seem right. It's in�tears. 4032139 - Old Key - An old, rusty key that Mr. Pickall has been looking for. -4032140 - Bubbling Doll - An adorable doll that was designed based on Bubbling, but something doesn't seem right. It's in…tears. +4032140 - Bubbling Doll - An adorable doll that was designed based on Bubbling, but something doesn't seem right. It's in�tears. 4032141 - Mattias' Mission Report - A mission report written by Roca, the Agent for Kerning City. This compiles a list of events that have taken place recently. 4032142 - Clear Tree Sap - A clear tree sap that can only be found at the very top of the skyscraping trees. Accompanied by the freshest green scent. 4032143 - Fruit - A fruit picked from plants near Henesys. 4032144 - Hersha's Mission Report - A mission report written by Hersha, the Agent for Ellinia. This compiles a list of events that have taken place recently. 4032145 - Detector - A detector made to detect any forces of darkness. Take this to the 10 Boogies. -4032146 - Wooden Mask Doll - An adorable doll modeled after the Wooden Mask, but something doesn't seem right… -4032147 - Rocky Mask Doll - An adorable doll modeled after the Stone Mask, but something doesn't seem right… +4032146 - Wooden Mask Doll - An adorable doll modeled after the Wooden Mask, but something doesn't seem right� +4032147 - Rocky Mask Doll - An adorable doll modeled after the Stone Mask, but something doesn't seem right� 4032148 - Detector - A detector created with the sole purpose of detecting the Puppeteer's movements. We put it to good use, so let's return it to Neinheart. 4032149 - 10 Boogies' Mission Report - A mission report written by 10 Boogies, the Agents for Perion. This compiles a list of events that have taken place recently. 4032178 - Hack Attempt - A record that shows that Chief Grays tried to hack into the system. 4032179 - Ereve Investigation Permit - A permitt that allows one to investigate every part of Ereve. When the Red Alert is on, this permit is the only way you can roam freely around Ereve. -4032190 - Orange Mushroom Doll - An adorable doll modeled after the Orange Mushroom, but something doesn't seem right… +4032190 - Orange Mushroom Doll - An adorable doll modeled after the Orange Mushroom, but something doesn't seem right� 4032196 - Concentrated Formula: Step 1 - A formula concentrated with effective and potent ingredients. The first formula used to raise Mimiana and Mimio 4032197 - Concentrated Formula: Step 2 - A formula concentrated with effective and potent ingredients. The second formula used to raise Mimiana and Mimio. 4032198 - Concentrated Formula: Step 3 - A formula concentrated with effective and potent ingredients. The third formula used to raise Mimiana and Mimio. @@ -2048,16 +2048,16 @@ 4032270 - Glistening Sunlight - Glistening sunlight filled with the feeling of spring. 4032271 - Pure Small Sprout - A fragrant new sprout filled with the energies of spring. Used as an ingredient for Pure Perfume. 4032272 - Stationery of Longing - Pink stationary that's rumored to return a favorable response if used to send a letter to a secret crush. -4032273 - Pencil of Courage X 10 - A pencil that's used to write things you don’t have the courage to say. +4032273 - Pencil of Courage X 10 - A pencil that's used to write things you don�t have the courage to say. 4032275 - Pure Normal Sprout - A fragrant new sprout filled with the energies of spring. Used as an ingredient for Pure Perfume. 4032276 - Pure Sprout - A fragrant new sprout filled with the energies of spring. Used as an ingredient for Pure Perfume. 4032277 - Pure Large Sprout - A fragrant new sprout filled with the energies of spring. Used as an ingredient for Pure Perfume. 4032278 - Stationery of Deep Longing - Pink stationary that's rumored to return a favorable response if used to send a letter to a secret crush. 4032279 - Stationary of Hope and Longing - Pink stationary that's rumored to return a favorable response if used to send a letter to a secret crush. 4032280 - Letter of Love and Longing - Pink stationary that's rumored to return a favorable response if used to send a letter to a secret crush. -4032281 - Pencil of Courage X 100 - A pencil that's used to write things you don’t have the courage to say. -4032282 - Pencil of Courage X 1000 - AA pencil that's used to write things you don’t have the courage to say. -4032283 - Pencil of Courage X 10000 - A pencil that's used to write things you don’t have the courage to say. +4032281 - Pencil of Courage X 100 - A pencil that's used to write things you don�t have the courage to say. +4032282 - Pencil of Courage X 1000 - AA pencil that's used to write things you don�t have the courage to say. +4032283 - Pencil of Courage X 10000 - A pencil that's used to write things you don�t have the courage to say. 4032284 - Child's Broken Toy - A toy stolen from a child by a monster. It's broken and cannot be used. 4032285 - Child's Broken Toy - A toy stolen from a child by a monster. It's broken and cannot be used. 4032286 - Child's Broken Toy - A toy stolen from a child by a monster. It's broken and cannot be used. diff --git a/handbook/Map.txt b/handbook/Map.txt index 97cff6d4e7..c7ace697e9 100644 --- a/handbook/Map.txt +++ b/handbook/Map.txt @@ -1565,9 +1565,9 @@ ossyria 200090057 - Empress' Road - To Ellinia 200090058 - Empress' Road - To Ereve 200090059 - Empress' Road - To Ellinia -200010303 - Hidden Street - Eliza’s Garden -211040102 - Hidden Street - Snow Soul’s Resting Place -209000100 - Happy Village - Cliff’s Hut +200010303 - Hidden Street - Eliza�s Garden +211040102 - Hidden Street - Snow Soul�s Resting Place +209000100 - Happy Village - Cliff�s Hut 219000000 - Hidden Street - Coke Town 219000001 - Hidden Street - Coke Town Sundry Goods Shop 219000002 - Hidden Street - House of Pouch @@ -2863,7 +2863,7 @@ etc 980027000 - Goldrich's Maze - Maze of Erosion 980027100 - Goldrich's Maze - Maze of Erosion 980027200 - Goldrich's Maze - Maze of Erosion -980027300 - Goldrich's Maze - Beginning of the Maze… +980027300 - Goldrich's Maze - Beginning of the Maze� 980027400 - Goldrich's Maze - Monster's Maze 980027500 - Goldrich's Maze - Monster's Maze 980027600 - Goldrich's Maze - Monster's Maze @@ -2944,7 +2944,7 @@ etc 980027001 - Goldrich's Maze - Maze of Erosion 980027101 - Goldrich's Maze - Maze of Erosion 980027201 - Goldrich's Maze - Maze of Erosion -980027301 - Goldrich's Maze - Beginning of the Maze… +980027301 - Goldrich's Maze - Beginning of the Maze� 980027401 - Goldrich's Maze - Monster's Maze 980027501 - Goldrich's Maze - Monster's Maze 980027601 - Goldrich's Maze - Monster's Maze @@ -3025,7 +3025,7 @@ etc 980027002 - Goldrich's Maze - Maze of Erosion 980027102 - Goldrich's Maze - Maze of Erosion 980027202 - Goldrich's Maze - Maze of Erosion -980027302 - Goldrich's Maze - Beginning of the Maze… +980027302 - Goldrich's Maze - Beginning of the Maze� 980027402 - Goldrich's Maze - Monster's Maze 980027502 - Goldrich's Maze - Monster's Maze 980027602 - Goldrich's Maze - Monster's Maze @@ -3349,7 +3349,7 @@ etc 913040007 - Opening - Cygnus Knights 913040008 - Opening - Cygnus Knights 913040009 - Opening - Cygnus Knights -920020000 - Hidden Street - Eliza’s Garden +920020000 - Hidden Street - Eliza�s Garden 922020300 - Hidden Street - Origin of the Clock Tower 922220000 - Hidden Street - Gloomy Forest 922230000 - Hidden Street - Lunar World diff --git a/handbook/Setup.txt b/handbook/Setup.txt index 7deebab82d..8a747bfb90 100644 --- a/handbook/Setup.txt +++ b/handbook/Setup.txt @@ -192,7 +192,7 @@ 3010058 - WorldEnd - You will recover 50 HP every 10 seconds. Perhaps, as you recline, you will find the answer to many of life's questions. 3010057 - BloodyRose - You will recover 50 HP every 10 seconds. You will experience the might of a conqueror after recovery. 3010060 - Noblesse Chair - A chair makes you feel like you're sitting in the lap of luxury. Also recovers 50 HP every 10 seconds. -3010061 - Underneath the Maple Tree… - A white chair created to celebrate Maple Story's 6th Anniversary. Sit on it to restore 35 HP and 10 MP every 10 seconds. +3010061 - Underneath the Maple Tree� - A white chair created to celebrate Maple Story's 6th Anniversary. Sit on it to restore 35 HP and 10 MP every 10 seconds. 3010062 - Bamboo Chair - A chair that restores HP every 10 seconds when used. It's very strong since it was made from bamboo grown on Rien. 3010063 - Moon and Star Cushion - A pretty cushion shaped like a moon. Recovers 60 HP every 10 seconds. 3010064 - Male Desert Rabbit Cushion - 60 HP is restored every 10 seconds if you lean back on this cute Male Desert Rabbit Cushion. diff --git a/src/main/java/client/command/commands/gm2/IdCommand.java b/src/main/java/client/command/commands/gm2/IdCommand.java index 75d08cdff2..c64466b68d 100644 --- a/src/main/java/client/command/commands/gm2/IdCommand.java +++ b/src/main/java/client/command/commands/gm2/IdCommand.java @@ -3,68 +3,121 @@ package client.command.commands.gm2; import client.Character; import client.Client; import client.command.Command; +import constants.game.NpcChat; import constants.id.NpcId; import server.ThreadManager; import tools.exceptions.IdTypeNotSupportedException; -import java.io.BufferedReader; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Predicate; +import java.util.stream.Collectors; public class IdCommand extends Command { { setDescription("Search in handbook."); } + private final static int MAX_SEARCH_HITS = 100; + private final Map handbookDirectory = typeFilePaths(); + private final Map typeItems = new ConcurrentHashMap<>(); - private final Map handbookDirectory = new HashMap<>(); - private final Map> itemMap = new HashMap<>(); + private Map typeFilePaths() { + return Map.ofEntries( + Map.entry("map", "handbook/Map.txt"), + Map.entry("etc", "handbook/Etc.txt"), + Map.entry("npc", "handbook/NPC.txt"), + Map.entry("use", "handbook/Use.txt"), + Map.entry("weapon", "handbook/Equip/Weapon.txt") // TODO add more into this + ); + } - public IdCommand() { - handbookDirectory.put("map", "handbook/Map.txt"); - handbookDirectory.put("etc", "handbook/Etc.txt"); - handbookDirectory.put("npc", "handbook/NPC.txt"); - handbookDirectory.put("use", "handbook/Use.txt"); - handbookDirectory.put("weapon", "handbook/Equip/Weapon.txt"); // TODO add more into this + private static class HandbookFileItems { + private final List items; + + public HandbookFileItems(List fileLines) { + this.items = fileLines.stream() + .map(this::parseLine) + .filter(Predicate.not(Objects::isNull)) + .toList(); + } + + private HandbookItem parseLine(String line) { + if (line == null) { + return null; + } + + String[] splitLine = line.split(" - ", 2); + if (splitLine.length < 2 || splitLine[1].isBlank()) { + return null; + } + return new HandbookItem(splitLine[0], splitLine[1]); + } + + public List search(String query) { + if (query == null || query.isBlank()) { + return Collections.emptyList(); + } + return items.stream() + .filter(item -> item.matches(query)) + .toList(); + } + } + + private record HandbookItem(String id, String name) { + + public HandbookItem { + Objects.requireNonNull(id); + Objects.requireNonNull(name); + } + + public boolean matches(String query) { + if (query == null) { + return false; + } + return this.name.toLowerCase().contains(query.toLowerCase()); + } } @Override public void execute(Client client, final String[] params) { - final Character player = client.getPlayer(); + final Character chr = client.getPlayer(); if (params.length < 2) { - player.yellowMessage("Syntax: !id "); + chr.yellowMessage("Syntax: !id "); return; } - final String queryItem = joinStringArr(Arrays.copyOfRange(params, 1, params.length), " "); - player.yellowMessage("Querying for entry... May take some time... Please try to refine your search."); + final String type = params[0].toLowerCase(); + final String[] queryItems = Arrays.copyOfRange(params, 1, params.length); + final String query = String.join(" ", queryItems); + chr.yellowMessage("Querying for entry... May take some time... Please try to refine your search."); Runnable queryRunnable = () -> { try { - populateIdMap(params[0].toLowerCase()); + populateIdMap(type); - Map resultList = fetchResults(itemMap.get(params[0]), queryItem); - StringBuilder sb = new StringBuilder(); + final HandbookFileItems handbookFileItems = typeItems.get(type); + if (handbookFileItems == null) { + return; + } + final List searchHits = handbookFileItems.search(query); - if (resultList.size() > 0) { - int count = 0; - for (Map.Entry entry : resultList.entrySet()) { - sb.append(String.format("Id for %s is: #b%s#k", entry.getKey(), entry.getValue()) + "\r\n"); - if (++count > 100) { - break; - } - } - sb.append(String.format("Results found: #r%d#k | Returned: #b%d#k/100 | Refine search query to improve time.", resultList.size(), count) + "\r\n"); - - player.getAbstractPlayerInteraction().npcTalk(NpcId.MAPLE_ADMINISTRATOR, sb.toString()); + if (!searchHits.isEmpty()) { + String searchHitsText = searchHits.stream() + .limit(MAX_SEARCH_HITS) + .map(item -> "Id for %s is: #b%s#k".formatted(item.name, item.id)) + .collect(Collectors.joining(NpcChat.NEW_LINE)); + int hitsCount = Math.min(searchHits.size(), MAX_SEARCH_HITS); + String summaryText = "Results found: #r%d#k | Returned: #b%d#k/100 | Refine search query to improve time.".formatted(searchHits.size(), hitsCount); + String fullText = searchHitsText + NpcChat.NEW_LINE + summaryText; + chr.getAbstractPlayerInteraction().npcTalk(NpcId.MAPLE_ADMINISTRATOR, fullText); } else { - player.yellowMessage(String.format("Id not found for item: %s, of type: %s.", queryItem, params[0])); + chr.yellowMessage(String.format("Id not found for item: %s, of type: %s.", query, type)); } } catch (IdTypeNotSupportedException e) { - player.yellowMessage("Your query type is not supported."); + chr.yellowMessage("Your query type is not supported."); } catch (IOException e) { - player.yellowMessage("Error reading file, please contact your administrator."); + chr.yellowMessage("Error reading file, please contact your administrator."); } }; @@ -72,40 +125,15 @@ public class IdCommand extends Command { } private void populateIdMap(String type) throws IdTypeNotSupportedException, IOException { - if (!handbookDirectory.containsKey(type)) { + final String filePath = handbookDirectory.get(type); + if (filePath == null) { throw new IdTypeNotSupportedException(); } - itemMap.put(type, new HashMap<>()); - try (BufferedReader reader = Files.newBufferedReader(Path.of(handbookDirectory.get(type)))) { - String line; - while ((line = reader.readLine()) != null) { - String[] row = line.split(" - ", 2); - if (row.length == 2) { - itemMap.get(type).put(row[1].toLowerCase(), row[0]); - } - } + if (typeItems.containsKey(type)) { + return; } - } - private String joinStringArr(String[] arr, String separator) { - if (null == arr || 0 == arr.length) { - return ""; - } - StringBuilder sb = new StringBuilder(256); - sb.append(arr[0]); - for (int i = 1; i < arr.length; i++) { - sb.append(separator).append(arr[i]); - } - return sb.toString(); - } - - private Map fetchResults(Map queryMap, String queryItem) { - Map results = new HashMap<>(); - for (String item : queryMap.keySet()) { - if (item.indexOf(queryItem) != -1) { - results.put(item, queryMap.get(item)); - } - } - return results; + final List fileLines = Files.readAllLines(Path.of(filePath)); + typeItems.put(type, new HandbookFileItems(fileLines)); } } diff --git a/src/main/java/constants/game/NpcChat.java b/src/main/java/constants/game/NpcChat.java new file mode 100644 index 0000000000..892dfc3532 --- /dev/null +++ b/src/main/java/constants/game/NpcChat.java @@ -0,0 +1,8 @@ +package constants.game; + +public final class NpcChat { + public static final String NEW_LINE = "\r\n"; + + private NpcChat() {} + +}