From c58d2266808988cb4aaa059c83f980183b99d29f Mon Sep 17 00:00:00 2001 From: AlexTheCoder Date: Mon, 18 Jul 2016 16:26:05 -0400 Subject: [PATCH] More work on Nether and Runes --- .../game/clans/clans/ClansManager.java | 2 +- .../clans/clans/nether/NetherManager.java | 57 +++++++++++++--- .../game/clans/clans/nether/NetherPortal.java | 56 +++++++++++----- .../clans/nether/command/CloseCommand.java | 24 +++++++ .../clans/nether/command/DeleteCommand.java | 2 +- .../clans/nether/command/PortalCommand.java | 4 +- .../mineplex/game/clans/items/CustomItem.java | 14 ++++ .../game/clans/items/GearManager.java | 2 +- .../clans/items/commands/RuneCommand.java | 8 ++- .../game/clans/items/runes/RuneManager.java | 66 +++++++++++++++---- 10 files changed, 192 insertions(+), 43 deletions(-) create mode 100644 Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/nether/command/CloseCommand.java diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/ClansManager.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/ClansManager.java index 08157bd5d..8f53fec8d 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/ClansManager.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/ClansManager.java @@ -422,7 +422,7 @@ public class ClansManager extends MiniClientPluginimplements IRelati _siegeManager = new SiegeManager(this); -// _netherManager = new NetherManager(this); + _netherManager = new NetherManager(this); } @Override diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/nether/NetherManager.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/nether/NetherManager.java index 260a94132..52a8b9356 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/nether/NetherManager.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/nether/NetherManager.java @@ -37,6 +37,7 @@ import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.World; import org.bukkit.WorldBorder; +import org.bukkit.WorldCreator; import org.bukkit.block.Block; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.file.YamlConfiguration; @@ -58,7 +59,7 @@ import com.google.common.collect.Lists; public class NetherManager extends MiniPlugin { - private static final long PORTAL_OPEN_DURATION = UtilTime.convert(30, TimeUnit.MINUTES, TimeUnit.SECONDS) * 20; + private static final long PORTAL_OPEN_DURATION = UtilTime.convert(30, TimeUnit.MINUTES, TimeUnit.MILLISECONDS); private static final long NETHER_SLOW_WARMUP = UtilTime.convert(17, TimeUnit.MINUTES, TimeUnit.MILLISECONDS); private static final long NETHER_BLIND_WARMUP = UtilTime.convert(18, TimeUnit.MINUTES, TimeUnit.MILLISECONDS); private static final long NETHER_ALLOWED_DURATION = UtilTime.convert(20, TimeUnit.MINUTES, TimeUnit.MILLISECONDS); @@ -97,7 +98,11 @@ public class NetherManager extends MiniPlugin private void begin() { - _netherWorld = Bukkit.getWorld("world_nether"); + if (Bukkit.getWorld("nether") == null) + { + Bukkit.createWorld(new WorldCreator("nether")); + } + _netherWorld = Bukkit.getWorld("nether"); WorldBorder worldBorder = _netherWorld.getWorldBorder(); worldBorder.setCenter(0, 0); @@ -138,6 +143,25 @@ public class NetherManager extends MiniPlugin } } + @Override + public void disable() + { + closePortals(); + try + { + savePortals(); + } + catch (IOException e) + { + e.printStackTrace(); + } + for (Player player : InNether.keySet()) + { + player.teleport(Spawn.getNorthSpawn()); + } + InNether.clear(); + } + public void savePortals() throws IOException { _portalConfig.set("PortalCount", Portals.size()); @@ -146,8 +170,8 @@ public class NetherManager extends MiniPlugin for (int i = 0; i < Portals.size(); i++) { int id = i + 1; - _portalConfig.set("Portals." + id + ".CornerOne", Portals.get(0).getCorners()[0]); - _portalConfig.set("Portals." + id + ".CornerTwo", Portals.get(0).getCorners()[1]); + _portalConfig.set("Portals." + id + ".CornerOne", UtilWorld.locToStr(Portals.get(i).getCorners()[0])); + _portalConfig.set("Portals." + id + ".CornerTwo", UtilWorld.locToStr(Portals.get(i).getCorners()[1])); } _portalConfig.save(_portalCfg); @@ -206,7 +230,7 @@ public class NetherManager extends MiniPlugin @EventHandler(priority = EventPriority.HIGHEST) public void onPortal(PlayerPortalEvent event) { - if (event.getTo().getWorld().equals(_netherWorld)) + if (event.getTo() == null || event.getTo().getWorld().equals(_netherWorld)) { return; } @@ -344,6 +368,7 @@ public class NetherManager extends MiniPlugin data.setFirstCorner(block); UtilPlayer.message(event.getPlayer(), F.main(getName(), "You have selected the Portal's first corner!")); } + event.setCancelled(true); } } @@ -352,8 +377,7 @@ public class NetherManager extends MiniPlugin { if (event.getCreature() instanceof GolemCreature || event.getCreature() instanceof SkeletonCreature || event.getCreature() instanceof SpiderCreature) { - //spawnPortal(); - Bukkit.broadcastMessage("A PORTAL SPAWN WOULD BE CALLED HERE IF IT WASN'T DISABLED"); + spawnPortal(); } } @@ -367,7 +391,7 @@ public class NetherManager extends MiniPlugin return player.getWorld().equals(_netherWorld); } - public void spawnPortal() + public void spawnPortal(long duration) { if (Portals.isEmpty()) { @@ -376,11 +400,16 @@ public class NetherManager extends MiniPlugin NetherPortal portal = Portals.get(UtilMath.r(Portals.size())); portal.open(); UtilTextMiddle.display(F.clansNether("Nether Portal"), "Has opened at " + F.elem(UtilWorld.locToStrClean(portal.getLocation()))); - Bukkit.broadcastMessage(F.main(getName(), "A " + F.clansNether("Nether Portal") + " has opened at " + F.elem(UtilWorld.locToStrClean(portal.getLocation())))); + Bukkit.broadcastMessage(F.main(getName(), "A " + F.clansNether("Nether Portal") + " has opened at " + F.elem(UtilWorld.locToStrClean(portal.getLocation())) + " for " + F.elem(UtilTime.MakeStr(duration)) + "!")); runSyncLater(() -> { portal.close(); - }, PORTAL_OPEN_DURATION); + }, (duration / 1000) * 20); + } + + public void spawnPortal() + { + spawnPortal(PORTAL_OPEN_DURATION); } public void createPortal(Player creator) @@ -406,6 +435,14 @@ public class NetherManager extends MiniPlugin } } + public void closePortals() + { + for (NetherPortal portal : Portals) + { + portal.close(); + } + } + public void showPortalList(Player player) { UtilPlayer.message(player, F.main(getName(), "Portal List:")); diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/nether/NetherPortal.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/nether/NetherPortal.java index 2c485ba79..d6d9b0aa5 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/nether/NetherPortal.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/nether/NetherPortal.java @@ -6,6 +6,7 @@ import mineplex.core.common.util.F; import mineplex.core.common.util.UtilPlayer; import mineplex.game.clans.clans.ClanTips.TipType; import mineplex.game.clans.clans.ClansManager; +import mineplex.game.clans.spawn.Spawn; import org.bukkit.Bukkit; import org.bukkit.Location; @@ -17,6 +18,7 @@ import org.bukkit.event.EventPriority; import org.bukkit.event.HandlerList; import org.bukkit.event.Listener; import org.bukkit.event.block.BlockBreakEvent; +import org.bukkit.event.block.BlockPhysicsEvent; import org.bukkit.event.entity.EntityPortalEnterEvent; import org.bukkit.event.entity.EntityPortalEvent; import org.bukkit.event.player.PlayerPortalEvent; @@ -25,19 +27,21 @@ import com.google.common.collect.Lists; public class NetherPortal implements Listener { + private static final int SECONDS_UNTIL_PORTAL = 5; private List _frame = Lists.newArrayList(); private List _portal = Lists.newArrayList(); private Location _loc; private Location[] _corners; + private boolean _returnPortal; - public NetherPortal(Location firstCorner, Location secondCorner) + public NetherPortal(Location firstCorner, Location secondCorner, boolean returnPortal) { int maxX = Math.max(firstCorner.getBlockX(), secondCorner.getBlockX()); int minX = Math.min(firstCorner.getBlockX(), secondCorner.getBlockX()); - int maxY = Math.max(firstCorner.getBlockX(), secondCorner.getBlockX()); - int minY = Math.min(firstCorner.getBlockX(), secondCorner.getBlockX()); - int maxZ = Math.max(firstCorner.getBlockX(), secondCorner.getBlockX()); - int minZ = Math.min(firstCorner.getBlockX(), secondCorner.getBlockX()); + int maxY = Math.max(firstCorner.getBlockY(), secondCorner.getBlockY()); + int minY = Math.min(firstCorner.getBlockY(), secondCorner.getBlockY()); + int maxZ = Math.max(firstCorner.getBlockZ(), secondCorner.getBlockZ()); + int minZ = Math.min(firstCorner.getBlockZ(), secondCorner.getBlockZ()); for (int x = minX; x <= maxX; x++) { @@ -73,6 +77,7 @@ public class NetherPortal implements Listener _loc = new Location(firstCorner.getWorld(), minX + ((maxX - minX) / 2), maxY, minZ + ((maxZ - minZ) / 2)); _corners = new Location[] {firstCorner, secondCorner}; + _returnPortal = returnPortal; } private boolean isInPortal(Block block) @@ -90,8 +95,14 @@ public class NetherPortal implements Listener return _corners; } + public boolean isReturnPortal() + { + return _returnPortal; + } + public void open() { + Bukkit.getPluginManager().registerEvents(this, ClansManager.getInstance().getPlugin()); for (Block block : _frame) { block.setType(Material.OBSIDIAN); @@ -99,24 +110,20 @@ public class NetherPortal implements Listener for (Block block : _portal) { block.setType(Material.PORTAL); + Bukkit.broadcastMessage("Creating Portal Piece"); } - Bukkit.getPluginManager().registerEvents(this, ClansManager.getInstance().getPlugin()); } public void close() { HandlerList.unregisterAll(this); - for (Block block : _frame) - { - block.setType(Material.AIR); - } for (Block block : _portal) { block.setType(Material.AIR); } } - @EventHandler + @EventHandler(priority = EventPriority.HIGHEST) public void onBreak(BlockBreakEvent event) { if (isInPortal(event.getBlock())) @@ -155,12 +162,31 @@ public class NetherPortal implements Listener { if (isInPortal(event.getEntity().getLocation().getBlock())) { - ClansManager.getInstance().getNetherManager().InNether.put((Player)event.getEntity(), System.currentTimeMillis()); - event.getEntity().teleport(event.getLocation()); //MAKE NETHER SPAWN - ClansManager.getInstance().ClanTips.displayTip(TipType.ENTER_NETHER, (Player)event.getEntity()); + if (isReturnPortal()) + { + ClansManager.getInstance().getNetherManager().InNether.remove((Player)event.getEntity()); + ClansManager.getInstance().getCondition().Clean((Player)event.getEntity()); + event.getEntity().teleport(Spawn.getNorthSpawn()); + UtilPlayer.message(event.getEntity(), F.main(ClansManager.getInstance().getNetherManager().getName(), "You have escaped " + F.clansNether("The Nether") + "!")); + } + else + { + ClansManager.getInstance().getNetherManager().InNether.put((Player)event.getEntity(), System.currentTimeMillis()); + event.getEntity().teleport(ClansManager.getInstance().getNetherManager().getNetherWorld().getSpawnLocation()); + ClansManager.getInstance().ClanTips.displayTip(TipType.ENTER_NETHER, (Player)event.getEntity()); + } } - }, 5 * 20); + }, SECONDS_UNTIL_PORTAL * 20); } } } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onBlockPhysics(BlockPhysicsEvent event) + { + if (isInPortal(event.getBlock())) + { + event.setCancelled(true); + } + } } \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/nether/command/CloseCommand.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/nether/command/CloseCommand.java new file mode 100644 index 000000000..cfc778e90 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/nether/command/CloseCommand.java @@ -0,0 +1,24 @@ +package mineplex.game.clans.clans.nether.command; + +import org.bukkit.entity.Player; + +import mineplex.core.command.CommandBase; +import mineplex.core.common.Rank; +import mineplex.core.common.util.F; +import mineplex.core.common.util.UtilPlayer; +import mineplex.game.clans.clans.nether.NetherManager; + +public class CloseCommand extends CommandBase +{ + public CloseCommand(NetherManager plugin) + { + super(plugin, Rank.ADMIN, "close"); + } + + @Override + public void Execute(Player caller, String[] args) + { + UtilPlayer.message(caller, F.main(Plugin.getName(), "Closing all " + F.clansNether("Nether Portals" + "!"))); + Plugin.closePortals(); + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/nether/command/DeleteCommand.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/nether/command/DeleteCommand.java index 1a8b70d81..ed5f70ac0 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/nether/command/DeleteCommand.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/nether/command/DeleteCommand.java @@ -24,7 +24,7 @@ public class DeleteCommand extends CommandBase id = Integer.parseInt(args[0]); } catch (Exception e) {} - if (id == null || id >= Plugin.Portals.size() || id < 1) + if (id == null || id > Plugin.Portals.size() || id < 1) { UtilPlayer.message(caller, F.main(Plugin.getName(), "Usage: " + F.elem("/portal " + _aliasUsed + " "))); return; diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/nether/command/PortalCommand.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/nether/command/PortalCommand.java index e146a980d..b0c0f1551 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/nether/command/PortalCommand.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/nether/command/PortalCommand.java @@ -17,6 +17,7 @@ public class PortalCommand extends MultiCommandBase AddCommand(new DeleteCommand(plugin)); AddCommand(new ListCommand(plugin)); AddCommand(new SpawnCommand(plugin)); + AddCommand(new CloseCommand(plugin)); AddCommand(new WandCommand(plugin)); } @@ -24,7 +25,8 @@ public class PortalCommand extends MultiCommandBase protected void Help(Player caller, String[] args) { UtilPlayer.message(caller, F.help("/" + _aliasUsed + " spawn", "Forces a Nether Portal to spawn", Rank.ADMIN)); - UtilPlayer.message(caller, F.help("/" + _aliasUsed + " lists", "Lists all loaded Nether Portals", Rank.ADMIN)); + UtilPlayer.message(caller, F.help("/" + _aliasUsed + " close", "Closes all Nether Portals", Rank.ADMIN)); + UtilPlayer.message(caller, F.help("/" + _aliasUsed + " list", "Lists all loaded Nether Portals", Rank.ADMIN)); UtilPlayer.message(caller, F.help("/" + _aliasUsed + " wand", "Gives you a Nether Portal claim wand", Rank.ADMIN)); UtilPlayer.message(caller, F.help("/" + _aliasUsed + " create", "Creates a Nether Portal with the corners you have selected", Rank.ADMIN)); UtilPlayer.message(caller, F.help("/" + _aliasUsed + " delete", "Deletes a loaded Nether Portal", Rank.ADMIN)); diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/items/CustomItem.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/items/CustomItem.java index 02a71b2c4..667bbdee1 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/items/CustomItem.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/items/CustomItem.java @@ -186,6 +186,11 @@ public class CustomItem implements Listener meta.setLore(lore); item.setItemMeta(meta); + + if (_dullEnchantment) + { + UtilInv.addDullEnchantment(item); + } GearManager.writeNBT(this, item); } @@ -213,4 +218,13 @@ public class CustomItem implements Listener { return _attributes; } + + public void setMaterial(Material material) + { + if (_material == null) + { + _displayName = prettifyName(material); + } + _material = material; + } } diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/items/GearManager.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/items/GearManager.java index d3110e2e4..27b8900b0 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/items/GearManager.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/items/GearManager.java @@ -227,7 +227,7 @@ public class GearManager extends MiniPlugin implements IPacketHandler, Runnable _instance = this; _shop = new GearShop(this, clientManager, donationManager); - _rune = new RuneManager("Rune"); + _rune = new RuneManager("Rune", plugin); // Register listeners UtilServer.getServer().getPluginManager().registerEvents(new ItemListener(getPlugin()), getPlugin()); diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/items/commands/RuneCommand.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/items/commands/RuneCommand.java index f51bf58af..6ae4cc5ed 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/items/commands/RuneCommand.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/items/commands/RuneCommand.java @@ -19,12 +19,16 @@ public class RuneCommand extends CommandBase public RuneCommand(GearManager plugin) { super(plugin, Rank.ADMIN, "rune", "giverune", "getrune"); - _rune = Plugin.getRuneManager(); } @Override public void Execute(Player caller, String[] args) { + if (_rune == null) + { + _rune = Plugin.getRuneManager(); + } + if (args.length < 1) { UtilPlayer.message(caller, F.main("Rune", "Usage: /" + _aliasUsed + " ")); @@ -35,7 +39,7 @@ public class RuneCommand extends CommandBase } return; } - RuneAttribute rune = RuneAttribute.valueOf(args[0].toUpperCase()); + RuneAttribute rune = RuneAttribute.getFromString(args[0]); if (rune == null) { UtilPlayer.message(caller, F.main(Plugin.getName(), "Invalid rune type! Available types:")); diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/items/runes/RuneManager.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/items/runes/RuneManager.java index be46a6b5d..d4c349ded 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/items/runes/RuneManager.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/items/runes/RuneManager.java @@ -28,6 +28,7 @@ import mineplex.game.clans.items.attributes.weapon.HasteAttribute; import mineplex.game.clans.items.attributes.weapon.JaggedAttribute; import mineplex.game.clans.items.attributes.weapon.SharpAttribute; +import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.Sound; import org.bukkit.entity.Player; @@ -40,15 +41,17 @@ import org.bukkit.event.inventory.InventoryType; import org.bukkit.event.inventory.PrepareItemCraftEvent; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.plugin.java.JavaPlugin; public class RuneManager implements Listener { private static final String RUNE_NAME = C.cGold + "Ancient Rune"; private String _managerName; - public RuneManager(String name) + public RuneManager(String name, JavaPlugin plugin) { _managerName = name; + Bukkit.getPluginManager().registerEvents(this, plugin); } public boolean isRune(ItemStack item) @@ -88,7 +91,7 @@ public class RuneManager implements Listener { if (!rune.canApplyTo(to.getType())) { - return to; + return null; } if (GearManager.isCustomItem(to)) { @@ -96,13 +99,20 @@ public class RuneManager implements Listener { ItemAttribute attribute = rune.getAttributeClass().newInstance(); CustomItem item = GearManager.parseItem(to); + if (!item.getAttributes().getRemainingTypes().contains(attribute.getType())) + { + return null; + } item.getAttributes().addAttribute(attribute); - return item.toItemStack(); + ItemStack stack = to.clone(); + item.setMaterial(stack.getType()); + item.update(stack); + return stack; } catch (Exception e) { e.printStackTrace(); - return to; + return null; } } else @@ -113,12 +123,14 @@ public class RuneManager implements Listener item.addDullEnchantment(); ItemAttribute attribute = rune.getAttributeClass().newInstance(); item.getAttributes().addAttribute(attribute); - return item.toItemStack(); + ItemStack stack = to.clone(); + item.update(stack); + return stack; } catch (Exception e) { e.printStackTrace(); - return to; + return null; } } } @@ -195,15 +207,25 @@ public class RuneManager implements Listener } RuneAttribute rune = decodeRune(event.getCursor()); - if (!rune.canApplyTo(event.getCurrentItem().getType())) + if (rune == null) { - UtilPlayer.message(player, F.main(_managerName, "That rune seems to reject that type of item!")); return; } + if (!rune.canApplyTo(event.getCurrentItem().getType())) + { + UtilPlayer.message(player, F.main(_managerName, "The rune seems to reject that type of item!")); + return; + } + ItemStack after = applyToItem(rune, event.getCurrentItem()); + if (after == null) + { + UtilPlayer.message(player, F.main(_managerName, "The rune seems to reject that item!")); + return; + } + event.setCancelled(true); event.setCursor(new ItemStack(Material.AIR)); - ItemStack after = applyToItem(rune, event.getCurrentItem()); - event.getInventory().setItem(event.getSlot(), after); + event.getClickedInventory().setItem(event.getSlot(), after); player.playSound(player.getLocation(), Sound.ANVIL_USE, 1.5f, 5f); player.updateInventory(); @@ -269,9 +291,16 @@ public class RuneManager implements Listener public boolean canApplyTo(Material type) { - if (_weapon && (UtilItem.isSword(type) || UtilItem.isAxe(type))) + if (_weapon) { - return true; + if (UtilItem.isSword(type) || UtilItem.isAxe(type)) + { + return true; + } + if (type == Material.RECORD_4 || type == Material.GOLD_RECORD || type == Material.RECORD_3 || type == Material.RECORD_5 || type == Material.GREEN_RECORD) + { + return true; + } } if (_armor && UtilItem.isArmor(type)) { @@ -297,5 +326,18 @@ public class RuneManager implements Listener return null; } + + public static RuneAttribute getFromString(String string) + { + for (RuneAttribute rune : RuneAttribute.values()) + { + if (rune.toString().equalsIgnoreCase(string)) + { + return rune; + } + } + + return null; + } } } \ No newline at end of file