Saving enchants to config

Discussion in 'Plugin Development' started by xXLightbulbXx, Oct 29, 2015.

Thread Status:
Not open for further replies.
  1. Offline

    xXLightbulbXx

    Hey, so i'm trying to save enchantments to the config but i seem to be having a bit of a problem.
    Code:
    private void saveItem(ConfigurationSection section, ItemStack itemStack)
          {
            section.set("type", itemStack.getType().name());
            section.set("amount", Integer.valueOf(itemStack.getAmount()));
            section.set("enchants", itemStack.getEnchantments().toString());
          }
    I tried that code but it didn't save to the config properly. Is there any other way i can do this so my config might look like this.
    Config: (open)

    backpack:
    cf4aeas77-1bf5e9-37df1-8dda-93a94d31fb:
    b:
    type: DIAMOND_PICKAXE
    amount: 1
    enchants:
    - DAMAGE_ALL: 1
    - PROTECTION: 1
     
  2. Offline

    teej107

    1. You don't need to "Box" in the integer like that. Just save the int.

    2. You are saving the value that is returned by #toString() and it isn't what you expected I bet. You'll need to loop through the Map entries and save the key and value yourself.
     
  3. Offline

    xXLightbulbXx

    I am having a little trouble with this... can you help me?
     
  4. Offline

    Zombie_Striker

    As @teej107 pointed out
    This says you want to turn an integer into an integer. Don't do that.
    This is turning all the enchantment data into a string. This is bad. You can:
    1. Save the whole enchantment instance into the config (remove the .toString())
    2. Loop through all enchantments, save each individually under an integer value such as
      Code:
      "Enchantment."+i, enchantment[0]
      Which would give this in the config
    Code:
    Enchantment:
       1:Enchantmentdata12345 <-- I made this name up. It will not look like this.
       2:Ehcnantmentdata2 <--- I made this name up. It will not look like this 
     
  5. Offline

    xXLightbulbXx

    Ok, Thanks but this is where i got stuck.
    Code:
    for (Enchantment ench : Enchantment.values()) {
               
    }
     
  6. Offline

    Zombie_Striker

  7. Offline

    xXLightbulbXx

    I've got the for loop, But now how would i save each individually under an integer value?
    @Zombie_Striker
     
  8. Offline

    Zombie_Striker

    @xXLightbulbXx
    I = 0;
    for loop;
    i++
    Config.set("PATH."+I, enmchantment);
     
  9. Offline

    teej107

    Wat.... No. An int into an Integer. Your statement is confusing.
    Don't loop through each Enchament ever. Loop through the ones in your ItemStack. You need to loop through a Map's entrySet.
     
  10. Offline

    xXLightbulbXx

    Im really confused with this do you guys mind explaining a little more? or giving example code?
     
  11. Offline

    Zombie_Striker

    That never happens on this forum.

    Let me explain:
    We are referring to
    Which turns an INT to an INTEGER. I really don't see the purpose of doing that.
    Refers to
    Which is looping through ALL EXISTING Enchantments, not the ones on the itemstack.
    This was some "Mock code" that I wrote up. They get the idea through without actually posting code. You should be able to understand what to do.
     
  12. Offline

    Scimiguy

    @xXLightbulbXx
    1. Get your collection of enchantments.
    If it's from an item, use ItemStack#getEnchantments()
    2. Loop through that collection of enchantments, much like how you tried above.
    3. Get the name of the enchantment with getName()
    4. Store that string wherever you want.

    If you want to use ID's instead of names for some reason, use getId()
     
  13. Offline

    xXLightbulbXx

    @Scimiguy @Zombie_Striker
    This is what i did.
    Code:
    Map<Enchantment, Integer> enchants = itemStack.getEnchantments();
            List<String> enchantList = new ArrayList<String>();
            for (Enchantment e : itemStack.getEnchantments().keySet()) {
                int level = enchants.get(e);
                enchantList.add(e.getName().toLowerCase() + ":" + level);
            }
    Now how would i load the enchant from the config?
     
  14. Offline

    teej107

    No. My statement was not referring to that. I said to get the ItemStack's Enchantments.

    @xXLightbulbXx. Loop through the entrySet rather then the keySet. Then you wouldn't need to get the values yourself.
     
  15. Offline

    Scimiguy

    @xXLightbulbXx
    Getting from the config is done much the same way..
    Loop through your config keys, and create the enchantments with Enchantment#getByName()
     
  16. Offline

    xXLightbulbXx

    @teej107
    When i do that i get this
    Error: (open)
    Type mismatch: cannot convert from element type Map.Entry<Enchantment,Integer> to Enchantment

    Then when i fix it, it changes to
    Code:
    Map<Enchantment, Integer> enchants = itemStack.getEnchantments();
            List<String> enchantList = new ArrayList<String>();
            for (Entry<Enchantment, Integer> e : itemStack.getEnchantments().entrySet()) {
                int level = enchants.get(e);
                enchantList.add(e.getValue() + ":" + level);
            }
    
     
  17. Offline

    Scimiguy

    @xXLightbulbXx
    keySet() gives you the key. In this case that'd be the enchantment.
    entrySet() gives you each entry in the map. In this case that'd be the Enchantment + the Integer amplifier.

    You can get the level of your enchant with e.getValue();
    You can get the Enchantment itself with e.getKey()
     
  18. Offline

    xXLightbulbXx

    Ok thats good... Now how would i load the enchantment? from the config. @Scimiguy
     
  19. Offline

    Scimiguy

  20. Offline

    xXLightbulbXx

    This is my complete code now. Can you please revise it/review it? @Scimiguy
    Code:
    private void saveItem(ConfigurationSection section, ItemStack itemStack)
          {
            section.set("type", itemStack.getType().name());
            section.set("amount", Integer.valueOf(itemStack.getAmount()));
          
            Map<Enchantment, Integer> enchants = itemStack.getEnchantments();
            List<String> enchantList = new ArrayList<String>();
            for (Entry<Enchantment, Integer> e : itemStack.getEnchantments().entrySet()) {
                int level = enchants.get(e);
                enchantList.add(e.getKey() + ":" + level);
            }
          }
    
        private ItemStack loadItem(ConfigurationSection section)
          {
            
              ItemStack item = new ItemStack(Material.valueOf(section.getString("type")), section.getInt("amount"));
              ItemMeta itemmeta = item.getItemMeta();
              item.setItemMeta(itemmeta);
              itemmeta.getDisplayName();
              Enchantment.getByName(section.getString("enchants"));
            
            return item;
          }
     
  21. Offline

    Scimiguy

    @xXLightbulbXx
    Have you tried it out?

    It's far easier for you to just try it than for us to read through it

    The key thing to remember here is:
    We aren't writing your plugin. You are.
     
  22. Offline

    xXLightbulbXx

    Im trying to set the enchants to the config then load them.
    But its not doing that. @Scimiguy
     
    Last edited: Oct 30, 2015
  23. Offline

    Scimiguy

    @xXLightbulbXx
    What is it doing then?
    Any errors?

    Show your current code
     
  24. Offline

    xXLightbulbXx

    This is what i have for saving and loading
    Code:
    private void saveItem(ConfigurationSection section, ItemStack itemStack)
          {
            section.set("type", itemStack.getType().name());
            section.set("amount", Integer.valueOf(itemStack.getAmount()));
           
            Map<Enchantment, Integer> enchants = itemStack.getEnchantments();
            List<String> enchantList = section.getStringList("enchants");
            for (Entry<Enchantment, Integer> e : itemStack.getEnchantments().entrySet()) {
                int level = enchants.get(e);
                enchantList.add(e.getKey() + ":" + level);
            }
          }
    
        private ItemStack loadItem(ConfigurationSection section)
          {
             
              ItemStack item = new ItemStack(Material.valueOf(section.getString("type")), section.getInt("amount"));
              ItemMeta itemmeta = item.getItemMeta();
              item.setItemMeta(itemmeta);
              itemmeta.getDisplayName();
              itemmeta.getEnchants().get(section.getStringList("enchants"));
             
            return item;
          }
    The error i'm getting is
    Error: (open)

    [17:24:14 ERROR]: Could not pass event InventoryCloseEvent to Backpacks v1.0
    org.bukkit.event.EventException
    at org.bukkit.plugin.java.JavaPluginLoader$1.execute(JavaPluginLoader.ja
    va:310) ~[Spigot.jar:git-Spigot-d97e08b-880a532]
    at org.bukkit.plugin.RegisteredListener.callEvent(RegisteredListener.jav
    a:62) ~[Spigot.jar:git-Spigot-d97e08b-880a532]
    at org.bukkit.plugin.SimplePluginManager.fireEvent(SimplePluginManager.j
    ava:502) [Spigot.jar:git-Spigot-d97e08b-880a532]
    at org.bukkit.plugin.SimplePluginManager.callEvent(SimplePluginManager.j
    ava:487) [Spigot.jar:git-Spigot-d97e08b-880a532]
    at org.bukkit.craftbukkit.v1_8_R3.event.CraftEventFactory.handleInventor
    yCloseEvent(CraftEventFactory.java:851) [Spigot.jar:git-Spigot-d97e08b-880a532]
    at net.minecraft.server.v1_8_R3.PlayerConnection.a(PlayerConnection.java
    :1411) [Spigot.jar:git-Spigot-d97e08b-880a532]
    at net.minecraft.server.v1_8_R3.PacketPlayInCloseWindow.a(PacketPlayInCl
    oseWindow.java:18) [Spigot.jar:git-Spigot-d97e08b-880a532]
    at net.minecraft.server.v1_8_R3.PacketPlayInCloseWindow.a(PacketPlayInCl
    oseWindow.java:1) [Spigot.jar:git-Spigot-d97e08b-880a532]
    at net.minecraft.server.v1_8_R3.PlayerConnectionUtils$1.run(SourceFile:1
    3) [Spigot.jar:git-Spigot-d97e08b-880a532]
    at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source) [
    ?:1.8.0_40]
    at java.util.concurrent.FutureTask.run(Unknown Source) [?:1.8.0_40]
    at net.minecraft.server.v1_8_R3.SystemUtils.a(SourceFile:44) [Spigot.jar
    :git-Spigot-d97e08b-880a532]
    at net.minecraft.server.v1_8_R3.MinecraftServer.B(MinecraftServer.java:7
    14) [Spigot.jar:git-Spigot-d97e08b-880a532]
    at net.minecraft.server.v1_8_R3.DedicatedServer.B(DedicatedServer.java:3
    74) [Spigot.jar:git-Spigot-d97e08b-880a532]
    at net.minecraft.server.v1_8_R3.MinecraftServer.A(MinecraftServer.java:6
    53) [Spigot.jar:git-Spigot-d97e08b-880a532]
    at net.minecraft.server.v1_8_R3.MinecraftServer.run(MinecraftServer.java
    :556) [Spigot.jar:git-Spigot-d97e08b-880a532]
    at java.lang.Thread.run(Unknown Source) [?:1.8.0_40]
    Caused by: java.lang.NullPointerException
    at xXLightbulbXx.Backpacks.Backpacks.saveItem(Backpacks.java:180) ~[?:?]

    at xXLightbulbXx.Backpacks.Backpacks.onInventoryClose(Backpacks.java:128
    ) ~[?:?]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0
    _40]
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0
    _40]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[?:1
    .8.0_40]
    at java.lang.reflect.Method.invoke(Unknown Source) ~[?:1.8.0_40]
    at org.bukkit.plugin.java.JavaPluginLoader$1.execute(JavaPluginLoader.ja
    va:306) ~[Spigot.jar:git-Spigot-d97e08b-880a532]
    ... 16 more


    This is the onInventoryClose event.
    Code:
    @EventHandler
          public void onInventoryClose(InventoryCloseEvent e){
              if (!getConfig().contains("backpack." + e.getPlayer().getUniqueId())) {
                  getConfig().createSection("backpack." + e.getPlayer().getUniqueId());
                }
                char c = 'a';
                for (ListIterator<ItemStack> localListIterator = ((Inventory)this.backpack.get(e.getPlayer().getUniqueId())).iterator(); localListIterator.hasNext();)
                {
                  ItemStack itemStack = (ItemStack)localListIterator.next();
                  if (itemStack != null)
                  {
                    c = (char)(c + '\001');
                    saveItem(getConfig().createSection("backpack." + e.getPlayer().getUniqueId() + "." + c), itemStack);
                   
                  }
                }
              saveConfig();
          }
     
  25. Offline

    Scimiguy

    @xXLightbulbXx
    Post your entire class, not just cutouts.
    We can't match the error to the code without having all of the code in that class
     
  26. Offline

    xXLightbulbXx

    @Scimiguy
    Code:
    package xXLightbulbXx.Backpacks;
    
    import java.util.HashMap;
    import java.util.ListIterator;
    import java.util.Map;
    import java.util.UUID;
    
    import org.bukkit.Bukkit;
    import org.bukkit.ChatColor;
    import org.bukkit.Effect;
    import org.bukkit.Material;
    import org.bukkit.Sound;
    import org.bukkit.command.Command;
    import org.bukkit.command.CommandSender;
    import org.bukkit.configuration.ConfigurationSection;
    import org.bukkit.entity.Player;
    import org.bukkit.event.EventHandler;
    import org.bukkit.event.Listener;
    import org.bukkit.event.inventory.InventoryCloseEvent;
    import org.bukkit.event.inventory.InventoryType;
    import org.bukkit.event.player.PlayerJoinEvent;
    import org.bukkit.event.player.PlayerKickEvent;
    import org.bukkit.event.player.PlayerQuitEvent;
    import org.bukkit.inventory.Inventory;
    import org.bukkit.inventory.ItemStack;
    import org.bukkit.inventory.meta.ItemMeta;
    import org.bukkit.plugin.java.JavaPlugin;
    
    public class Backpacks extends JavaPlugin implements Listener{
    
        private HashMap<UUID, Inventory> backpack = new HashMap<UUID, Inventory>();
    
        String prefix = ChatColor.GRAY + "[" + ChatColor.AQUA + "Backpacks" + ChatColor.GRAY + "] ";
    
        public void onEnable(){
            Bukkit.getServer().getPluginManager().registerEvents(this, this);
        }
    
        @SuppressWarnings("rawtypes")
        public void onDisable(){
            for (Map.Entry entry : this.backpack.entrySet())
            {
              if (!getConfig().contains("backpack." + entry.getKey())) {
                getConfig().createSection("backpack." + entry.getKey());
              }
              char c = 'a';
              for (ListIterator localListIterator = ((Inventory)entry.getValue()).iterator(); localListIterator.hasNext();)
              {
                ItemStack itemStack = (ItemStack)localListIterator.next();
                if (itemStack != null)
                {
                  c = (char)(c + '\001');
                  saveItem(getConfig().createSection("backpack." + entry.getKey() + "." + c), itemStack);
                }
              }
              saveConfig();
            }
            saveConfig();
        }
      
          @EventHandler
          public void onPlayerJoin(PlayerJoinEvent e)
          {
              Player player = e.getPlayer();
          
            Inventory inv = Bukkit.getServer().createInventory(e.getPlayer(), InventoryType.CHEST, ChatColor.RED + ChatColor.BOLD.toString() + player.getName() + " Backpack");
            if (getConfig().contains("backpack." + e.getPlayer().getUniqueId())) {
              for (String item : getConfig().getConfigurationSection("backpack." + e.getPlayer().getUniqueId()).getKeys(false)) {
                inv.addItem(new ItemStack[] { loadItem(getConfig().getConfigurationSection("backpack." + e.getPlayer().getUniqueId() + "." + item)) });
              }
            }
            this.backpack.put(e.getPlayer().getUniqueId(), inv);
          }
      
          @EventHandler
          public void onPlayerLeave(PlayerQuitEvent e){
            if (!getConfig().contains("backpack." + e.getPlayer().getUniqueId())) {
              getConfig().createSection("backpack." + e.getPlayer().getUniqueId());
            }
            char c = 'a';
            for (ListIterator<ItemStack> localListIterator = ((Inventory)this.backpack.get(e.getPlayer().getUniqueId())).iterator(); localListIterator.hasNext();)
            {
              ItemStack itemStack = (ItemStack)localListIterator.next();
              if (itemStack != null)
              {
                c = (char)(c + '\001');
                saveItem(getConfig().createSection("backpack." + e.getPlayer().getUniqueId() + "." + c), itemStack);
              }
            }
            saveConfig();
          }
      
          @EventHandler
          public void onPlayerKick(PlayerKickEvent e){
              if (!getConfig().contains("backpack." + e.getPlayer().getUniqueId())) {
                  getConfig().createSection("backpack." + e.getPlayer().getUniqueId());
                }
                char c = 'a';
                for (ListIterator<ItemStack> localListIterator = ((Inventory)this.backpack.get(e.getPlayer().getUniqueId())).iterator(); localListIterator.hasNext();)
                {
                  ItemStack itemStack = (ItemStack)localListIterator.next();
                  if (itemStack != null)
                  {
                    c = (char)(c + '\001');
                    saveItem(getConfig().createSection("backpack." + e.getPlayer().getUniqueId() + "." + c), itemStack);
                
                  }
                }
                saveConfig();
          }
      
          @EventHandler
          public void onInventoryClose(InventoryCloseEvent e){
              if (!getConfig().contains("backpack." + e.getPlayer().getUniqueId())) {
                  getConfig().createSection("backpack." + e.getPlayer().getUniqueId());
                }
                char c = 'a';
                for (ListIterator<ItemStack> localListIterator = ((Inventory)this.backpack.get(e.getPlayer().getUniqueId())).iterator(); localListIterator.hasNext();)
                {
                  ItemStack itemStack = (ItemStack)localListIterator.next();
                  if (itemStack != null)
                  {
                    c = (char)(c + '\001');
                    saveItem(getConfig().createSection("backpack." + e.getPlayer().getUniqueId() + "." + c), itemStack);
                
                  }
                }
              saveConfig();
          }
      
          @SuppressWarnings("deprecation")
        public boolean onCommand(CommandSender sender, Command cmd, String commandLabel, String[] args)
          {
              Player player = (Player)sender;
          
            if (!(sender instanceof Player))
            {
              sender.sendMessage(ChatColor.RED + "Only players can run this command");
              return true;
            }
            if (commandLabel.equalsIgnoreCase("backpack") && args.length == 0){
              if (!player.hasPermission("backpack.allow"))
              {
                player.sendMessage(prefix + ChatColor.DARK_RED + "Error: " + ChatColor.RED + "You do not have permission for this command!");
              }
              else
              {
                player.getWorld().playSound(player.getLocation(), Sound.LEVEL_UP, 1.5F, 1.0F);
                player.openInventory((Inventory)this.backpack.get(player.getUniqueId()));
                player.playEffect(player.getLocation(), Effect.CLOUD, 1);
              }
            }else{
                if(player.hasPermission("backpack.staff")){
                    if(Bukkit.getPlayerExact(args[0]) != null){
                        player.getWorld().playSound(player.getLocation(), Sound.LEVEL_UP, 1.5F, 1.0F);
                        player.openInventory((Inventory)this.backpack.get(Bukkit.getPlayer(args[0]).getUniqueId()));
                        player.playEffect(player.getLocation(), Effect.CLOUD, 1);
                    }else{
                        player.sendMessage(prefix + ChatColor.GREEN + "That player is not online!");
                    }
                }else{
                    player.sendMessage(prefix + ChatColor.DARK_RED + "Error: " + ChatColor.RED + "You do not have permission for this command!");
                }
            }
            return true;
          }
      
          private void saveItem(ConfigurationSection section, ItemStack itemStack)
          {
            section.set("type", itemStack.getType().name());
            section.set("amount", Integer.valueOf(itemStack.getAmount()));
            section.set("durability", itemStack.getDurability());
            section.set("name", itemStack.getItemMeta().getDisplayName());
        
          }
    
        private ItemStack loadItem(ConfigurationSection section)
          {
          
              ItemStack item = new ItemStack(Material.valueOf(section.getString("type")), section.getInt("amount"));
              ItemMeta itemmeta = item.getItemMeta();
              item.setItemMeta(itemmeta);
              item.setDurability((short)(section.getInt("durability")));
              item.getItemMeta().setDisplayName(section.getString("name"));
          
            return item;
          }
    }
    EDIT: I switched part of the code to this
    Code:
    ArrayList<ItemStack> lootList = new ArrayList<ItemStack>();
          @SuppressWarnings("deprecation")
        public void saveItem(){
              for (int i = 0; i <= 64; i++) {
                  if (getConfig().getString("loot." + i) != null) {
                      int setItem = (getConfig().getInt("loot." + i + ".item"));
                      int setAmount = (getConfig().getInt("loot." + i + ".amount"));
                      int durability = (getConfig().getInt("loot." + i + ".durability"));
                      ItemStack stack = new ItemStack(setItem, setAmount);
                      stack.setDurability((short) durability);
                      for(int j = 0; j <= 10; j++) {
                          String enchantment = (getConfig().getString("loot." + i + ".enchantments." + j + ".enchantment"));
                          int level = (getConfig().getInt("loot." + i + ".enchantments." + j + ".level"));
                          stack.addUnsafeEnchantment(Enchantment.getByName(enchantment), level);
                      }
                      lootList.add(stack);
                  }
              }
          }
    And now i get an error
    Error: (open)

    [21:41:47 ERROR]: null
    org.bukkit.command.CommandException: Unhandled exception executing command 'back
    pack' in plugin Backpacks v1.0
    at org.bukkit.command.PluginCommand.execute(PluginCommand.java:46) ~[Spi
    got.jar:git-Spigot-d97e08b-880a532]
    at org.bukkit.command.SimpleCommandMap.dispatch(SimpleCommandMap.java:14
    1) ~[Spigot.jar:git-Spigot-d97e08b-880a532]
    at org.bukkit.craftbukkit.v1_8_R3.CraftServer.dispatchCommand(CraftServe
    r.java:641) ~[Spigot.jar:git-Spigot-d97e08b-880a532]
    at net.minecraft.server.v1_8_R3.PlayerConnection.handleCommand(PlayerCon
    nection.java:1162) [Spigot.jar:git-Spigot-d97e08b-880a532]
    at net.minecraft.server.v1_8_R3.PlayerConnection.a(PlayerConnection.java
    :997) [Spigot.jar:git-Spigot-d97e08b-880a532]
    at net.minecraft.server.v1_8_R3.PacketPlayInChat.a(PacketPlayInChat.java
    :45) [Spigot.jar:git-Spigot-d97e08b-880a532]
    at net.minecraft.server.v1_8_R3.PacketPlayInChat.a(PacketPlayInChat.java
    :1) [Spigot.jar:git-Spigot-d97e08b-880a532]
    at net.minecraft.server.v1_8_R3.PlayerConnectionUtils$1.run(SourceFile:1
    3) [Spigot.jar:git-Spigot-d97e08b-880a532]
    at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source) [
    ?:1.8.0_40]
    at java.util.concurrent.FutureTask.run(Unknown Source) [?:1.8.0_40]
    at net.minecraft.server.v1_8_R3.SystemUtils.a(SourceFile:44) [Spigot.jar
    :git-Spigot-d97e08b-880a532]
    at net.minecraft.server.v1_8_R3.MinecraftServer.B(MinecraftServer.java:7
    14) [Spigot.jar:git-Spigot-d97e08b-880a532]
    at net.minecraft.server.v1_8_R3.DedicatedServer.B(DedicatedServer.java:3
    74) [Spigot.jar:git-Spigot-d97e08b-880a532]
    at net.minecraft.server.v1_8_R3.MinecraftServer.A(MinecraftServer.java:6
    53) [Spigot.jar:git-Spigot-d97e08b-880a532]
    at net.minecraft.server.v1_8_R3.MinecraftServer.run(MinecraftServer.java
    :556) [Spigot.jar:git-Spigot-d97e08b-880a532]
    at java.lang.Thread.run(Unknown Source) [?:1.8.0_40]
    Caused by: java.lang.NullPointerException
    at org.bukkit.craftbukkit.v1_8_R3.entity.CraftHumanEntity.openInventory(
    CraftHumanEntity.java:176) ~[Spigot.jar:git-Spigot-d97e08b-880a532]
    at xXLightbulbXx.Backpacks.Backpacks.onCommand(Backpacks.java:151) ~[?:?
    ]
    at org.bukkit.command.PluginCommand.execute(PluginCommand.java:44) ~[Spi
    got.jar:git-Spigot-d97e08b-880a532]
    ... 15 more
     
    Last edited: Oct 30, 2015
  27. Offline

    teej107

Thread Status:
Not open for further replies.

Share This Page