Dismiss Notice
Wynncraft, the Minecraft MMORPG. Play it now on your Minecraft client at (IP): play.wynncraft.com. No mods required! Click here for more info...
Dismiss Notice
Have some great ideas for Wynncraft? Join the official CT (content team) and help us make quests, builds, cinematics and much more!

World Ocean Currents! Code Included!(+ 60 Supporters)

Discussion in 'General Suggestions' started by Arreme, Feb 19, 2016.

?

Would you like to see this in-game?

  1. Yes. +1 Supporter

    87.5%
  2. No. +0 Supporters

    12.5%
Thread Status:
Not open for further replies.
  1. Ironraptor3

    Ironraptor3 Dragon Slayer, Sabre, CS/Game Dev VIP

    Messages:
    1,103
    Likes Received:
    605
    Trophy Points:
    117
    Guild:
    Minecraft:
    Havent been home
     
  2. Lemniscate

    Lemniscate ☞ ͠° ‿‿ ° ☞ HERO

    Messages:
    510
    Likes Received:
    95
    Trophy Points:
    58
    Guild:
    Minecraft:
    It sounds cool and all, but honestly I'd rather the devs work on fixing current content and building on it rather than adding things like this.
     
  3. Ironraptor3

    Ironraptor3 Dragon Slayer, Sabre, CS/Game Dev VIP

    Messages:
    1,103
    Likes Received:
    605
    Trophy Points:
    117
    Guild:
    Minecraft:
    Whale then, I finally got to making that xD
    As the continuous notes in the code say, any part of it can be changed to be made better, I simply threw it together to show that it was easy to do, and could be efficient.
    It was tested and it works fine.

    Code:
    public class Main extends JavaPlugin implements Listener {
        //And obviously, anyone with an interest in making plugins can always talk to me if you want help
        public static Plugin plugin;
        World w = null;
        public static final double speed = .3; //again, changeable, or able to be stored in another class and altered
        //Testing speed at 1 was pretty violent when opposing the current
      
        //Add a config file to save current info in between sessions, too lazy to do that for just an example
      
        @Override
        public void onEnable() {
            plugin = this;
            Bukkit.getServer().getPluginManager().registerEvents(this, this);
            currentLoop();
        }
        @Override
        public void onDisable() {
            plugin = null;
        }
      
        public static ConcurrentHashMap<Boat, Long> removing = new ConcurrentHashMap<Boat, Long>();
        public static ConcurrentHashMap<Location, Vector> currents = new ConcurrentHashMap<Location, Vector>();
      
        public void currentLoop() {
            new BukkitRunnable() {
                @Override
                public void run() {
                    if (w == null) return;
                    for (Entity e : w.getEntities()) {
                        if (e instanceof Boat) {
                            Boat b = (Boat) e;
                            if (removing.containsKey(b)) {
                                if (b.getPassenger() != null && b.getPassenger() instanceof Player) removing.remove(b);
                                else if (System.currentTimeMillis() - removing.get(b) >= 10*1000) {
                                    removing.remove(b);//boats despawn within 10 seconds of being placed
                                    b.remove();
                                }
                            }
                            else {
                                if (b.getPassenger() == null || !(b.getPassenger() instanceof Player)) {
                                    removing.put(b, System.currentTimeMillis());
                                    continue;
                                }
                                /* You can make a separate stream class, adding equations for their shape,
                                 * dimensions, bounds, etc.  Its simpy an example, however, and if I
                                 * were to mess up, I would not wish to debug that~*/
                                for (Location location : currents.keySet()) {
                                    if (b.getLocation().distanceSquared(location) <= 100) {
                                        b.setVelocity(b.getVelocity().add( currents.get(location).normalize().multiply(speed) ));
                                        break;
                                    //Ew lots of braces
                                    }
                                }
                            }
                        }
                    }
                }
            }.runTaskTimer(plugin, 0, 5);
        }
      
        @EventHandler
        public void onClick(PlayerInteractEvent e) {
            //Just to make it easy, obviously permissions and everything, blah blah blah blah blahyou've read this several times
            //You know its up to you how to make it, its just an example
            if (e.getPlayer().isOp() && e.getPlayer().getInventory().getItemInHand().getType().equals(Material.EYE_OF_ENDER)) {
                Location l = e.getPlayer().getLocation();
                while (l.getBlock().getType() == null) l = l.subtract(0, 1, 0);
                currents.put(l, e.getPlayer().getEyeLocation().getDirection().setY(0));
                e.getPlayer().sendMessage(ChatColor.GREEN + "New current set!"); //debug message
            }
            else if (w == null && e.getPlayer().getInventory().getItemInHand().getType().equals(Material.BOAT)) w = e.getPlayer().getWorld();
        }
    }
    //Wow less than even 100 lines, what a miracle (mwahah take that people who said it couldnt be done effeciently or easily)
    //Written by Ironraptor3
    
    ________________________________
    Doesn't need directional testing, vectors that push the player can be saved to a current class. Though it would contain a few points, code could be written in such a way as to test general --> specific (using equations that follow the current's path, setting rectangular/circular bounds, etc) when it comes to whether a player is in a certain current. And because only players in boats would be tested, and the tests would only run every say, 1/4 of a second, it wouldn't be terrible unless an entire server was in boats (Never seen that one before)
     
    Last edited: Feb 23, 2016
  4. Loggerhead

    Loggerhead Some Loggerhead

    Messages:
    1,453
    Likes Received:
    874
    Trophy Points:
    117
    Guild:
    Minecraft:
    The missing island is bear zoo, and add a hot current leading to jofash... that way, I'll change my vote to a yes!
     
  5. Bebinson

    Bebinson Well-Known Adventurer

    Messages:
    240
    Likes Received:
    206
    Trophy Points:
    67
    Minecraft:
    If it's not too hard to implement I would love to see it!
    Boats are so boring so I prefer using escape spell because I love visiting new areas
    Funny fact: cold currents are one of the reason why Africa's coasts are hot.
     
  6. IggyBoii

    IggyBoii I Have No Idea What Im Doing VIP

    Messages:
    2,129
    Likes Received:
    692
    Trophy Points:
    73
    Guild:
    Minecraft:
    The code was clearly finished, not really hard to add now...
     
    Bebinson likes this.
  7. Ironraptor3

    Ironraptor3 Dragon Slayer, Sabre, CS/Game Dev VIP

    Messages:
    1,103
    Likes Received:
    605
    Trophy Points:
    117
    Guild:
    Minecraft:
    Well it's just an example, it could be really detailed! :P. I spent 20 mins on it, if i really wanted to make a version that i personally would release, it would take at least 20 times longer
     
    Arreme and Bebinson like this.
  8. Arreme

    Arreme Veteran, Learning Game Design VIP+

    Messages:
    378
    Likes Received:
    328
    Trophy Points:
    85
    Minecraft:
    Oh, mai freaking god... Awesome!! Really, I wish I could do that. Programing is just amazing ^^, Thanks a lot, I'm going to add it on the main post, okay? :D
     
    Last edited: Feb 24, 2016
    Ironraptor3 likes this.
  9. daniel3m

    daniel3m Your Mum

    Messages:
    26
    Likes Received:
    2
    Trophy Points:
    47
    Guild:
    HI THIS IS A COOL POST
     
  10. Arreme

    Arreme Veteran, Learning Game Design VIP+

    Messages:
    378
    Likes Received:
    328
    Trophy Points:
    85
    Minecraft:
    HI THIS IS A COOL REPLY.
    Jkjk, thanks ^.^!
     
  11. xKindredKinesis

    xKindredKinesis .[_]. VIP

    Messages:
    3,997
    Likes Received:
    8,656
    Trophy Points:
    217
    Minecraft:
    i like it, but it's kinda difficult
    maybe something to consider if wynn ever becomes a standalone game
    implementing this into wynn in its current state would be pretty damn hard
     
  12. Arreme

    Arreme Veteran, Learning Game Design VIP+

    Messages:
    378
    Likes Received:
    328
    Trophy Points:
    85
    Minecraft:
    If you look on this page, there is someone who has already done this ;). I think I would have to put it on the main post
     
  13. xKindredKinesis

    xKindredKinesis .[_]. VIP

    Messages:
    3,997
    Likes Received:
    8,656
    Trophy Points:
    217
    Minecraft:
    oh
    ...
    well ill be damned
     
  14. Arreme

    Arreme Veteran, Learning Game Design VIP+

    Messages:
    378
    Likes Received:
    328
    Trophy Points:
    85
    Minecraft:
    *Bump* Only you can make this idea succesful! *Bump*
     
  15. SPYROHAWK

    SPYROHAWK Head Grand Theorist HERO

    Messages:
    3,743
    Likes Received:
    4,302
    Trophy Points:
    194
    Minecraft:
    Cooleo. Not bad, but I am not sure if it is possible
     
  16. DarkDemonDragon

    DarkDemonDragon Sorta Veteran

    Messages:
    565
    Likes Received:
    690
    Trophy Points:
    89
    Minecraft:
    Well the basic coding for it has already been done so it is possible. However, lag with hundreds of players could change things. I feel like the first week after this is implemented will be hell for ocean travel with strange bugs happening, but after several weeks of refinement it could be worth it to have a complex and realistic ocean. It's all up to whether the admins want to take that risk.
     
  17. Ironraptor3

    Ironraptor3 Dragon Slayer, Sabre, CS/Game Dev VIP

    Messages:
    1,103
    Likes Received:
    605
    Trophy Points:
    117
    Guild:
    Minecraft:
    Hm, I realize that what I said earlier about using equations would actually be insanely efficient, as rather than checking points, one would only need to check whether the player was in or out of each of the currents (There are only 13 in this suggestion, 1 extra for the bottom half of the circle around volcano islands, if you do not have a function in the wynn API for +/-)

    Pseudocode:
    Code:
    Write an equation for a current
    Write derivative of current (in vector form)
    Set strength of current and whether it flows in the positive or negative direction
    
    Now that you have all of this:
    For players in boats check their x (or z cord), have it rounded to an acceptable interval.
    Plug this value into each equation
    If the resultant z is close to the player's z (or x if you chose to use z initially), then they are in that specific current.  
    Distance formula (cpu intensive) is not needed, as all you need to do is subtract the two 1 dimensional coordinates.
    If they do in fact lie in the current, set their velocity to what it currently is + a the vector of the derivative in vector form (use parametric or convert slope).  
    The derivative, if you did not know, yields a line tangent to the curve (the slope at exactly one point, and therefore the player's should be instantaneous velocity).
    
    Recap:
    5 seconds of math on dev's part programming the currents
      -Even this can be bypassed with some additional coding
    Immensely accurate in both bounds and velocities
    No lengthy lists to be checked/No distance formula
    (I will probably make a full version for my friend's private server now xD)
    
     
    Arreme likes this.
  18. Arreme

    Arreme Veteran, Learning Game Design VIP+

    Messages:
    378
    Likes Received:
    328
    Trophy Points:
    85
    Minecraft:
    Wew, well den, now they can't say that this is difficult nor possible xD. Thanks a lot man for helping, I really appreciate it ;)
     
    Bebinson and Ironraptor3 like this.
  19. Ironraptor3

    Ironraptor3 Dragon Slayer, Sabre, CS/Game Dev VIP

    Messages:
    1,103
    Likes Received:
    605
    Trophy Points:
    117
    Guild:
    Minecraft:
    Well I had too much free time in school today xD
    Anyway here you all are, some minor changes could be made to the efficiency and the ability to write new functions, but this is basically the full version. The only thing that would need to be changed would be changing the bukkit API to the wynn API, whatever that may use xD. Just showin its possble/showing off/was bored

    Main.java:
    Code:
    public class Main extends JavaPlugin implements Listener {
       
        public static Plugin plugin;
        World w = null;
        public static final double speed = .3;
       
        //sorry I suck with naming while coding <3
       
        @Override
        public void onEnable() {
            plugin = this;
            Bukkit.getServer().getPluginManager().registerEvents(this, this);
            //add currents here.  This is the equation for the top half of the volcano island circle (according to the wynn map coords)~
            //(Obviously can be changed from two Semi circles to 2 widened parabolas to improve performance further).
           
            OceanCurrent.currents.put(new OceanCurrent(new Equation("(250^2 + -1 * ((x+950)^2) ) ^ 0.5 - 3700",
                    "(-1* (x + 950)) / ((250^2 + -1 * ((x+950)^2) ) ^ 0.5)"), true, false, -1200, -700), true);
           
            currentLoop();
        }
        @Override
        public void onDisable() {
            plugin = null;
        }
       
        public static ConcurrentHashMap<Boat, Long> removing = new ConcurrentHashMap<Boat, Long>();
       
        public void currentLoop() {
            new BukkitRunnable() {
                @Override
                public void run() {
                    if (w == null) return;
                    for (Entity e : w.getEntities()) {
                        if (e instanceof Boat) {
                            Boat b = (Boat) e;
                            if (removing.containsKey(b)) {
                                if (b.getPassenger() != null && b.getPassenger() instanceof Player) removing.remove(b);
                                else if (System.currentTimeMillis() - removing.get(b) >= 10*1000) {
                                    removing.remove(b);//boats despawn within 10 seconds of being placed
                                    b.remove();
                                }
                            }
                            else {
                                if (b.getPassenger() == null || !(b.getPassenger() instanceof Player)) {
                                    removing.put(b, System.currentTimeMillis());
                                    continue;
                                }
                                for (OceanCurrent oc : OceanCurrent.currents.keySet()) {
                                    if (OceanCurrent.currents.get(oc) == false)continue;
                                    Player p = (Player) b.getPassenger();
                                    if (oc.checkCoords(p)) {
                                        oc.setVelocity(p);
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }
            }.runTaskTimer(plugin, 0, 5);
        }
       
        @EventHandler
        public void onClick(PlayerInteractEvent e) {
            if (w == null && e.getPlayer().getInventory().getItemInHand().getType().equals(Material.BOAT)) w = e.getPlayer().getWorld();
        }
       
    }
    //Written by Ironraptor3
    
    OceanCurrent.java:
    Code:
    public class OceanCurrent {
       
        //Define these two with testing
        static double hotMultiplier = .15;
        static double coldMultiplier = .1;
       
        Equation e;
        boolean hot;
        boolean posDirection;
        double bound1;
        double bound2;
       
        public static ConcurrentHashMap<OceanCurrent, Boolean> currents = new ConcurrentHashMap<OceanCurrent, Boolean>();
       
        public OceanCurrent(Equation e, boolean hot, boolean posDirection, double bound1, double bound2) {
            this.e=e;
            this.hot=hot;
            this.posDirection=posDirection;
            this.bound1 = bound1;
            this.bound2 = bound2;
        }
        //add particles if you wish, the only thing is particles lag
       
        public boolean checkCoords(Player p) {
            int x = (int) Math.floor(p.getLocation().getX());
            if (x < bound1 || x > bound2) return false;
            //unsure why something that can only be an integer states it returns a double, thanks java
            double z = p.getLocation().getZ();
            if (Math.abs(this.e.evaluate(x)-z) <= 20) return true;
            else return false;
        }
       
        public void setVelocity(Player p) {
            int x = (int) Math.floor(p.getLocation().getX());
            double slope = this.e.getTangent(x);
            Vector v = new Vector(1, 0, slope).normalize().multiply( (this.posDirection ? 1:-1)* (this.hot ? hotMultiplier:coldMultiplier));
            p.setVelocity(p.getVelocity().add(v));
        }
    }
    
    Equation.java:
    Code:
    public class Equation {
    
        String e;
        String d;
       
        public Equation(String e, String d) {
            this.e=e;
            this.d=d;
        }
       
        public double evaluate(double x) {
            return solve(e,x);
        }
       
        public double getTangent(double x) {
            return solve(d,x);
        }
        public static void main(String[] args) {
            System.out.println(new Equation("((62500 + -1 * ((x+950)^2) ) ^ 0.5)+ -3700", "0").evaluate(-950));
        }
        //warning: not perfect order of operations (P EMD AS) rather than (P E MD AS)
        //Please do not subtract, rather, use *-1 to numbers.  Do not write things such as 3x, write 3 * x
        //If you wish to fix any of this, it is relatively simple, use debug statements to check
        //You can also make a function for finding the derivative of this function, meh
        //But yeah, do with this what you will~
        @SuppressWarnings("unchecked")
        public static double solve(String s, double x) {
            List<Object> terms = new ArrayList<Object>();
            terms.add((double) 0);
            for (int i = 0; i < s.length(); i++) {
                if (s.charAt(i) == '(') {
                    for (int p = s.length() - 1; p > i; p--) if (s.charAt(p) == ')'){
                        terms.add(solve(s.substring(i+1, p), x));
                        i=p;
                        break;
                    }
                }
                else {
                    char current = s.charAt(i);
                    if (current == 'x') {
                        terms.add(x);
                    }
                    else if (Character.isDigit(current) || current == '.' || current == '-') {
                        for (int c = i; c <= s.length(); c++) {
                            if (c == s.length() || s.charAt(c) == ' ') {
                                terms.add(Double.parseDouble(s.substring(i, c)) );
                                i = c;
                                break;
                            }
                        }
                    }
                    else if (current == '*' || current == '/' || current == '^') terms.add(current);
                }       
            }
           
            if (terms.isEmpty()) return 0;
            else {
                int index = 0;
                terms.remove(0);
                while (index < terms.size()-1) {
                    if (terms.get(index) instanceof Character) {
                        double num;
                        double old1 = ((double) terms.get(index - 1));
                        double old2 = ((double) terms.get(index + 1));
                        Character c = (Character) terms.get(index);
                        if ( c == '*') num =  old1 * old2;
                        else if ( c == '/') num =  old1 * old2;
                        else {
                            num =  Math.pow(old1, old2);
                        }
                        terms.remove(index);
                        terms.remove(old1);
                        terms.remove(old2);
                        terms.add(0, num);
                        index=0;
                       
                    }
                    index++;
                }
               
                double sum = 0;
                for (double d : (List<Double>) (List<?>) terms) {
                    sum+=d;
                }
                return sum;
            }
        }
    }
     
    Bebinson likes this.
  20. Arreme

    Arreme Veteran, Learning Game Design VIP+

    Messages:
    378
    Likes Received:
    328
    Trophy Points:
    85
    Minecraft:
    Oh, mai, freaking god. Er... After all your work they have to try to add this xd. Really, thanks so much. Wish I know how to do that. Argh Want to lean coding.
     
Thread Status:
Not open for further replies.