· 5 years ago · May 09, 2020, 09:12 AM
1============================================ CORE ===============================================
2diff --git a/src/main/java/com/l2jserver/gameserver/GameServer.java b/src/main/java/com/l2jserver/gameserver/GameServer.java
3index 2babfaa..49ec9cc 100644
4--- a/src/main/java/com/l2jserver/gameserver/GameServer.java
5+++ b/src/main/java/com/l2jserver/gameserver/GameServer.java
6@@ -46,6 +46,7 @@
7 import com.l2jserver.commons.util.IPv4Filter;
8 import com.l2jserver.commons.util.Util;
9 import com.l2jserver.gameserver.cache.HtmCache;
10+import static com.l2jserver.gameserver.config.Configuration.votesystem;
11 import com.l2jserver.gameserver.dao.factory.impl.DAOFactory;
12 import com.l2jserver.gameserver.data.json.ExperienceData;
13 import com.l2jserver.gameserver.data.sql.impl.AnnouncementsTable;
14@@ -150,6 +151,8 @@
15 import com.l2jserver.gameserver.taskmanager.KnownListUpdateTaskManager;
16 import com.l2jserver.gameserver.taskmanager.TaskManager;
17 import com.l2jserver.gameserver.util.DeadLockDetector;
18+import com.l2jserver.gameserver.votesystem.Handler.voteManager;
19+import com.l2jserver.gameserver.votesystem.VoteUtil.VoteSiteXml;
20 import com.l2jserver.mmocore.SelectorConfig;
21 import com.l2jserver.mmocore.SelectorThread;
22
23@@ -262,6 +265,15 @@
24 ClanHallManager.getInstance();
25 AuctionManager.getInstance();
26
27+ printSection("Vote System");
28+ if(votesystem().getEnableVoteSystem()) {
29+ voteManager.getInatance();
30+ LOG.info("======================Vote System Enabled=========================");
31+ VoteSiteXml.getInstance();
32+ }else {
33+ LOG.info("======================Vote System Disabled=========================");
34+ }
35+
36 printSection("Geodata");
37 GeoData.getInstance();
38
39diff --git a/src/main/java/com/l2jserver/gameserver/Shutdown.java b/src/main/java/com/l2jserver/gameserver/Shutdown.java
40index c0fca98..29d3fff 100644
41--- a/src/main/java/com/l2jserver/gameserver/Shutdown.java
42+++ b/src/main/java/com/l2jserver/gameserver/Shutdown.java
43@@ -50,6 +50,7 @@
44 import com.l2jserver.gameserver.network.serverpackets.ServerClose;
45 import com.l2jserver.gameserver.network.serverpackets.SystemMessage;
46 import com.l2jserver.gameserver.util.Broadcast;
47+import com.l2jserver.gameserver.votesystem.Handler.voteManager;
48
49 /**
50 * This class provides the functions for shutting down and restarting the server.<br>
51@@ -231,6 +232,14 @@
52 } catch (Exception e) {
53 // ignore
54 }
55+
56+ try{
57+ //Save global and individual votes
58+ voteManager.getInatance().Shutdown();
59+ LOG.info("Vote data has been saved");
60+ }catch(Exception e){
61+ //ignore
62+ }
63
64 // commit data, last chance
65 ConnectionFactory.getInstance().close();
66diff --git a/src/main/java/com/l2jserver/gameserver/config/Configuration.java b/src/main/java/com/l2jserver/gameserver/config/Configuration.java
67index 3b6ed3c..e7a1f87 100644
68--- a/src/main/java/com/l2jserver/gameserver/config/Configuration.java
69+++ b/src/main/java/com/l2jserver/gameserver/config/Configuration.java
70@@ -80,6 +80,8 @@
71 private static final PvPConfiguration pvp = ConfigFactory.create(PvPConfiguration.class);
72
73 private static final CustomsConfiguration customs = ConfigFactory.create(CustomsConfiguration.class);
74+
75+ private static final VoteSystemConfiguration votesystem = ConfigFactory.create(VoteSystemConfiguration.class);
76
77 private static final FloodProtectorConfiguration floodProtector = ConfigFactory.create(FloodProtectorConfiguration.class);
78
79@@ -187,6 +189,10 @@
80 return customs;
81 }
82
83+ public static VoteSystemConfiguration votesystem(){
84+ return votesystem;
85+ }
86+
87 public static FloodProtectorConfiguration floodProtector() {
88 return floodProtector;
89 }
90diff --git a/src/main/java/com/l2jserver/gameserver/config/VoteSystemConfiguration.java b/src/main/java/com/l2jserver/gameserver/config/VoteSystemConfiguration.java
91new file mode 100644
92index 0000000..ae68841
93--- /dev/null
94+++ b/src/main/java/com/l2jserver/gameserver/config/VoteSystemConfiguration.java
95@@ -0,0 +1,146 @@
96+/*
97+ * To change this license header, choose License Headers in Project Properties.
98+ * To change this template file, choose Tools | Templates
99+ * and open the template in the editor.
100+ */
101+package com.l2jserver.gameserver.config;
102+
103+import com.l2jserver.gameserver.config.converter.Hours2MillisecondsConverter;
104+import com.l2jserver.gameserver.config.converter.Minutes2MillisecondsConverter;
105+import static java.util.concurrent.TimeUnit.MINUTES;
106+import org.aeonbits.owner.Config;
107+import static org.aeonbits.owner.Config.HotReloadType.ASYNC;
108+import org.aeonbits.owner.Reloadable;
109+
110+/**
111+ *
112+ * @author escor
113+ */
114+
115+@Config.Sources({
116+ "file:./config/votesystem.properties",
117+ "classpath:config/votesystem.properties"
118+})
119+@Config.HotReload(value = 20, unit = MINUTES, type = ASYNC)
120+public interface VoteSystemConfiguration extends Config, Reloadable{
121+
122+ @Key("EnableVoteSystem")
123+ Boolean getEnableVoteSystem();
124+
125+ @Key("EnableGlobalVote")
126+ Boolean getEnableGlobalVote();
127+
128+ @Key("EnableIndividualVote")
129+ Boolean getEnableIndividualVote();
130+
131+ @Key("NextTimeToAutoUpdateTotalVote")
132+ @ConverterClass(Minutes2MillisecondsConverter.class)
133+ Integer getNextTimeToAutoUpdateTotalVote();
134+
135+ @Key("NextTimeToAutoUpdateIndividualVotes")
136+ @ConverterClass(Minutes2MillisecondsConverter.class)
137+ Integer getNextTimeToAutoUpdateIndividualVotes();
138+
139+ @Key("NextTimeToAutoCleanInnecesaryVotes")
140+ @ConverterClass(Minutes2MillisecondsConverter.class)
141+ Integer getNextTimeToAutoCleanInnecesaryVotes();
142+
143+ @Key("NextTimeToCheckAutoGlobalVotesReward")
144+ @ConverterClass(Minutes2MillisecondsConverter.class)
145+ Integer getNextTimeToCheckAutoGlobalVotesReward();
146+
147+ @Key("IntervalToNextVote")
148+ @ConverterClass(Hours2MillisecondsConverter.class)
149+ Integer getIntervalToNextVote();
150+
151+ @Key("GlobalVotesAmountToNextReward")
152+ Integer getGlobalVotesAmountToNextReward();
153+
154+ @Key("EnableVotingCommand")
155+ Boolean getEnableVotingCommand();
156+
157+ @Key("VotingCommand")
158+ String getVotingCommand();
159+
160+ @Key("VoteLinkTgs")
161+ String getVoteLinkTgs();
162+
163+ @Key("TgsApiKey")
164+ String getTgsApiKey();
165+
166+ @Key("VoteLinkTopCo")
167+ String getVoteLinkTopCo();
168+
169+ @Key("TopCoSrvId")
170+ String getTopCoSrvId();
171+
172+ @Key("VoteLinkItopz")
173+ String getVoteLinkItopz();
174+
175+ @Key("ItopzZpiKey")
176+ String getItopzZpiKey();
177+
178+ @Key("ItopzSrvId")
179+ String getItopzSrvId();
180+
181+ @Key("VoteLinkVts")
182+ String getVoteLinkVts();
183+
184+ @Key("VtsApiKey")
185+ String getVtsApiKey();
186+
187+ @Key("VtsSid")
188+ String getVtsSid();
189+
190+ @Key("VoteLinkHz")
191+ String getVoteLinkHz();
192+
193+ @Key("HzApiKey")
194+ String getHzApiKey();
195+
196+ @Key("VoteNetworkLink")
197+ String getVoteNetworkLink();
198+
199+ @Key("VoteNetworkUserName")
200+ String getVoteNetworkUserName();
201+
202+ @Key("VoteNetworkApiKey")
203+ String getVoteNetworkApiKey();
204+
205+ @Key("VoteLinkTss")
206+ String getVoteLinkTss();
207+
208+ @Key("TssApiToken")
209+ String getTssApiToken();
210+
211+ @Key("BrasilVoteLink")
212+ String getBrasilVoteLink();
213+
214+ @Key("BrasilUserName")
215+ String getBrasilUserName();
216+
217+ @Key("VoteLinkMmotop")
218+ String getVoteLinkMmotop();
219+
220+ @Key("MmotopApiKey")
221+ String getMmotopApiKey();
222+
223+ @Key("VoteLinkTz")
224+ String getVoteLinkTz();
225+
226+ @Key("TzApiKey")
227+ String getTzApiKey();
228+
229+ @Key("VoteLinkServers")
230+ String getVoteLinkServers();
231+
232+ @Key("ServersHashCode")
233+ String getServersHashCode();
234+
235+ @Key("ServersSrvId")
236+ String getServersSrvId();
237+
238+ @Key("TestIp")
239+ String getTestIp();
240+
241+}
242diff --git a/src/main/java/com/l2jserver/gameserver/config/converter/Hours2MillisecondsConverter.java b/src/main/java/com/l2jserver/gameserver/config/converter/Hours2MillisecondsConverter.java
243new file mode 100644
244index 0000000..4d408d0
245--- /dev/null
246+++ b/src/main/java/com/l2jserver/gameserver/config/converter/Hours2MillisecondsConverter.java
247@@ -0,0 +1,25 @@
248+/*
249+ * To change this license header, choose License Headers in Project Properties.
250+ * To change this template file, choose Tools | Templates
251+ * and open the template in the editor.
252+ */
253+package com.l2jserver.gameserver.config.converter;
254+
255+import java.lang.reflect.Method;
256+import static java.util.concurrent.TimeUnit.HOURS;
257+import org.aeonbits.owner.Converter;
258+import org.apache.logging.log4j.util.Strings;
259+
260+/**
261+ *
262+ * @author escor
263+ */
264+public class Hours2MillisecondsConverter implements Converter<Integer> {
265+ @Override
266+ public Integer convert(Method method, String input) {
267+ if (Strings.isBlank(input)) {
268+ return 0;
269+ }
270+ return (int) HOURS.toMillis(Integer.parseInt(input));
271+ }
272+}
273diff --git a/src/main/java/com/l2jserver/gameserver/model/actor/instance/L2NpcVoteInstance.java b/src/main/java/com/l2jserver/gameserver/model/actor/instance/L2NpcVoteInstance.java
274new file mode 100644
275index 0000000..818baa0
276--- /dev/null
277+++ b/src/main/java/com/l2jserver/gameserver/model/actor/instance/L2NpcVoteInstance.java
278@@ -0,0 +1,93 @@
279+/*
280+ * To change this license header, choose License Headers in Project Properties.
281+ * To change this template file, choose Tools | Templates
282+ * and open the template in the editor.
283+ */
284+package com.l2jserver.gameserver.model.actor.instance;
285+
286+import com.l2jserver.gameserver.cache.HtmCache;
287+import static com.l2jserver.gameserver.config.Configuration.votesystem;
288+import com.l2jserver.gameserver.datatables.ItemTable;
289+import com.l2jserver.gameserver.model.actor.L2Npc;
290+import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
291+import com.l2jserver.gameserver.network.serverpackets.NpcHtmlMessage;
292+import com.l2jserver.gameserver.votesystem.Enum.voteSite;
293+import com.l2jserver.gameserver.votesystem.Handler.voteManager;
294+import com.l2jserver.gameserver.votesystem.Model.Reward;
295+import com.l2jserver.gameserver.votesystem.VoteUtil.VoteSiteXml;
296+
297+/**
298+ *
299+ * @author escor
300+ */
301+public class L2NpcVoteInstance extends L2Npc{
302+
303+ public L2NpcVoteInstance(L2NpcTemplate template) {
304+ super(template);
305+ }
306+
307+ @Override
308+ public void onBypassFeedback(L2PcInstance activeChar, String command)
309+ {
310+ if(command == null) {
311+ return;
312+ }
313+ int Ordinalsite = Integer.parseInt(command);
314+ voteManager.getInatance().getReward(activeChar, Ordinalsite);
315+ showChatWindow(activeChar,0);
316+ super.onBypassFeedback(activeChar, command);
317+ }
318+
319+ @Override
320+ public void showChatWindow(L2PcInstance activeChar, int val) {
321+ final NpcHtmlMessage html = new NpcHtmlMessage(0);
322+ StringBuilder sb = new StringBuilder();
323+ int npcId = getTemplate().getId();
324+ String filename = HtmCache.getInstance().getHtm(activeChar.getHtmlPrefix(), getHtmlPath(npcId, 0));
325+ html.setHtml(filename);
326+ int count = 2;
327+ for(voteSite vs : voteSite.values()) {
328+ if(count%2 == 1)
329+ sb.append("<table bgcolor=002F17 width=280><tr>");
330+ else
331+ sb.append("<table bgcolor=000C2F width=280><tr>");
332+ sb.append("<td width=32><img src=\"icon.etc_treasure_box_i08\" width=32 height=32></td>");
333+ sb.append("<td width=220><table width=220>");
334+ sb.append("<tr><td><table width=220><tr><td width=145>"+String.format("%s",VoteSiteXml.getInstance().getSiteName(vs.ordinal()))+"</td>");
335+ if(voteManager.getInatance().checkIndividualAvailableVote(activeChar, vs.ordinal())) {
336+ sb.append("<td width=75>"+String.format("<button value=\"Get reward\" action=\"bypass -h vote_%s_site %s\" height=17 width=70 back=\"L2UI_CT1.Button_DF_Down\" fore=\"L2UI_CT1.Button_DF\">",getObjectId(),vs.ordinal())+"</td>");
337+ }else {
338+ sb.append(String.format("<td width=75 align=center><font color=C68E00>%s</font></td>", voteManager.getInatance().getTimeRemainingWithSampleFormat(activeChar, vs.ordinal())));
339+ }
340+ sb.append("</tr></table></td></tr>");
341+ sb.append("<tr><td><table width=220><tr>");
342+ int i=0;
343+ for(Reward r : VoteSiteXml.getInstance().getRewards(vs.ordinal())) {
344+ sb.append(String.format("<td width=110 height=32 align=center><font color=BFAF00>%s x%s</font></td>",ItemTable.getInstance().getTemplate(r.getItemId()).getName(), r.getItemCount()));
345+ i++;
346+ if(i%2==0) {
347+ sb.append("</tr><tr>");
348+ }
349+ }
350+ sb.append("</tr></table></td></tr></table></td></tr></table><br>");
351+ count++;
352+ }
353+ html.replace("%everyXtime%",votesystem().getIntervalToNextVote()/(3600*1000));
354+ html.replace("%enablevote%", sb.toString());
355+ html.replace("%accountName%",activeChar.getName());
356+ activeChar.sendPacket(html);
357+ }
358+
359+ @Override
360+ public String getHtmlPath(int npcId, int val)
361+ {
362+ String filename = "";
363+ if (val == 0)
364+ filename = "" + npcId;
365+ else
366+ filename = npcId + "-" + val;
367+
368+ return "data/html/mods/votesystem/" + filename + ".html";
369+ }
370+
371+}
372diff --git a/src/main/java/com/l2jserver/gameserver/network/clientpackets/RequestBypassToServer.java b/src/main/java/com/l2jserver/gameserver/network/clientpackets/RequestBypassToServer.java
373index 32d362d..5cc05e8 100644
374--- a/src/main/java/com/l2jserver/gameserver/network/clientpackets/RequestBypassToServer.java
375+++ b/src/main/java/com/l2jserver/gameserver/network/clientpackets/RequestBypassToServer.java
376@@ -168,7 +168,24 @@
377 }
378
379 activeChar.sendPacket(ActionFailed.STATIC_PACKET);
380- } else if (_command.startsWith("item_")) {
381+ }else if(_command.startsWith("vote_")) {
382+ int endOfId = _command.indexOf('_', 6);
383+ String id;
384+ if (endOfId > 0) {
385+ id = _command.substring(5, endOfId);
386+ } else {
387+ id = _command.substring(5);
388+ }
389+ if (Util.isDigit(id)) {
390+ L2Object object = L2World.getInstance().findObject(Integer.parseInt(id));
391+
392+ if ((object != null) && object.isNpc() && (endOfId > 0) && activeChar.isInsideRadius(object, L2Npc.INTERACTION_DISTANCE, false, false)) {
393+ ((L2Npc) object).onBypassFeedback(activeChar, _command.split(" ")[1]);
394+ }
395+ }
396+ activeChar.sendPacket(ActionFailed.STATIC_PACKET);
397+
398+ } else if (_command.startsWith("item_")) {
399 int endOfId = _command.indexOf('_', 5);
400 String id;
401 if (endOfId > 0) {
402diff --git a/src/main/java/com/l2jserver/gameserver/util/IXmlReader.java b/src/main/java/com/l2jserver/gameserver/util/IXmlReader.java
403index fa2430b..4e9dc80 100644
404--- a/src/main/java/com/l2jserver/gameserver/util/IXmlReader.java
405+++ b/src/main/java/com/l2jserver/gameserver/util/IXmlReader.java
406@@ -19,6 +19,7 @@
407 package com.l2jserver.gameserver.util;
408
409 import static com.l2jserver.gameserver.config.Configuration.server;
410+import com.l2jserver.gameserver.model.StatsSet;
411
412 import java.io.File;
413 import java.io.FileFilter;
414@@ -147,7 +148,7 @@
415 }
416 return true;
417 }
418-
419+
420 /**
421 * Wrapper for {@link #parseDirectory(File, boolean)}.
422 * @param path the path to the directory where the XML files are
423@@ -537,6 +538,19 @@
424 }
425 }
426
427+ default StatsSet parseAttributes(Node node)
428+ {
429+ final NamedNodeMap attrs = node.getAttributes();
430+ final StatsSet map = new StatsSet();
431+ for (int i = 0; i < attrs.getLength(); i++)
432+ {
433+ final Node att = attrs.item(i);
434+ map.set(att.getNodeName(), att.getNodeValue());
435+ }
436+ return map;
437+ }
438+
439+
440 /**
441 * Parses an enumerated value.
442 * @param <T> the enumerated type
443diff --git a/src/main/java/com/l2jserver/gameserver/votesystem/DB/globalVoteDB.java b/src/main/java/com/l2jserver/gameserver/votesystem/DB/globalVoteDB.java
444new file mode 100644
445index 0000000..e5714e4
446--- /dev/null
447+++ b/src/main/java/com/l2jserver/gameserver/votesystem/DB/globalVoteDB.java
448@@ -0,0 +1,97 @@
449+/*
450+ * To change this license header, choose License Headers in Project Properties.
451+ * To change this template file, choose Tools | Templates
452+ * and open the template in the editor.
453+ */
454+package com.l2jserver.gameserver.votesystem.DB;
455+
456+import com.l2jserver.commons.database.ConnectionFactory;
457+import com.l2jserver.gameserver.votesystem.Enum.voteSite;
458+import com.l2jserver.gameserver.votesystem.Model.globalVote;
459+import com.l2jserver.gameserver.votesystem.VoteUtil.VoteUtil;
460+import java.sql.Connection;
461+import java.sql.PreparedStatement;
462+import java.sql.ResultSet;
463+import java.sql.SQLException;
464+import java.sql.Statement;
465+import java.util.logging.Level;
466+import java.util.logging.Logger;
467+
468+/**
469+ *
470+ * @author escor
471+ */
472+public class globalVoteDB {
473+ private static final Logger LOGGER = Logger.getLogger(globalVoteDB.class.getName());
474+ private globalVote[] _globalVotes;
475+ private globalVoteDB() {
476+ _globalVotes = new globalVote[voteSite.values().length];
477+ loadGlobalVotes();
478+ }
479+
480+ public void loadGlobalVotes() {
481+ try(Connection con = ConnectionFactory.getInstance().getConnection();PreparedStatement ps = con.prepareStatement("Select voteSite,lastRewardVotes from globalVotes");
482+ ResultSet rs = ps.executeQuery();){
483+ if(rs.getRow() == 0){
484+ for(voteSite vs : voteSite.values()){
485+ globalVote gv = new globalVote();
486+ gv.setVoteSite(vs.ordinal());
487+ gv.setVotesLastReward(0);
488+ _globalVotes[gv.getVoyeSite()] = gv;
489+ }
490+ return;
491+ }
492+ while(rs.next()) {
493+ globalVote gv = new globalVote();
494+ gv.setVoteSite(rs.getInt("voteSite"));
495+ gv.setVotesLastReward(rs.getInt("lastRewardVotes"));
496+ _globalVotes[gv.getVoyeSite()] = gv;
497+ }
498+ LOGGER.log(Level.INFO,"{} global votes have been uploaded", new Object[]{_globalVotes.length});
499+ }catch(SQLException e) {
500+
501+ e.printStackTrace();
502+ }
503+ }
504+ public void saveGlobalVote(globalVote gb) {
505+ try(Connection con = ConnectionFactory.getInstance().getConnection();PreparedStatement ps = con.prepareStatement("INSERT INTO globalVotes(voteSite,lastRewardVotes) VALUES(?,?)"
506+ + "ON DUPLICATE KEY UPDATE voteSite = VALUES(voteSite), lastRewardVotes = VALUES(lastRewardVotes)"))
507+
508+ {
509+ ps.setInt(1, gb.getVoyeSite());
510+ ps.setInt(2, gb.getVotesLastReward());
511+ ps.executeUpdate();
512+
513+ }catch(SQLException e) {
514+ e.printStackTrace();
515+ }
516+ }
517+
518+ public void saveGlobalVotes(globalVote[] globalVotes) {
519+ try(Connection con = ConnectionFactory.getInstance().getConnection();PreparedStatement ps = con.prepareStatement("INSERT INTO globalVotes(voteSite,lastRewardVotes) VALUES(?,?)"
520+ + "ON DUPLICATE KEY UPDATE voteSite = VALUES(voteSite), lastRewardVotes = VALUES(lastRewardVotes)"))
521+
522+ {
523+ for(voteSite vs : voteSite.values()) {
524+ globalVote gb = globalVotes[vs.ordinal()];
525+ ps.setInt(1, gb.getVoyeSite());
526+ ps.setInt(2, gb.getVotesLastReward());
527+ ps.addBatch();
528+ }
529+ ps.executeBatch();
530+
531+ }catch(SQLException e) {
532+ e.printStackTrace();
533+ }
534+ }
535+
536+ public globalVote[] getGlobalVotes() {
537+ return _globalVotes;
538+ }
539+ public static final globalVoteDB getInstance() {
540+ return SingleHolder.INSTANCE;
541+ }
542+ private static final class SingleHolder {
543+ protected static final globalVoteDB INSTANCE = new globalVoteDB();
544+ }
545+}
546diff --git a/src/main/java/com/l2jserver/gameserver/votesystem/DB/individualVoteDB.java b/src/main/java/com/l2jserver/gameserver/votesystem/DB/individualVoteDB.java
547new file mode 100644
548index 0000000..8a298b7
549--- /dev/null
550+++ b/src/main/java/com/l2jserver/gameserver/votesystem/DB/individualVoteDB.java
551@@ -0,0 +1,143 @@
552+/*
553+ * To change this license header, choose License Headers in Project Properties.
554+ * To change this template file, choose Tools | Templates
555+ * and open the template in the editor.
556+ */
557+package com.l2jserver.gameserver.votesystem.DB;
558+
559+import com.l2jserver.commons.database.ConnectionFactory;
560+import com.l2jserver.gameserver.votesystem.Model.individualVote;
561+import java.sql.Connection;
562+import java.sql.PreparedStatement;
563+import java.sql.ResultSet;
564+import java.sql.SQLException;
565+import java.sql.Statement;
566+import java.util.HashSet;
567+import java.util.logging.Level;
568+import java.util.logging.Logger;
569+
570+/**
571+ *
572+ * @author escor
573+ */
574+public final class individualVoteDB {
575+ private static final Logger LOGGER = Logger.getLogger(individualVoteDB.class.getName());
576+ private HashSet<individualVote> _votes;
577+ private Statement st;
578+ private Connection con;
579+
580+ private individualVoteDB() {
581+ _votes = new HashSet<>();
582+ loadVotes();
583+ }
584+
585+ public void loadVotes() {
586+ _votes.clear();
587+ try(Connection con = ConnectionFactory.getInstance().getConnection();PreparedStatement ps = con.prepareStatement("SELECT voterIp,voteSite,serverVotingTime,votingTimeSite,alreadyRewarded FROM individualVotes");
588+ ResultSet rs = ps.executeQuery();)
589+ {
590+ while(rs.next()) {
591+ individualVote iv = new individualVote();
592+ iv.setVoterIp(rs.getString("voterIp"));
593+ iv.setVoteSite(rs.getInt("voteSite"));
594+ iv.setServerVotingTime(rs.getLong("serverVotingTime"));
595+ iv.setVotingTimeSite(rs.getLong("votingTimeSite"));
596+ iv.setAlreadyRewarded(rs.getBoolean("alreadyRewarded"));
597+ _votes.add(iv);
598+ }
599+ }
600+ catch (SQLException e)
601+ {
602+ // TODO Auto-generated catch block
603+ e.printStackTrace();
604+ }
605+
606+ }
607+
608+ public void SaveVotes(HashSet<individualVote> votes) {
609+
610+ if(votes == null)
611+ return;
612+ if(votes.size() == 0) {
613+ return;
614+ }
615+ try(Connection con = ConnectionFactory.getInstance().getConnection(); PreparedStatement ps = con.prepareStatement("INSERT INTO individualVotes(voterIp,voteSite,serverVotingTime,votingTimeSite,alreadyRewarded) VALUES(?,?,?,?,?) ON DUPLICATE KEY UPDATE "
616+ + "voterIp = VALUES(voterIp), voteSite = VALUES(voteSite), serverVotingTime = VALUES(serverVotingTime), votingTimeSite = VALUES(votingTimeSite),alreadyRewarded = VALUES(alreadyRewarded)");)
617+ {
618+
619+ for(individualVote iv : votes) {
620+ ps.setString(1, iv.getVoterIp());
621+ ps.setInt(2, iv.getVoteSite());
622+ ps.setLong(3, iv.getServerVotingTime());
623+ ps.setLong(4, iv.getVotingTimeSite());
624+ ps.setBoolean(5, iv.getAlreadyRewarded());
625+ ps.addBatch();
626+ }
627+ ps.executeBatch();
628+ ps.close();
629+ con.close();
630+ }
631+ catch (SQLException e)
632+ {
633+ e.printStackTrace();
634+ }
635+ }
636+
637+public void SaveVote(individualVote vote) {
638+
639+ if(vote == null)
640+ return;
641+ try(Connection con = ConnectionFactory.getInstance().getConnection(); PreparedStatement ps = con.prepareStatement("INSERT INTO individualVotes(voterIp,voteSite,serverVotingTime,votingTimeSite,alreadyRewarded) VALUES(?,?,?,?,?) ON DUPLICATE KEY UPDATE"
642+ + "voterIp = VALUES(voterIp), voteSite = VALUES(voteSite), serverVotingTime = VALUES(serverVotingTime), votingTimeSite = VALUES(votingTimeSite), alreadyRewarded = VALUES(alreadyRewarded)");)
643+ {
644+ ps.setString(1, vote.getVoterIp());
645+ ps.setInt(2, vote.getVoteSite());
646+ ps.setLong(3, vote.getServerVotingTime());
647+ ps.setLong(4, vote.getVotingTimeSite());
648+ ps.setBoolean(5, vote.getAlreadyRewarded());
649+ ps.executeUpdate();
650+ }
651+ catch (SQLException e)
652+ {
653+ e.printStackTrace();
654+ }
655+ }
656+
657+ public void DeleteVotes(HashSet<individualVote> deleteVotes) {
658+ if(deleteVotes == null) {
659+ return;
660+ }
661+ if(deleteVotes.size() == 0) {
662+ return;
663+ }
664+ try {
665+ con = ConnectionFactory.getInstance().getConnection();
666+ st = con.createStatement();
667+ for(individualVote iv : deleteVotes) {
668+ String sql = String.format("Delete from individualVotes where voterIp = '%s' AND voteSite = %s", iv.getVoterIp(),iv.getVoteSite());
669+ st.addBatch(sql);
670+ }
671+ int[] result = st.executeBatch();
672+ st.close();
673+ con.close();
674+
675+ LOGGER.log(Level.INFO, "Delete Innecesary votes: {0}", new Object[]{result.length});
676+
677+ }catch(SQLException e) {
678+ e.printStackTrace();
679+ }
680+ }
681+
682+ public HashSet<individualVote> getVotesDB(){
683+ return _votes;
684+ }
685+
686+ public static final individualVoteDB getInstance()
687+ {
688+ return SingleHolder.INSTANCE;
689+ }
690+
691+ private static final class SingleHolder {
692+ protected static final individualVoteDB INSTANCE = new individualVoteDB();
693+ }
694+}
695diff --git a/src/main/java/com/l2jserver/gameserver/votesystem/Enum/voteSite.java b/src/main/java/com/l2jserver/gameserver/votesystem/Enum/voteSite.java
696new file mode 100644
697index 0000000..3685107
698--- /dev/null
699+++ b/src/main/java/com/l2jserver/gameserver/votesystem/Enum/voteSite.java
700@@ -0,0 +1,24 @@
701+/*
702+ * To change this license header, choose License Headers in Project Properties.
703+ * To change this template file, choose Tools | Templates
704+ * and open the template in the editor.
705+ */
706+package com.l2jserver.gameserver.votesystem.Enum;
707+
708+/**
709+ *
710+ * @author escor
711+ */
712+public enum voteSite {
713+ L2TOPGAMESERVER,
714+ ITOPZ,
715+ L2TOPCO,
716+ L2VOTES,
717+ HOPZONE,
718+ L2NETWORK,
719+ L2TOPSERVERS,
720+ TOPL2JBRASIL,
721+ MMOTOP,
722+ TOPZONE,
723+ L2SERVERS,
724+}
725diff --git a/src/main/java/com/l2jserver/gameserver/votesystem/Handler/voteHandler.java b/src/main/java/com/l2jserver/gameserver/votesystem/Handler/voteHandler.java
726new file mode 100644
727index 0000000..d8cf8e1
728--- /dev/null
729+++ b/src/main/java/com/l2jserver/gameserver/votesystem/Handler/voteHandler.java
730@@ -0,0 +1,498 @@
731+/*
732+ * To change this license header, choose License Headers in Project Properties.
733+ * To change this template file, choose Tools | Templates
734+ * and open the template in the editor.
735+ */
736+package com.l2jserver.gameserver.votesystem.Handler;
737+
738+import static com.l2jserver.gameserver.config.Configuration.votesystem;
739+import com.l2jserver.gameserver.votesystem.Model.individualVoteResponse;
740+import com.l2jserver.gameserver.votesystem.VoteUtil.VoteUtil;
741+import java.io.BufferedReader;
742+import java.io.DataOutputStream;
743+import java.io.IOException;
744+import java.io.InputStreamReader;
745+import java.net.HttpURLConnection;
746+import java.net.URL;
747+import java.nio.charset.Charset;
748+import java.text.ParseException;
749+import java.text.SimpleDateFormat;
750+import java.util.logging.Level;
751+import java.util.logging.Logger;
752+
753+/**
754+ *
755+ * @author escor
756+ */
757+public class voteHandler {
758+ public static final Logger LOGGER = Logger.getLogger(voteHandler.class.getName());
759+
760+ protected static String getNetWorkResponse(String URL,int ordinal) {
761+ try {
762+ String API_URL = votesystem().getVoteNetworkLink();
763+ String detail = URL;
764+ String postParameters = "";
765+ postParameters +="apiKey="+VoteUtil.between("apiKey=", detail, "&type=");
766+ postParameters += "&type="+VoteUtil.between("&type=", detail, "&player");
767+ String beginIndexPlayer = "&player=";
768+ String player = detail.substring(detail.indexOf(beginIndexPlayer)+beginIndexPlayer.length());
769+
770+ if (player != null && !player.equals(""))
771+ postParameters += "&player=" + player;
772+
773+ byte[] postData = postParameters.getBytes(Charset.forName("UTF-8"));
774+ URL url = new URL(API_URL);
775+ HttpURLConnection con = (HttpURLConnection)url.openConnection();
776+ con.setConnectTimeout(5000);
777+ con.setRequestMethod("POST");
778+ con.setRequestProperty("Content-Length", Integer.toString(postData.length));
779+ con.setRequestProperty("User-Agent", "Mozilla/5.0");
780+ con.setDoOutput(true);
781+
782+ DataOutputStream os = new DataOutputStream(con.getOutputStream());
783+ os.write(postData);
784+ os.flush();
785+ os.close();
786+
787+ BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
788+ String inputLine;
789+ StringBuffer response = new StringBuffer();
790+
791+ while ((inputLine = in.readLine()) != null) {
792+ response.append(inputLine);
793+ }
794+ in.close();
795+ return response.toString();
796+
797+ } catch (IOException e) {
798+ LOGGER.log(Level.WARNING, "{0} Say: An error ocurred {1}", new Object[]{VoteUtil.Sites[ordinal], e.getMessage()});
799+ return "";
800+ }
801+ }
802+
803+ protected static String getResponse(String Url, int ordinal)
804+ {
805+
806+ try
807+ {
808+ int responseCode = 0;
809+ URL objUrl = new URL(Url);
810+ HttpURLConnection con = (HttpURLConnection) objUrl.openConnection();
811+ con.setRequestMethod("GET");
812+ con.setRequestProperty("User-Agent", "Mozilla/5.0");
813+ con.setConnectTimeout(5000);
814+ responseCode = con.getResponseCode();
815+ if (responseCode == HttpURLConnection.HTTP_OK) {
816+ String inputLine;
817+ StringBuffer response = new StringBuffer();
818+ BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
819+ while ((inputLine = in.readLine()) != null) {
820+ response.append(inputLine);
821+ }
822+ in.close();
823+ return response.toString();
824+ }
825+
826+ }
827+ catch (IOException e)
828+ {
829+ LOGGER.log(Level.WARNING, "{0} Say: An error ocurred {1}", new Object[]{VoteUtil.Sites[ordinal],e.getMessage()});
830+ return "";
831+ }
832+
833+ return "";
834+ }
835+
836+
837+ public static individualVoteResponse getIndividualVoteResponse(int ordinal,String ip, String AccountName)
838+ {
839+ String response = "";
840+ boolean isVoted = false;
841+ long voteSiteTime = 0L, serverVoteTime = 0L;
842+ SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
843+ individualVoteResponse ivr = new individualVoteResponse();
844+
845+ switch(ordinal)
846+ {
847+ case 0:
848+ response = getResponse(getIndividualUrl(ordinal,ip,null),ordinal);
849+ isVoted = Boolean.parseBoolean(VoteUtil.between("\"already_voted\":", response, ",\"vote_time\""));
850+ if(isVoted) {
851+ try
852+ {
853+ voteSiteTime = format.parse(VoteUtil.between("\"vote_time\":\"", response, "\",\"server_time\"")).getTime();
854+ serverVoteTime = VoteUtil.getTimeVotingSite(ordinal);
855+ }
856+ catch (ParseException e)
857+ {
858+ e.printStackTrace();
859+ }
860+ }
861+ break;
862+
863+ case 1:
864+ response = getResponse(getIndividualUrl(ordinal,ip,null),ordinal);
865+ System.out.println(response);
866+ isVoted = Boolean.parseBoolean(response);
867+ if(isVoted) {
868+ voteSiteTime = VoteUtil.getTimeVotingSite(ordinal);
869+ serverVoteTime = VoteUtil.getTimeVotingSite(ordinal);
870+ }
871+ break;
872+
873+ case 2:
874+ response = getResponse(getIndividualUrl(ordinal,ip,null),ordinal);
875+ isVoted = Boolean.parseBoolean(response);
876+ if(isVoted) {
877+ voteSiteTime = VoteUtil.getTimeVotingSite(ordinal);
878+ serverVoteTime = VoteUtil.getTimeVotingSite(ordinal);
879+ }
880+ break;
881+
882+ case 3:
883+ response = getResponse(getIndividualUrl(ordinal,ip,null),ordinal);
884+ isVoted = Integer.parseInt(VoteUtil.between("\"status\":\"", response, "\",\"date\"")) == 1;
885+ if(isVoted) {
886+ String dateString = VoteUtil.between("\"date\":\"", response, "\"}]");
887+ try
888+ {
889+ voteSiteTime = format.parse(String.format("%s-%s-%s %s:%s:%s", dateString.substring(0, 4),dateString.substring(4, 6),dateString.substring(6, 8),dateString.substring(8, 10),dateString.substring(10, 12),dateString.substring(12, 14))).getTime();
890+ serverVoteTime = VoteUtil.getTimeVotingSite(ordinal);
891+ }
892+ catch (ParseException e)
893+ {
894+ e.printStackTrace();
895+ }
896+
897+ }
898+ break;
899+
900+ case 4:
901+ response = getResponse(getIndividualUrl(ordinal,ip,null),ordinal);
902+ isVoted = Boolean.parseBoolean(VoteUtil.between("\"voted\":", response, ",\"voteTime\""));
903+ if(isVoted) {
904+ try
905+ {
906+ voteSiteTime = format.parse(VoteUtil.between("\"voteTime\":\"", response, "\",\"hopzoneServerTime\"")).getTime();
907+ serverVoteTime = VoteUtil.getTimeVotingSite(ordinal);
908+ }
909+ catch (ParseException e)
910+ {
911+ e.printStackTrace();
912+ }
913+ }
914+ break;
915+
916+ case 5:
917+ //first method with date response
918+ /*response = getNetWorkResponse(getIndividualUrl(ordinal,ip,AccountName),ordinal);
919+ voteSiteTime = Long.parseLong(response)*1000;
920+ serverVoteTime = VoteUtil.getTimeVotingSite(ordinal);
921+ if(Config.INTERVAL_TO_NEXT_VOTE - (serverVoteTime - voteSiteTime) > 0) {
922+ isVoted = true;
923+ }else {
924+ try
925+ {
926+ //https://l2network.eu/index.php?a=in&u=TOPLIST_USERNAME&id=VOTER_USERNAME_OR_ID
927+ URL url = new URL(String.format("https://l2network.eu/index.php?a=in&u=%s&id=%s",Config.VOTE_NETWORK_USER_NAME,AccountName));
928+ try
929+ {
930+ Desktop.getDesktop().browse(url.toURI());
931+ }
932+ catch (IOException | URISyntaxException e)
933+ {
934+ e.printStackTrace();
935+ }
936+ }
937+ catch (MalformedURLException e)
938+ {
939+ e.printStackTrace();
940+ }
941+ }*/
942+ //second method without date response
943+ response = getResponse(getIndividualUrl(ordinal,ip,null),ordinal);
944+ isVoted = (Integer.parseInt(response) == 1);
945+ voteSiteTime = serverVoteTime = VoteUtil.getTimeVotingSite(ordinal);
946+ serverVoteTime = VoteUtil.getTimeVotingSite(ordinal);
947+ break;
948+
949+ case 6:
950+ response = getResponse(getIndividualUrl(ordinal,ip,null),ordinal);
951+ isVoted = Boolean.parseBoolean(VoteUtil.between("\"voted\":", response, ",\"voteTime\""));
952+ if(isVoted) {
953+ try
954+ {
955+ voteSiteTime = format.parse(VoteUtil.between("\"voteTime\":\"", response, "\",\"l2topserversServerTime\"")).getTime();
956+ serverVoteTime = VoteUtil.getTimeVotingSite(ordinal);
957+ }
958+ catch (ParseException e)
959+ {
960+ e.printStackTrace();
961+ }
962+
963+ }
964+ break;
965+
966+ case 7:
967+ response = getResponse(getIndividualUrl(ordinal,ip,null),ordinal);
968+ isVoted = Integer.parseInt(VoteUtil.between("\"status\":\"", response, "\",\"server_time\"")) == 1;
969+ if(isVoted) {
970+ try
971+ {
972+ voteSiteTime = format.parse(VoteUtil.between("\"date\":\"", response, "\",\"status\"")).getTime();
973+ serverVoteTime = VoteUtil.getTimeVotingSite(ordinal);
974+ }
975+ catch (ParseException e)
976+ {
977+ e.printStackTrace();
978+ }
979+ }
980+ break;
981+
982+ case 8:
983+ response = getResponse(getIndividualUrl(ordinal,ip,null),ordinal);
984+ isVoted = Boolean.parseBoolean(VoteUtil.between("\"is_voted\":", response, ",\"vote_time\""));
985+ if(isVoted) {
986+ try
987+ {
988+ voteSiteTime = (Long.parseLong(VoteUtil.between("\"vote_time\":", response, ",\"server_time\"")))*1000;
989+ serverVoteTime = VoteUtil.getTimeVotingSite(ordinal);
990+ }
991+ catch (NumberFormatException e)
992+ {
993+ // TODO Auto-generated catch block
994+ e.printStackTrace();
995+ }
996+ }
997+ break;
998+
999+ case 9:
1000+ response = getResponse(getIndividualUrl(ordinal,ip,null),ordinal);
1001+ isVoted = Boolean.parseBoolean(VoteUtil.between("\"isVoted\": ", response, ",\"voteTime\""));
1002+ if(isVoted) {
1003+ voteSiteTime = Long.parseLong(VoteUtil.between("\"voteTime\": \"", response, "\",\"serverTime\""));
1004+ serverVoteTime = VoteUtil.getTimeVotingSite(ordinal);
1005+ }
1006+ break;
1007+
1008+ case 10:
1009+ response = getResponse(getIndividualUrl(ordinal,ip,null),ordinal);
1010+ isVoted = Boolean.parseBoolean(response);
1011+ if(isVoted) {
1012+ voteSiteTime = VoteUtil.getTimeVotingSite(ordinal);
1013+ serverVoteTime = VoteUtil.getTimeVotingSite(ordinal);
1014+ }
1015+ break;
1016+
1017+ }
1018+
1019+ ivr.setIsVoted(isVoted);
1020+ ivr.setServerVoteTime(serverVoteTime);
1021+ ivr.setVoteSiteTime(voteSiteTime);
1022+ return ivr;
1023+ }
1024+
1025+ public int getGlobalVotesResponse(int ordinal)
1026+ {
1027+
1028+ String response = "";
1029+ int totalVotes = 0;
1030+
1031+ switch(ordinal)
1032+ {
1033+ case 0:
1034+ response = getResponse(getGlobalUrl(ordinal), ordinal);
1035+ response = VoteUtil.between("\"getVotes\":",response,"}");
1036+ totalVotes = (!"".equals(response)) ? Integer.parseInt(response) : -1;
1037+ break;
1038+
1039+ case 1:
1040+ response = getResponse(getGlobalUrl(ordinal), ordinal);
1041+ response = VoteUtil.between("[server_votes]=>",response.replace(" ", ""),"[server_rank]");
1042+ totalVotes = (!"".equals(response)) ? Integer.parseInt(response) : -1;
1043+ break;
1044+
1045+ case 2:
1046+ response = getResponse(getGlobalUrl(ordinal), ordinal);
1047+ totalVotes = (!"".equals(response)) ? Integer.parseInt(response) : -1;
1048+ break;
1049+
1050+ case 3:
1051+ response = VoteUtil.getResponse(getGlobalUrl(ordinal), ordinal);
1052+ response = VoteUtil.between("Votes:</th><th><a class='votes'>", response, "</a></th></tr><tr><th>Clicks:");
1053+ totalVotes = (!"".equals(response)) ? Integer.parseInt(response) : -1;
1054+ break;
1055+
1056+ case 4:
1057+ response = getResponse(getGlobalUrl(ordinal), ordinal);
1058+ response = VoteUtil.between("\"totalvotes\":",response,",\"status_code\"");
1059+ totalVotes = (!"".equals(response)) ? Integer.parseInt(response) : -1;
1060+ break;
1061+
1062+ case 5:
1063+ String responseNetwork = getNetWorkResponse(getGlobalUrl(ordinal),ordinal);
1064+ totalVotes = (!"".equals(response)) ? Integer.parseInt(responseNetwork) : -1;
1065+ break;
1066+
1067+ /*case 6:
1068+
1069+ break;*/
1070+
1071+ case 7:
1072+ response = VoteUtil.getResponse(getGlobalUrl(ordinal), ordinal);
1073+ response = VoteUtil.between("nicas:</b> ", response, "<br /><br />");
1074+ totalVotes = (!"".equals(response)) ? Integer.parseInt(response) : -1;
1075+ break;
1076+
1077+ case 8:
1078+ response = getResponse(getGlobalUrl(ordinal), ordinal);
1079+ response = VoteUtil.between("\"monthly_votes\":",response,"}}");
1080+ totalVotes = (!"".equals(response)) ? Integer.parseInt(response) : -1;
1081+ break;
1082+
1083+ case 9:
1084+ response = getResponse(getGlobalUrl(ordinal), ordinal);
1085+ response = VoteUtil.between("\"totalVotes\":\"", response, "\",\"serverRank\"");
1086+ totalVotes = (!"".equals(response)) ? Integer.parseInt(response) : -1;
1087+ break;
1088+
1089+ case 10:
1090+ response = getResponse(getGlobalUrl(ordinal), ordinal);
1091+ totalVotes = (!"".equals(response)) ? Integer.parseInt(response) : -1;
1092+ break;
1093+ }
1094+
1095+ return totalVotes;
1096+ }
1097+
1098+ public static String getIndividualUrl(int ordinal,String ip,String AccountName)
1099+ {
1100+ String url = "";
1101+ ip = votesystem().getTestIp();
1102+ switch(ordinal) {
1103+ case 0:
1104+ //l2.topgameserver.net
1105+ url = String.format("%sAPI_KEY=%s/getData/%s", votesystem().getVoteLinkTgs(), votesystem().getTgsApiKey(),ip);
1106+ break;
1107+
1108+ case 1:
1109+ //itopz.com
1110+ url = String.format("%s%s/%s/%s", votesystem().getVoteLinkItopz(),votesystem().getItopzZpiKey(),votesystem().getItopzSrvId(),ip);
1111+ break;
1112+
1113+ case 2:
1114+ //l2top.co
1115+ url = String.format("%sVoteCheck.php?id=%s&ip=%s", votesystem().getVoteLinkTopCo(),votesystem().getTopCoSrvId(),ip);
1116+ break;
1117+
1118+ case 3:
1119+ //l2votes.com
1120+ url = String.format("%sapi.php?apiKey=%s&ip=%s", votesystem().getVoteLinkVts(),votesystem().getVtsApiKey(),ip);
1121+ break;
1122+
1123+ case 4:
1124+ //hopzone.net
1125+ url = String.format("%svote?token=%s&ip_address=%s",votesystem().getVoteLinkHz(),votesystem().getHzApiKey(),ip);
1126+ break;
1127+
1128+ case 5:
1129+ //l2network.eu
1130+ //first Method
1131+ //url = String.format("apiKey=%s&type=%s&player=%s",Config.VOTE_NETWORK_API_KEY,2,AccountName);
1132+ //second method
1133+ url = String.format("https://l2network.eu/index.php?a=in&u=%s&ipc=%s", votesystem().getVoteNetworkUserName(),ip);
1134+ break;
1135+
1136+ case 6:
1137+ //l2topservers.com
1138+ url = String.format("%stoken=%s&ip=%s", votesystem().getVoteLinkTss(),votesystem().getTssApiToken(),ip);
1139+ break;
1140+
1141+ case 7:
1142+ //top.l2jbrasil.com
1143+ url = String.format("%susername=%s&ip=%s&type=json",votesystem().getBrasilVoteLink(),votesystem().getBrasilUserName(),ip);
1144+ break;
1145+
1146+ case 8:
1147+ //mmotop
1148+ url = String.format("%s%s/%s", votesystem().getVoteLinkMmotop(),votesystem().getMmotopApiKey(),ip);
1149+ break;
1150+
1151+ case 9:
1152+ //topzone.com
1153+ url = String.format("%svote?token=%s&ip=%s", votesystem().getVoteLinkTz(),votesystem().getTzApiKey(),ip);
1154+ break;
1155+
1156+ case 10:
1157+ //l2servers.com
1158+ url = String.format("%scheckip.php?hash=%s&server_id=%s&ip=%s", votesystem().getVoteLinkServers(),votesystem().getServersHashCode(),votesystem().getServersSrvId(),ip);
1159+ break;
1160+ }
1161+
1162+ return url;
1163+ }
1164+
1165+ public String getGlobalUrl(int ordinal)
1166+ {
1167+ String url = "";
1168+
1169+ switch(ordinal) {
1170+ case 0:
1171+ //l2.topgameserver.net
1172+ url = String.format("%sAPI_KEY=%s/getData", votesystem().getVoteLinkTgs(),votesystem().getTgsApiKey());
1173+ break;
1174+
1175+ case 1:
1176+ //itopz.com
1177+ url = String.format("%s%s/%s", votesystem().getVoteLinkItopz(),votesystem().getItopzZpiKey(),votesystem().getItopzSrvId());
1178+ break;
1179+
1180+ case 2:
1181+ //l2top.co
1182+ url = String.format("%sVoteCheck_Total.php?id=%s", votesystem().getVoteLinkTopCo(),votesystem().getTopCoSrvId());
1183+ break;
1184+
1185+ case 3:
1186+ //l2votes.com
1187+ url = String.format("%sserverPage.php?sid=%s",votesystem().getVoteLinkVts(),votesystem().getVtsSid());
1188+ break;
1189+
1190+ case 4:
1191+ //hopzone.net
1192+ url = String.format("%svotes?token=%s", votesystem().getVoteLinkTz(),votesystem().getHzApiKey());
1193+ break;
1194+
1195+ case 5:
1196+ //l2network.eu
1197+ url = String.format("apiKey=%s&type=%s&player=",votesystem().getVoteNetworkApiKey(),1);
1198+ break;
1199+
1200+ /*case 6:
1201+ //l2topservers
1202+ return String.format("%sAPI_KEY=%s/getData", Config.VOTE_LINK_TGS,Config.TGS_API_KEY);
1203+ break;*/
1204+
1205+ case 7:
1206+ //top.l2jbrasil.com
1207+ url = String.format("https://top.l2jbrasil.com/index.php?a=stats&u=%s", votesystem().getBrasilUserName());
1208+ break;
1209+
1210+ case 8:
1211+ //mmotop.eu/l2/
1212+ url = String.format("%s%s/info/", votesystem().getVoteLinkMmotop(),votesystem().getMmotopApiKey());
1213+ break;
1214+
1215+ case 9:
1216+ //l2topzone.com
1217+ url = String.format("%sserver_%s/getServerData", votesystem().getVoteLinkTz(),votesystem().getTzApiKey());
1218+ break;
1219+
1220+ case 10:
1221+ //l2servers.com
1222+ url = String.format("%syearlyvotes.php?server_id=%s", votesystem().getVoteLinkServers(),votesystem().getServersSrvId());
1223+ break;
1224+ }
1225+
1226+ return url;
1227+ }
1228+}
1229diff --git a/src/main/java/com/l2jserver/gameserver/votesystem/Handler/voteManager.java b/src/main/java/com/l2jserver/gameserver/votesystem/Handler/voteManager.java
1230new file mode 100644
1231index 0000000..c7a1fc8
1232--- /dev/null
1233+++ b/src/main/java/com/l2jserver/gameserver/votesystem/Handler/voteManager.java
1234@@ -0,0 +1,377 @@
1235+/*
1236+ * To change this license header, choose License Headers in Project Properties.
1237+ * To change this template file, choose Tools | Templates
1238+ * and open the template in the editor.
1239+ */
1240+package com.l2jserver.gameserver.votesystem.Handler;
1241+
1242+import com.l2jserver.gameserver.ThreadPoolManager;
1243+import static com.l2jserver.gameserver.config.Configuration.votesystem;
1244+import com.l2jserver.gameserver.model.L2World;
1245+import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
1246+import com.l2jserver.gameserver.network.L2GameClient;
1247+import com.l2jserver.gameserver.network.SystemMessageId;
1248+import com.l2jserver.gameserver.network.serverpackets.ItemList;
1249+import com.l2jserver.gameserver.network.serverpackets.SystemMessage;
1250+import com.l2jserver.gameserver.util.Broadcast;
1251+import com.l2jserver.gameserver.votesystem.DB.globalVoteDB;
1252+import com.l2jserver.gameserver.votesystem.DB.individualVoteDB;
1253+import com.l2jserver.gameserver.votesystem.Enum.voteSite;
1254+import static com.l2jserver.gameserver.votesystem.Handler.voteHandler.getIndividualVoteResponse;
1255+import com.l2jserver.gameserver.votesystem.Model.Reward;
1256+import com.l2jserver.gameserver.votesystem.Model.globalVote;
1257+import com.l2jserver.gameserver.votesystem.Model.individualVote;
1258+import com.l2jserver.gameserver.votesystem.Model.individualVoteResponse;
1259+import com.l2jserver.gameserver.votesystem.VoteUtil.VoteSiteXml;
1260+import com.l2jserver.gameserver.votesystem.VoteUtil.VoteUtil;
1261+import java.util.HashSet;
1262+import java.util.Iterator;
1263+import java.util.Map;
1264+import java.util.Optional;
1265+import java.util.Set;
1266+import java.util.concurrent.ConcurrentHashMap;
1267+import java.util.concurrent.ScheduledFuture;
1268+import java.util.stream.Collectors;
1269+
1270+/**
1271+ *
1272+ * @author escor
1273+ */
1274+public final class voteManager extends voteHandler{
1275+ private ScheduledFuture<?> _saveGlobalVotes;
1276+ private ScheduledFuture<?> _updateIndividualVotes;
1277+ private ScheduledFuture<?> _cleanInnecesaryIndividualVotes;
1278+ private ScheduledFuture<?> _autoGlobalVotesReward;
1279+
1280+ private HashSet<individualVote> _votes;
1281+ private Map<String,individualVote[]> _foundVoters;
1282+ private globalVote[] _globalVotes = new globalVote[voteSite.values().length];
1283+
1284+ public voteManager() {
1285+ loadVotes();
1286+ loadGlobalVotes();
1287+ _foundVoters = new ConcurrentHashMap<>();
1288+ checkAllResponseGlobalVotes();
1289+ stopAutoTasks();
1290+
1291+ if(votesystem().getEnableIndividualVote() && votesystem().getEnableVoteSystem()) {
1292+ _cleanInnecesaryIndividualVotes = ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(new AutoCleanInnecesaryIndividualVotesTask(), 30000, votesystem().getNextTimeToAutoCleanInnecesaryVotes());
1293+ _updateIndividualVotes = ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(new AutoUpdateIndividualVotesTask(), 30000, votesystem().getNextTimeToAutoUpdateIndividualVotes());
1294+ }
1295+ if(votesystem().getEnableGlobalVote() && votesystem().getEnableVoteSystem()) {
1296+ _autoGlobalVotesReward = ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(new AutoGlobalVoteRewardTask(), 10000, votesystem().getNextTimeToCheckAutoGlobalVotesReward());
1297+ _saveGlobalVotes = ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(new AutoSaveGlobalVotesTask(), 30000, votesystem().getNextTimeToAutoUpdateTotalVote());
1298+ }
1299+ }
1300+
1301+ private void stopAutoTasks() {
1302+ if(_saveGlobalVotes != null) {
1303+ _saveGlobalVotes.cancel(true);
1304+ _saveGlobalVotes = null;
1305+ }
1306+ if(_updateIndividualVotes != null) {
1307+ _updateIndividualVotes.cancel(true);
1308+ _updateIndividualVotes = null;
1309+ }
1310+ if(_cleanInnecesaryIndividualVotes != null) {
1311+ _cleanInnecesaryIndividualVotes.cancel(true);
1312+ _cleanInnecesaryIndividualVotes = null;
1313+ }
1314+ if(_autoGlobalVotesReward != null) {
1315+ _autoGlobalVotesReward.cancel(true);
1316+ _autoGlobalVotesReward = null;
1317+ }
1318+ }
1319+
1320+ public void getReward(L2PcInstance activeChar, int ordinalSite) {
1321+ String ip = existIp(activeChar);
1322+ if(ip == null) {
1323+ return;
1324+ }
1325+ individualVoteResponse ivr = getIndividualVoteResponse(ordinalSite,ip,activeChar.getAccountName());
1326+ if(!ivr.getIsVoted()) {
1327+ activeChar.sendMessage(String.format("You haven't vote on %s yet!", VoteSiteXml.getInstance().getSiteName(ordinalSite)));
1328+ return;
1329+ }
1330+ individualVote iv = new individualVote(ip,ivr.getServerVoteTime(),ivr.getVoteSiteTime(),ordinalSite,true);
1331+ if(!checkIndividualAvailableVote(activeChar,ordinalSite)) {
1332+ activeChar.sendMessage(String.format("You can get the reward again on %s at %s", VoteSiteXml.getInstance().getSiteName(ordinalSite),getTimeRemainingWithSampleFormat(activeChar,ordinalSite)));
1333+ return;
1334+ }
1335+ _votes.add(iv);
1336+ individualVote[] aiv;
1337+ if(!_foundVoters.containsKey(ip)) {
1338+ Set<individualVote> ivts = _votes.stream().filter(st -> st.getVoterIp().equalsIgnoreCase(iv.getVoterIp())).collect(Collectors.toSet());
1339+ aiv = new individualVote[voteSite.values().length];
1340+ if(ivts.size()>1) {
1341+ ivts.forEach(x -> {
1342+ aiv[x.getVoteSite()] = x;
1343+ });
1344+ _foundVoters.put(ip, aiv);
1345+ }else {
1346+ aiv[ordinalSite] = iv;
1347+ _foundVoters.put(ip, aiv);
1348+ }
1349+ }else {
1350+ aiv = _foundVoters.get(ip);
1351+ aiv[ordinalSite] = iv;
1352+ _foundVoters.replace(ip, aiv);
1353+ }
1354+ for(Reward reward : VoteSiteXml.getInstance().getRewards(ordinalSite)) {
1355+ activeChar.getInventory().addItem("VoteSystem", reward.getItemId(), reward.getItemCount(), activeChar, null);
1356+ activeChar.sendPacket(SystemMessage.getSystemMessage(SystemMessageId.EARNED_S2_S1_S).addItemName(reward.getItemId()).addInt(reward.getItemCount()));
1357+ }
1358+ activeChar.sendMessage(String.format("%s: Thank you for voting for our server, your reward has been delivered.", VoteSiteXml.getInstance().getSiteName(ordinalSite)));
1359+ activeChar.sendPacket(new ItemList(activeChar, true));
1360+
1361+ }
1362+
1363+ public boolean checkIndividualAvailableVote(L2PcInstance activeChar, int ordinalSite) {
1364+ String ip = existIp(activeChar);
1365+ //If player has registered almost 1 vote
1366+ if(_foundVoters.containsKey(ip)) {
1367+ individualVote[] ivs=_foundVoters.get(ip);
1368+ if(ivs[ordinalSite] == null)
1369+ return true;
1370+ if(ivs[ordinalSite] != null) {
1371+ individualVote iv = ivs[ordinalSite];
1372+ if(getTimeRemaining(iv)<0 || !iv.getAlreadyRewarded()) {
1373+ return true;
1374+ }
1375+ }
1376+ }
1377+
1378+ //if the player hasn't registered a vote or after the initial charge
1379+ Optional<individualVote> iv = _votes.stream().filter(s -> s.getVoterIp().equalsIgnoreCase(ip)).filter(y -> y.getVoteSite() == ordinalSite).findFirst();
1380+ if(iv.isEmpty()) {
1381+ return true;
1382+ }
1383+ return getTimeRemaining(iv.get()) <0 || !iv.get().getAlreadyRewarded();
1384+
1385+ }
1386+
1387+ public long getTimeRemaining(individualVote iv) {
1388+ long timeRemaining = 0L;
1389+ timeRemaining = iv.getVotingTimeSite() + votesystem().getIntervalToNextVote() - (System.currentTimeMillis() - (System.currentTimeMillis() - VoteUtil.getTimeVotingSite(iv.getVoteSite())));
1390+ return timeRemaining;
1391+ }
1392+
1393+ public String getTimeRemainingWithSampleFormat(L2PcInstance activeChar, int ordinalSite) {
1394+ String ip = existIp(activeChar);
1395+ String timeRemainingWithSampleFormat ="";
1396+ if(_foundVoters.containsKey(ip)) {
1397+ individualVote[] ivs=_foundVoters.get(ip);
1398+ if(ivs[ordinalSite] != null) {
1399+ individualVote iv = ivs[ordinalSite];
1400+ long timeRemaining = getTimeRemaining(iv);
1401+ if(timeRemaining>0 && iv.getAlreadyRewarded()) {
1402+ timeRemainingWithSampleFormat = CalculateTimeRemainingWithSampleDateFormat(timeRemaining);
1403+ return timeRemainingWithSampleFormat;
1404+ }
1405+ }
1406+ }
1407+ Optional<individualVote> iv = _votes.stream().filter(s -> s.getVoterIp().equalsIgnoreCase(ip)).filter(y -> y.getVoteSite() == ordinalSite).findFirst();
1408+ if(!iv.isEmpty()) {
1409+ if(getTimeRemaining(iv.get()) > 0 && iv.get().getAlreadyRewarded()) {
1410+ long timeRemaining = getTimeRemaining(iv.get());
1411+ timeRemainingWithSampleFormat = CalculateTimeRemainingWithSampleDateFormat(timeRemaining);
1412+ return timeRemainingWithSampleFormat;
1413+ }
1414+ }
1415+
1416+ return timeRemainingWithSampleFormat;
1417+ }
1418+
1419+ public String CalculateTimeRemainingWithSampleDateFormat(long timeRemaining) {
1420+ long t = timeRemaining/1000;
1421+ int hours = Math.round((t/3600%24));
1422+ int minutes = Math.round((t/60)%60);
1423+ int seconds = Math.round(t%60);
1424+ return String.format("%sH:%sm:%ss", hours,minutes,seconds);
1425+ }
1426+
1427+ public String existIp(L2PcInstance activeChar) {
1428+
1429+ L2GameClient client = activeChar.getClient();
1430+ if(client.getConnection() != null && client.getActiveChar()!= null && !client.isDetached()) {
1431+ try
1432+ {
1433+ return client.getConnection().getInetAddress().getHostAddress();
1434+ }
1435+ catch (Exception e)
1436+ {
1437+ e.printStackTrace();
1438+ }
1439+ }
1440+ return null;
1441+
1442+ }
1443+
1444+ public final void loadVotes() {
1445+ _votes = individualVoteDB.getInstance().getVotesDB();
1446+ }
1447+ protected void loadGlobalVotes(){
1448+ _globalVotes = globalVoteDB.getInstance().getGlobalVotes();
1449+ }
1450+ protected void saveVotes() {
1451+ individualVoteDB.getInstance().SaveVotes(_votes);
1452+ }
1453+
1454+ protected void AutoGlobalVoteReward() {
1455+ HashSet<String> ipList = new HashSet<>();
1456+ for(voteSite vs : voteSite.values()) {
1457+ new Thread(new Runnable() {
1458+ @Override
1459+ public void run() {
1460+ checkNewUpdate(vs.ordinal());
1461+ if(_globalVotes[vs.ordinal()].getCurrentVotes() >= _globalVotes[vs.ordinal()].getVotesLastReward() + votesystem().getGlobalVotesAmountToNextReward()) {
1462+ _globalVotes[vs.ordinal()].setVotesLastReward(_globalVotes[vs.ordinal()].getVotesLastReward() + votesystem().getGlobalVotesAmountToNextReward());
1463+ for(L2PcInstance activeChar : L2World.getInstance().getPlayers()) {
1464+ String ip = existIp(activeChar);
1465+ if(ip == null) {
1466+ continue;
1467+ }
1468+ if(ipList.contains(ip)) {
1469+ continue;
1470+ }
1471+ for(Reward reward : VoteSiteXml.getInstance().getRewards(11)) {
1472+ activeChar.getInventory().addItem("VoteSystem: ", reward.getItemId(), reward.getItemCount(), activeChar, null);
1473+ activeChar.sendPacket(SystemMessage.getSystemMessage(SystemMessageId.EARNED_S2_S1_S).addItemName(reward.getItemId()).addInt(reward.getItemCount()));
1474+ }
1475+ ipList.add(ip);
1476+ activeChar.sendPacket(new ItemList(activeChar, true));
1477+ }
1478+ Broadcast.toAllOnlinePlayers(VoteUtil.Sites[vs.ordinal()]+": All players has been rewarded, please check your inventory", true);
1479+ }else {
1480+ String encourage ="";
1481+ int nextReward = _globalVotes[vs.ordinal()].getVotesLastReward() + votesystem().getGlobalVotesAmountToNextReward();
1482+ encourage = String.format("Vote for %s current Votes: %s, next quantity of votes to reward : %s, need votes to next reward: %s", VoteUtil.Sites[vs.ordinal()], _globalVotes[vs.ordinal()].getCurrentVotes(),nextReward, nextReward-_globalVotes[vs.ordinal()].getCurrentVotes() );
1483+ Broadcast.toAllOnlinePlayers(encourage, true);
1484+ }
1485+ }
1486+ }).start();
1487+
1488+ }
1489+ }
1490+
1491+ protected void AutoSaveGlobalVotes() {
1492+ globalVoteDB.getInstance().saveGlobalVotes(_globalVotes);
1493+ }
1494+
1495+ protected synchronized void AutoUpdateIndividualVotes() {
1496+ individualVoteDB.getInstance().SaveVotes(_votes);
1497+ }
1498+
1499+ protected synchronized void AutoCleanInnecesaryIndividualVotes() {
1500+ HashSet<individualVote> removeVotes= new HashSet<>();
1501+ Iterator<individualVote> iv = _votes.iterator();
1502+ while(iv.hasNext()){
1503+ individualVote individualvote = iv.next();
1504+ if(getTimeRemaining(individualvote) < 0) {
1505+ removeVotes.add(individualvote);
1506+ iv.remove();
1507+ if(_foundVoters.containsKey(individualvote.getVoterIp())) {
1508+ if(_foundVoters.get(individualvote.getVoterIp())[individualvote.getVoteSite()] != null) {
1509+ _foundVoters.get(individualvote.getVoterIp())[individualvote.getVoteSite()] = null;
1510+ }
1511+ }
1512+ }
1513+ }
1514+ individualVoteDB.getInstance().DeleteVotes(removeVotes);
1515+ }
1516+
1517+ public void checkAllResponseGlobalVotes() {
1518+ for(voteSite vs : voteSite.values()) {
1519+ new Thread(()-> {
1520+ checkNewUpdate(vs.ordinal());
1521+ });
1522+ }
1523+ }
1524+
1525+ public void checkNewUpdate(int ordinalSite) {
1526+ int globalVotesResponse = getGlobalVotesResponse(ordinalSite);
1527+ if(globalVotesResponse == -1) {
1528+ return;
1529+ }
1530+ _globalVotes[ordinalSite].setCurrentVotes(globalVotesResponse);
1531+ int last = globalVotesResponse - votesystem().getGlobalVotesAmountToNextReward();
1532+ if(last <0 ) {
1533+ _globalVotes[ordinalSite].setVotesLastReward(0);
1534+ return;
1535+ }
1536+ if((_globalVotes[ordinalSite].getVotesLastReward() + votesystem().getGlobalVotesAmountToNextReward()) < globalVotesResponse) {
1537+ _globalVotes[ordinalSite].setVotesLastReward(globalVotesResponse);
1538+ return;
1539+ }
1540+ }
1541+
1542+ public void Shutdown() {
1543+ AutoSaveGlobalVotes();
1544+ AutoCleanInnecesaryIndividualVotes();
1545+ AutoUpdateIndividualVotes();
1546+ }
1547+
1548+ protected class AutoGlobalVoteRewardTask implements Runnable {
1549+
1550+ /* (non-Javadoc)
1551+ * @see java.lang.Runnable#run()
1552+ */
1553+ @Override
1554+ public void run()
1555+ {
1556+ AutoGlobalVoteReward();
1557+
1558+ }
1559+
1560+ }
1561+
1562+ protected class AutoSaveGlobalVotesTask implements Runnable {
1563+
1564+ /* (non-Javadoc)
1565+ * @see java.lang.Runnable#run()
1566+ */
1567+ @Override
1568+ public void run()
1569+ {
1570+ AutoSaveGlobalVotes();
1571+
1572+ }
1573+
1574+ }
1575+
1576+ protected class AutoUpdateIndividualVotesTask implements Runnable {
1577+
1578+ /* (non-Javadoc)
1579+ * @see java.lang.Runnable#run()
1580+ */
1581+ @Override
1582+ public void run()
1583+ {
1584+ AutoUpdateIndividualVotes();
1585+
1586+ }
1587+
1588+ }
1589+
1590+ protected class AutoCleanInnecesaryIndividualVotesTask implements Runnable {
1591+
1592+ /* (non-Javadoc)
1593+ * @see java.lang.Runnable#run()
1594+ */
1595+ @Override
1596+ public void run()
1597+ {
1598+ AutoCleanInnecesaryIndividualVotes();
1599+
1600+ }
1601+
1602+ }
1603+
1604+ public static voteManager getInatance() {
1605+ return SingleHolder.INSTANCE;
1606+ }
1607+
1608+ private static class SingleHolder {
1609+ protected static final voteManager INSTANCE = new voteManager();
1610+ }
1611+}
1612diff --git a/src/main/java/com/l2jserver/gameserver/votesystem/Model/Reward.java b/src/main/java/com/l2jserver/gameserver/votesystem/Model/Reward.java
1613new file mode 100644
1614index 0000000..227264a
1615--- /dev/null
1616+++ b/src/main/java/com/l2jserver/gameserver/votesystem/Model/Reward.java
1617@@ -0,0 +1,36 @@
1618+/*
1619+ * To change this license header, choose License Headers in Project Properties.
1620+ * To change this template file, choose Tools | Templates
1621+ * and open the template in the editor.
1622+ */
1623+package com.l2jserver.gameserver.votesystem.Model;
1624+
1625+import com.l2jserver.gameserver.model.StatsSet;
1626+
1627+/**
1628+ *
1629+ * @author escor
1630+ */
1631+public class Reward {
1632+ private int _itemId;
1633+ private int _itemCount;
1634+
1635+ public Reward(StatsSet set)
1636+ {
1637+ _itemId = set.getInt("itemId");
1638+ _itemCount = set.getInt("itemCount");
1639+ }
1640+
1641+ public void setItemId(int itemId) {
1642+ _itemId = itemId;
1643+ }
1644+ public void setItemCount(int itemCount) {
1645+ _itemCount = itemCount;
1646+ }
1647+ public int getItemId() {
1648+ return _itemId;
1649+ }
1650+ public int getItemCount() {
1651+ return _itemCount;
1652+ }
1653+}
1654diff --git a/src/main/java/com/l2jserver/gameserver/votesystem/Model/VoteSite.java b/src/main/java/com/l2jserver/gameserver/votesystem/Model/VoteSite.java
1655new file mode 100644
1656index 0000000..b868be9
1657--- /dev/null
1658+++ b/src/main/java/com/l2jserver/gameserver/votesystem/Model/VoteSite.java
1659@@ -0,0 +1,42 @@
1660+package com.l2jserver.gameserver.votesystem.Model;
1661+
1662+import java.util.ArrayList;
1663+import java.util.List;
1664+
1665+/*
1666+ * To change this license header, choose License Headers in Project Properties.
1667+ * To change this template file, choose Tools | Templates
1668+ * and open the template in the editor.
1669+ */
1670+
1671+/**
1672+ *
1673+ * @author escor
1674+ */
1675+public class VoteSite {
1676+ private int _siteOrdinal;
1677+ private String _siteName;
1678+ private List<Reward> _rewards = new ArrayList<>();
1679+ public VoteSite() {
1680+
1681+ }
1682+ public void setSiteOrdinal(int siteOrdinal) {
1683+ _siteOrdinal = siteOrdinal;
1684+ }
1685+ public void setSiteName(String siteName) {
1686+ _siteName = siteName;
1687+ }
1688+ public void setRewardList(List<Reward> rewards) {
1689+ for(Reward r : rewards)
1690+ _rewards.add(r);
1691+ }
1692+ public int getSiteOrdinal() {
1693+ return _siteOrdinal;
1694+ }
1695+ public String getSiteName() {
1696+ return _siteName;
1697+ }
1698+ public List<Reward> getRewardList(){
1699+ return _rewards;
1700+ }
1701+}
1702diff --git a/src/main/java/com/l2jserver/gameserver/votesystem/Model/globalVote.java b/src/main/java/com/l2jserver/gameserver/votesystem/Model/globalVote.java
1703new file mode 100644
1704index 0000000..357b084
1705--- /dev/null
1706+++ b/src/main/java/com/l2jserver/gameserver/votesystem/Model/globalVote.java
1707@@ -0,0 +1,48 @@
1708+/*
1709+ * To change this license header, choose License Headers in Project Properties.
1710+ * To change this template file, choose Tools | Templates
1711+ * and open the template in the editor.
1712+ */
1713+package com.l2jserver.gameserver.votesystem.Model;
1714+
1715+/**
1716+ *
1717+ * @author escor
1718+ */
1719+public class globalVote {
1720+ private int _voteSite;
1721+ private int _votesLastReward;
1722+ private int _currentVotes;
1723+ public globalVote() {
1724+
1725+ }
1726+
1727+ public globalVote(int voteSite, int votesLastReward) {
1728+ _voteSite = voteSite;
1729+ _votesLastReward = votesLastReward;
1730+ }
1731+
1732+ public void setVoteSite(int voteSite) {
1733+ _voteSite = voteSite;
1734+ }
1735+
1736+ public void setVotesLastReward(int votesLastReward) {
1737+ _votesLastReward = votesLastReward;
1738+ }
1739+
1740+ public void setCurrentVotes(int currentVotes) {
1741+ _currentVotes = currentVotes;
1742+ }
1743+
1744+ public int getVoyeSite() {
1745+ return _voteSite;
1746+ }
1747+
1748+ public int getVotesLastReward() {
1749+ return _votesLastReward;
1750+ }
1751+
1752+ public int getCurrentVotes() {
1753+ return _currentVotes;
1754+ }
1755+}
1756diff --git a/src/main/java/com/l2jserver/gameserver/votesystem/Model/individualVote.java b/src/main/java/com/l2jserver/gameserver/votesystem/Model/individualVote.java
1757new file mode 100644
1758index 0000000..ca309f1
1759--- /dev/null
1760+++ b/src/main/java/com/l2jserver/gameserver/votesystem/Model/individualVote.java
1761@@ -0,0 +1,71 @@
1762+/*
1763+ * To change this license header, choose License Headers in Project Properties.
1764+ * To change this template file, choose Tools | Templates
1765+ * and open the template in the editor.
1766+ */
1767+package com.l2jserver.gameserver.votesystem.Model;
1768+
1769+/**
1770+ *
1771+ * @author escor
1772+ */
1773+public class individualVote {
1774+ private String _voterIp;
1775+ private long _serverVotingTime;
1776+ private long _votingTimeSite;
1777+ private int _voteSite;
1778+ private boolean _alreadyRewarded;
1779+
1780+
1781+ public individualVote(String voterIp, long serverVotingTime, long votingTimeSite, int voteSite, boolean alreadyRewarded){
1782+ _voterIp = voterIp;
1783+ _serverVotingTime = serverVotingTime;
1784+ _votingTimeSite = votingTimeSite;
1785+ _voteSite = voteSite;
1786+ _alreadyRewarded = alreadyRewarded;
1787+ }
1788+
1789+ public individualVote(){
1790+
1791+ }
1792+
1793+ public void setVoterIp(String voterIp) {
1794+ _voterIp = voterIp;
1795+ }
1796+
1797+ public void setServerVotingTime(long serverVotingTime) {
1798+ _serverVotingTime = serverVotingTime;
1799+ }
1800+
1801+ public void setVotingTimeSite(long votingTimeSite) {
1802+ _votingTimeSite = votingTimeSite;
1803+ }
1804+
1805+ public void setVoteSite(int voteSite) {
1806+ _voteSite = voteSite;
1807+ }
1808+
1809+ public void setAlreadyRewarded(boolean alreadyRewarded) {
1810+ _alreadyRewarded = alreadyRewarded;
1811+ }
1812+
1813+ public String getVoterIp() {
1814+ return _voterIp;
1815+ }
1816+
1817+ public long getServerVotingTime() {
1818+ return _serverVotingTime;
1819+ }
1820+
1821+ public long getVotingTimeSite() {
1822+ return _votingTimeSite;
1823+ }
1824+
1825+ public int getVoteSite() {
1826+ return _voteSite;
1827+ }
1828+
1829+ public boolean getAlreadyRewarded() {
1830+ return _alreadyRewarded;
1831+ }
1832+}
1833diff --git a/src/main/java/com/l2jserver/gameserver/votesystem/Model/individualVoteResponse.java b/src/main/java/com/l2jserver/gameserver/votesystem/Model/individualVoteResponse.java
1834new file mode 100644
1835index 0000000..c940817
1836--- /dev/null
1837+++ b/src/main/java/com/l2jserver/gameserver/votesystem/Model/individualVoteResponse.java
1838@@ -0,0 +1,40 @@
1839+/*
1840+ * To change this license header, choose License Headers in Project Properties.
1841+ * To change this template file, choose Tools | Templates
1842+ * and open the template in the editor.
1843+ */
1844+package com.l2jserver.gameserver.votesystem.Model;
1845+
1846+/**
1847+ *
1848+ * @author escor
1849+ */
1850+public class individualVoteResponse {
1851+ private boolean _isVoted;
1852+ private long _serverVoteTime;
1853+ private long _voteSiteTime;
1854+
1855+ public individualVoteResponse() {
1856+
1857+ }
1858+
1859+ public void setIsVoted(boolean isVoted) {
1860+ _isVoted = isVoted;
1861+ }
1862+ public void setServerVoteTime(long serverVoteTime) {
1863+ _serverVoteTime = serverVoteTime;
1864+ }
1865+ public void setVoteSiteTime(long voteSiteTime) {
1866+ _voteSiteTime = voteSiteTime;
1867+ }
1868+
1869+ public boolean getIsVoted() {
1870+ return _isVoted;
1871+ }
1872+ public long getServerVoteTime() {
1873+ return _serverVoteTime;
1874+ }
1875+ public long getVoteSiteTime() {
1876+ return _voteSiteTime;
1877+ }
1878+}
1879diff --git a/src/main/java/com/l2jserver/gameserver/votesystem/VoteUtil/VoteSiteXml.java b/src/main/java/com/l2jserver/gameserver/votesystem/VoteUtil/VoteSiteXml.java
1880new file mode 100644
1881index 0000000..3d3e97a
1882--- /dev/null
1883+++ b/src/main/java/com/l2jserver/gameserver/votesystem/VoteUtil/VoteSiteXml.java
1884@@ -0,0 +1,80 @@
1885+/*
1886+ * To change this license header, choose License Headers in Project Properties.
1887+ * To change this template file, choose Tools | Templates
1888+ * and open the template in the editor.
1889+ */
1890+package com.l2jserver.gameserver.votesystem.VoteUtil;
1891+
1892+import com.l2jserver.gameserver.util.IXmlReader;
1893+import com.l2jserver.gameserver.votesystem.Model.Reward;
1894+import com.l2jserver.gameserver.votesystem.Model.VoteSite;
1895+import java.util.Collection;
1896+import java.util.HashMap;
1897+import java.util.Map;
1898+import java.util.logging.Level;
1899+import java.util.logging.Logger;
1900+import org.w3c.dom.Document;
1901+import org.w3c.dom.Node;
1902+
1903+/**
1904+ *
1905+ * @author escor
1906+ */
1907+public class VoteSiteXml implements IXmlReader{
1908+ private static final Logger LOGGER = Logger.getLogger(VoteSiteXml.class.getName());
1909+ private final Map<Integer,VoteSite> _voteSites = new HashMap<>();
1910+
1911+ protected VoteSiteXml() {
1912+ load();
1913+ }
1914+
1915+ @Override
1916+ public synchronized void load()
1917+ {
1918+ parseDatapackFile("data/votesystem.xml");
1919+ LOGGER.log(Level.INFO,"Loaded {} reward sites", _voteSites.size());
1920+ }
1921+
1922+
1923+ @Override
1924+ public void parseDocument(Document doc)
1925+ {
1926+ for(Node n = doc.getFirstChild(); n != null; n = n.getNextSibling()){
1927+ if("list".equalsIgnoreCase(n.getNodeName())){
1928+ for(Node d = n.getFirstChild(); d != null; d = d.getNextSibling()){
1929+ if("votesite".equalsIgnoreCase(d.getNodeName())){
1930+ final VoteSite votesite = new VoteSite();
1931+ votesite.setSiteName(parseString(d.getAttributes(),"name"));
1932+ votesite.setSiteOrdinal(parseInteger(d.getAttributes(),"ordinal"));
1933+ for(Node cd = d.getFirstChild(); cd != null; cd = cd.getNextSibling()){
1934+ for(Node cde = cd.getFirstChild(); cde != null; cde = cde.getNextSibling()){
1935+ if("item".equalsIgnoreCase(cde.getNodeName())){
1936+ votesite.getRewardList().add(new Reward(parseAttributes(cde)));
1937+ _voteSites.put(votesite.getSiteOrdinal(), votesite);
1938+ }
1939+ }
1940+ }
1941+ }
1942+ }
1943+ }
1944+ }
1945+ }
1946+
1947+ public String getSiteName(int ordinal) {
1948+ return _voteSites.get(ordinal).getSiteName();
1949+ }
1950+
1951+ public Collection<Reward> getRewards(int ordinal){
1952+ return _voteSites.get(ordinal).getRewardList();
1953+ }
1954+
1955+ public static final VoteSiteXml getInstance()
1956+ {
1957+ return SingletonHolder.INSTANCE;
1958+ }
1959+
1960+ private static final class SingletonHolder
1961+ {
1962+ protected static final VoteSiteXml INSTANCE = new VoteSiteXml();
1963+ }
1964+}
1965diff --git a/src/main/java/com/l2jserver/gameserver/votesystem/VoteUtil/VoteUtil.java b/src/main/java/com/l2jserver/gameserver/votesystem/VoteUtil/VoteUtil.java
1966new file mode 100644
1967index 0000000..e8f02b7
1968--- /dev/null
1969+++ b/src/main/java/com/l2jserver/gameserver/votesystem/VoteUtil/VoteUtil.java
1970@@ -0,0 +1,117 @@
1971+/*
1972+ * To change this license header, choose License Headers in Project Properties.
1973+ * To change this template file, choose Tools | Templates
1974+ * and open the template in the editor.
1975+ */
1976+package com.l2jserver.gameserver.votesystem.VoteUtil;
1977+
1978+import com.l2jserver.gameserver.votesystem.Enum.voteSite;
1979+import java.io.BufferedReader;
1980+import java.io.InputStreamReader;
1981+import java.net.HttpURLConnection;
1982+import java.net.URL;
1983+import java.time.LocalDateTime;
1984+import java.time.ZoneId;
1985+import java.time.ZonedDateTime;
1986+import java.util.logging.Level;
1987+import java.util.logging.Logger;
1988+
1989+/**
1990+ *
1991+ * @author escor
1992+ */
1993+public class VoteUtil {
1994+ private static final Logger LOGGER = Logger.getLogger(VoteUtil.class.getName());
1995+
1996+ private static String voteTimeZones[] = {
1997+ "topgameserver.net=Europe/Berlin",
1998+ "itopz.com=America/New_York",
1999+ "l2top.co=Europe/London",
2000+ "l2votes.com=GMT",
2001+ "hopzone.net=Europe/Athens",
2002+ "l2network.eu=America/Chicago",
2003+ "l2topservers.com=Europe/Athens",
2004+ "top.l2jbrasil.com=America/Sao_Paulo",
2005+ "mmotop.eu=America/Chicago",
2006+ "l2topzone.com=America/Chicago",
2007+ "l2servers.com=America/Chicago",
2008+ };
2009+
2010+ public static final long getTimeVotingSite(int ordinalSite) {
2011+ LocalDateTime ldt = LocalDateTime.now(ZoneId.of(voteTimeZones[ordinalSite].split("=")[1]));
2012+ ZonedDateTime zdt = ldt.atZone(ZoneId.systemDefault());
2013+ long millis = zdt.toInstant().toEpochMilli();
2014+ return millis;
2015+ }
2016+
2017+ public static final String Sites[] =
2018+ {
2019+ "L2.TopGameServer.net",
2020+ "ITopZ.com",
2021+ "L2Top.co",
2022+ "L2Votes.com",
2023+ "L2.Hopzone.net",
2024+ "L2Network.eu",
2025+ "L2TopServers.com",
2026+ "top.l2jbrasil.com",
2027+ "MMOTOP.eu",
2028+ "L2Topzone.com",
2029+ "L2Servers.com"
2030+ };
2031+
2032+ public static final String getResponse(String Url, int ordinal)
2033+ {
2034+
2035+ try
2036+ {
2037+ int responseCode = 0;
2038+ URL objUrl = new URL(Url);
2039+ HttpURLConnection con = (HttpURLConnection) objUrl.openConnection();
2040+ con.setRequestMethod("GET");
2041+ con.setRequestProperty("User-Agent", "Mozilla/5.0");
2042+ con.setConnectTimeout(5000);
2043+ responseCode = con.getResponseCode();
2044+ if (responseCode == HttpURLConnection.HTTP_OK) {
2045+
2046+ String inputLine;
2047+ StringBuffer response = new StringBuffer();
2048+ BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
2049+ while ((inputLine = in.readLine()) != null) {
2050+ if(ordinal == voteSite.L2VOTES.ordinal()) {
2051+ if(inputLine.contains("Votes:")) {
2052+ response.append(inputLine);
2053+ break;
2054+ }
2055+ }
2056+ if(ordinal == voteSite.TOPL2JBRASIL.ordinal()){
2057+ if(inputLine.contains("<b>Entradas ")) {
2058+ response.append(inputLine);
2059+ break;
2060+ }
2061+ }
2062+ }
2063+ in.close();
2064+ return response.toString();
2065+ }
2066+
2067+ }
2068+ catch (Exception e)
2069+ {
2070+ LOGGER.log(Level.INFO, "{0} Say: An error ocurred: {1}", new Object[]{VoteUtil.Sites[ordinal], e.getMessage()});
2071+ return "";
2072+ }
2073+
2074+ return "";
2075+ }
2076+
2077+ public static final String between(String p1, String str, String p2){
2078+ String returnValue = "";
2079+ int i1 = str.indexOf(p1);
2080+ int i2 = str.indexOf(p2);
2081+ if(i1 != -1 && i2 != -1){
2082+ i1 = i1+p1.length();
2083+ returnValue = str.substring(i1,i2);
2084+ }
2085+ return returnValue;
2086+ }
2087+}
2088diff --git a/src/main/resources/config/votesystem.properties b/src/main/resources/config/votesystem.properties
2089new file mode 100644
2090index 0000000..b2b87e2
2091--- /dev/null
2092+++ b/src/main/resources/config/votesystem.properties
2093@@ -0,0 +1,96 @@
2094+
2095+EnableVoteSystem = True
2096+
2097+EnableGlobalVote = True
2098+
2099+EnableIndividualVote = True
2100+
2101+## Time to Update table totalVotes from DB
2102+NextTimeToAutoUpdateTotalVote = 2
2103+
2104+## Time to update table individualVotes
2105+NextTimeToAutoUpdateIndividualVotes = 2
2106+
2107+NextTimeToAutoCleanInnecesaryVotes = 30
2108+
2109+NextTimeToCheckAutoGlobalVotesReward = 1
2110+
2111+IntervalToNextVote = 12
2112+
2113+GlobalVotesAmountToNextReward = 1
2114+
2115+EnableVotingCommand = True
2116+
2117+VotingCommand = .getreward
2118+
2119+## l2.topgameserver.net
2120+VoteLinkTgs = http://l2.topgameserver.net/lineage/VoteApi/
2121+
2122+TgsApiKey =
2123+
2124+## l2top.co
2125+VoteLinkTopCo = https://l2top.co/reward/
2126+
2127+TopCoSrvId =
2128+
2129+## ITopz.com
2130+VoteLinkItopz = https://itopz.com/check/
2131+
2132+ItopzZpiKey =
2133+
2134+ItopzSrvId =
2135+
2136+## l2votes.com
2137+VoteLinkVts = https://l2votes.com/
2138+
2139+VtsApiKey =
2140+
2141+VtsSid =
2142+
2143+## Hopzone.net
2144+VoteLinkHz = https://api.hopzone.net/lineage2/
2145+
2146+HzApiKey =
2147+
2148+## l2network.eu
2149+VoteNetworkLink = https://l2network.eu/api.php
2150+
2151+VoteNetworkUserName =
2152+
2153+VoteNetworkApiKey =
2154+
2155+## L2TopServer.com
2156+VoteLinkTss = https://l2topservers.com/votes?
2157+
2158+TssApiToken =
2159+
2160+## L2Top.online
2161+##VoteLinkTon = http://l2top.online/avote/
2162+
2163+##TonSrvId =
2164+
2165+## top.l2jbrasil.com
2166+BrasilVoteLink = https://top.l2jbrasil.com/votesystem/index.php?
2167+
2168+BrasilUserName =
2169+
2170+## Mmotop.eu
2171+VoteLinkMmotop = https://mmotop.eu/l2/data/
2172+
2173+MmotopApiKey =
2174+
2175+## L2TopZone.com
2176+VoteLinkTz = https://api.l2topzone.com/v1/
2177+
2178+TzApiKey =
2179+
2180+## L2Servers.com
2181+VoteLinkServers = https://www.l2servers.com/api/
2182+
2183+ServersHashCode =
2184+
2185+ServersSrvId =
2186+
2187
2188============================================= DATAPACK ====================================================
2189diff --git a/.gitignore b/.gitignore
2190index 621983d..e5b5631 100644
2191--- a/.gitignore
2192+++ b/.gitignore
2193@@ -5,3 +5,4 @@
2194 /target/
2195 logs/
2196 test-output/
2197\ No newline at end of file
2198+/nbproject/
2199\ No newline at end of file
2200diff --git a/pom.xml b/pom.xml
2201index 3d571a4..b8022a8 100644
2202--- a/pom.xml
2203+++ b/pom.xml
2204@@ -50,6 +50,24 @@
2205 <version>${mockito.version}</version>
2206 <scope>test</scope>
2207 </dependency>
2208+ <dependency>
2209+ <groupId>org.junit.jupiter</groupId>
2210+ <artifactId>junit-jupiter-api</artifactId>
2211+ <version>5.5.2</version>
2212+ <scope>test</scope>
2213+ </dependency>
2214+ <dependency>
2215+ <groupId>org.junit.jupiter</groupId>
2216+ <artifactId>junit-jupiter-params</artifactId>
2217+ <version>5.5.2</version>
2218+ <scope>test</scope>
2219+ </dependency>
2220+ <dependency>
2221+ <groupId>org.junit.jupiter</groupId>
2222+ <artifactId>junit-jupiter-engine</artifactId>
2223+ <version>5.5.2</version>
2224+ <scope>test</scope>
2225+ </dependency>
2226 </dependencies>
2227 <build>
2228 <plugins>
2229diff --git a/src/main/java/com/l2jserver/datapack/handlers/MasterHandler.java b/src/main/java/com/l2jserver/datapack/handlers/MasterHandler.java
2230index dc4019a..279046c 100644
2231--- a/src/main/java/com/l2jserver/datapack/handlers/MasterHandler.java
2232+++ b/src/main/java/com/l2jserver/datapack/handlers/MasterHandler.java
2233@@ -264,7 +264,9 @@
2234 import com.l2jserver.datapack.handlers.voicedcommandhandlers.Debug;
2235 import com.l2jserver.datapack.handlers.voicedcommandhandlers.Lang;
2236 import com.l2jserver.datapack.handlers.voicedcommandhandlers.StatsVCmd;
2237+import com.l2jserver.datapack.handlers.voicedcommandhandlers.VoteSystem;
2238 import com.l2jserver.datapack.handlers.voicedcommandhandlers.Wedding;
2239+import static com.l2jserver.gameserver.config.Configuration.votesystem;
2240 import com.l2jserver.gameserver.handler.ActionHandler;
2241 import com.l2jserver.gameserver.handler.ActionShiftHandler;
2242 import com.l2jserver.gameserver.handler.AdminCommandHandler;
2243@@ -565,6 +567,7 @@
2244 (customs().multiLangEnable() && customs().multiLangVoiceCommand() ? Lang.class : null),
2245 (customs().debugVoiceCommand() ? Debug.class : null),
2246 (customs().allowChangePassword() ? ChangePassword.class : null),
2247+ (votesystem().getEnableVoteSystem() && votesystem().getEnableIndividualVote() && votesystem().getEnableVotingCommand() ? VoteSystem.class : null),
2248 };
2249
2250 // TODO(Zoey76): Add this handler.
2251diff --git a/src/main/java/com/l2jserver/datapack/handlers/voicedcommandhandlers/VoteSystem.java b/src/main/java/com/l2jserver/datapack/handlers/voicedcommandhandlers/VoteSystem.java
2252new file mode 100644
2253index 0000000..dd7c9e8
2254--- /dev/null
2255+++ b/src/main/java/com/l2jserver/datapack/handlers/voicedcommandhandlers/VoteSystem.java
2256@@ -0,0 +1,58 @@
2257+/*
2258+ * To change this license header, choose License Headers in Project Properties.
2259+ * To change this template file, choose Tools | Templates
2260+ * and open the template in the editor.
2261+ */
2262+package com.l2jserver.datapack.handlers.voicedcommandhandlers;
2263+
2264+import static com.l2jserver.gameserver.config.Configuration.votesystem;
2265+import com.l2jserver.gameserver.handler.IVoicedCommandHandler;
2266+import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
2267+import com.l2jserver.gameserver.votesystem.Enum.voteSite;
2268+import com.l2jserver.gameserver.votesystem.Handler.voteManager;
2269+
2270+/**
2271+ *
2272+ * @author escor
2273+ */
2274+public class VoteSystem implements IVoicedCommandHandler{
2275+
2276+ @Override
2277+ public boolean useVoicedCommand(String command, L2PcInstance activeChar, String params) {
2278+ if (command.equalsIgnoreCase(votesystem().getVotingCommand()))
2279+ {
2280+ if(!votesystem().getEnableVoteSystem()) {
2281+ activeChar.sendMessage("The rewards system has been disabled by your administrator");
2282+ return false;
2283+ }
2284+ if(!votesystem().getEnableIndividualVote()) {
2285+ activeChar.sendMessage("The individual reward system is disabled");
2286+ return false;
2287+ }
2288+ if(!votesystem().getEnableVotingCommand()) {
2289+ activeChar.sendMessage("Voting command reward is disabled");
2290+ return false;
2291+ }
2292+ if(activeChar.isJailed()) {
2293+ activeChar.sendMessage("You can't use that function while incarcerated");
2294+ return false;
2295+ }
2296+
2297+ for(voteSite vs : voteSite.values()) {
2298+ new Thread(()->{
2299+ voteManager.getInatance().getReward(activeChar, vs.ordinal());
2300+ }).start();
2301+ }
2302+
2303+ }
2304+ return true;
2305+ }
2306+
2307+ @Override
2308+ public String[] getVoicedCommandList() {
2309+ return new String[]{
2310+ votesystem().getVotingCommand(),
2311+ };
2312+ }
2313+
2314+}
2315diff --git a/src/main/resources/data/html/mods/votesystem/1000004.html b/src/main/resources/data/html/mods/votesystem/1000004.html
2316new file mode 100644
2317index 0000000..01331d0
2318--- /dev/null
2319+++ b/src/main/resources/data/html/mods/votesystem/1000004.html
2320@@ -0,0 +1,19 @@
2321+<html>
2322+<title>Voting panel</title>
2323+<body><center>
2324+ <br><img src="L2UI_CH3.herotower_deco" width=256 height=32><br>
2325+ <table cellpadding=2 width=280 background="L2UI_CH3.refinewnd_back_Pattern">
2326+ <tr><td width="280">Hello <font color="C6AF00">%accountName%</font>, welcome to the voting rewards dashboard, please help us by voting by server every <font color="C6AF00">%everyXtime% hours</font> in all voting sites.</td></tr>
2327+ </table>
2328+ <table width="290"><tr><td width="290" align="center">You can vote: </td></tr></table>
2329+ <br><img src="l2ui.SquareWhite" width=290 height=1><br>
2330+
2331+ %enablevote%
2332+
2333+ <br>
2334+ <img src="l2ui.SquareWhite" width=290 height=1><br>
2335+
2336+
2337+
2338+</center></body>
2339+</html>
2340diff --git a/src/main/resources/data/stats/npcs/custom/custom.xml b/src/main/resources/data/stats/npcs/custom/custom.xml
2341index 18f8f27..094ebc4 100644
2342--- a/src/main/resources/data/stats/npcs/custom/custom.xml
2343+++ b/src/main/resources/data/stats/npcs/custom/custom.xml
2344@@ -58,4 +58,10 @@
2345 <height normal="22.25" />
2346 </collision>
2347 </npc>
2348+ <npc id="1000004" displayId="32226" name="Kaaya" usingServerSideName="true" title="Vote Reward System" usingServerSideTitle="true" type="L2NpcVote">
2349+ <collision>
2350+ <radius normal="11" />
2351+ <height normal="22.25" />
2352+ </collision>
2353+ </npc>
2354 </list>
2355\ No newline at end of file
2356diff --git a/src/main/resources/data/votesystem.xml b/src/main/resources/data/votesystem.xml
2357new file mode 100644
2358index 0000000..f254f8c
2359--- /dev/null
2360+++ b/src/main/resources/data/votesystem.xml
2361@@ -0,0 +1,75 @@
2362+<?xml version="1.0" encoding="UTF-8"?>
2363+<list>
2364+ <votesite name="l2.topgameserver.net" ordinal="0">
2365+ <items>
2366+ <item itemId="57" itemCount="10000000" />
2367+ <item itemId="6673" itemCount="1"/>
2368+ </items>
2369+ </votesite>
2370+ <votesite name="ItopZ.com" ordinal="1">
2371+ <items>
2372+ <item itemId="57" itemCount="10000000" />
2373+ <item itemId="6673" itemCount="1"/>
2374+ </items>
2375+ </votesite>
2376+ <votesite name="L2Top.co" ordinal="2">
2377+ <items>
2378+ <item itemId="57" itemCount="10000000" />
2379+ <item itemId="6673" itemCount="1"/>
2380+ </items>
2381+ </votesite>
2382+ <votesite name="L2Votes.com" ordinal="3">
2383+ <items>
2384+ <item itemId="57" itemCount="10000000" />
2385+ <item itemId="6673" itemCount="1"/>
2386+ </items>
2387+ </votesite>
2388+ <votesite name="Hopzone.net" ordinal="4">
2389+ <items>
2390+ <item itemId="57" itemCount="10000000" />
2391+ <item itemId="6673" itemCount="1"/>
2392+ </items>
2393+ </votesite>
2394+ <votesite name="L2Network.eu" ordinal="5">
2395+ <items>
2396+ <item itemId="57" itemCount="10000000" />
2397+ <item itemId="6673" itemCount="1"/>
2398+ </items>
2399+ </votesite>
2400+ <votesite name="L2Topservers.com" ordinal="6">
2401+ <items>
2402+ <item itemId="57" itemCount="10000000" />
2403+ <item itemId="6673" itemCount="1"/>
2404+ </items>
2405+ </votesite>
2406+ <votesite name="top.l2jbrasil.com" ordinal="7">
2407+ <items>
2408+ <item itemId="57" itemCount="10000000" />
2409+ <item itemId="6673" itemCount="1"/>
2410+ </items>
2411+ </votesite>
2412+ <votesite name="MMOTOP.eu" ordinal="8">
2413+ <items>
2414+ <item itemId="57" itemCount="10000000" />
2415+ <item itemId="6673" itemCount="1"/>
2416+ </items>
2417+ </votesite>
2418+ <votesite name="L2Topzone.com" ordinal="9">
2419+ <items>
2420+ <item itemId="57" itemCount="10000000" />
2421+ <item itemId="6673" itemCount="1"/>
2422+ </items>
2423+ </votesite>
2424+ <votesite name="L2Servers.com" ordinal="10">
2425+ <items>
2426+ <item itemId="57" itemCount="10000000" />
2427+ <item itemId="6673" itemCount="1"/>
2428+ </items>
2429+ </votesite>
2430+ <votesite name="globalVotes" ordinal="11">
2431+ <items>
2432+ <item itemId="57" itemCount="10000000" />
2433+ <item itemId="6673" itemCount="1"/>
2434+ </items>
2435+ </votesite>
2436+</list>
2437\ No newline at end of file
2438diff --git a/src/main/resources/data/xsd/votesystem.xsd b/src/main/resources/data/xsd/votesystem.xsd
2439new file mode 100644
2440index 0000000..4d63c5d
2441--- /dev/null
2442+++ b/src/main/resources/data/xsd/votesystem.xsd
2443@@ -0,0 +1,32 @@
2444+<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
2445+ <xs:element name="list">
2446+ <xs:complexType>
2447+ <xs:sequence>
2448+ <xs:element name="votesite" maxOccurs="unbounded" minOccurs="0">
2449+ <xs:complexType>
2450+ <xs:sequence>
2451+ <xs:element name="items">
2452+ <xs:complexType>
2453+ <xs:sequence>
2454+ <xs:element name="item" maxOccurs="unbounded" minOccurs="0">
2455+ <xs:complexType>
2456+ <xs:simpleContent>
2457+ <xs:extension base="xs:string">
2458+ <xs:attribute type="xs:short" name="itemId" use="optional"/>
2459+ <xs:attribute type="xs:int" name="itemCount" use="optional"/>
2460+ </xs:extension>
2461+ </xs:simpleContent>
2462+ </xs:complexType>
2463+ </xs:element>
2464+ </xs:sequence>
2465+ </xs:complexType>
2466+ </xs:element>
2467+ </xs:sequence>
2468+ <xs:attribute type="xs:string" name="name" use="optional"/>
2469+ <xs:attribute type="xs:byte" name="ordinal" use="optional"/>
2470+ </xs:complexType>
2471+ </xs:element>
2472+ </xs:sequence>
2473+ </xs:complexType>
2474+ </xs:element>
2475+</xs:schema>
2476
2477-- ----------------------------
2478-- Table structure for globalvotes
2479-- ----------------------------
2480DROP TABLE IF EXISTS `globalvotes`;
2481CREATE TABLE `globalvotes` (
2482 `voteSite` tinyint(2) NOT NULL,
2483 `lastRewardVotes` int(11) NULL DEFAULT NULL,
2484 PRIMARY KEY (`voteSite`) USING BTREE
2485) ENGINE = InnoDB CHARACTER SET = latin1 COLLATE = latin1_swedish_ci ROW_FORMAT = Dynamic;
2486
2487-- ----------------------------
2488-- Records of globalvotes
2489-- ----------------------------
2490INSERT INTO `globalvotes` VALUES (0, 13);
2491INSERT INTO `globalvotes` VALUES (1, 68);
2492INSERT INTO `globalvotes` VALUES (2, 0);
2493INSERT INTO `globalvotes` VALUES (3, 3);
2494INSERT INTO `globalvotes` VALUES (4, 2);
2495INSERT INTO `globalvotes` VALUES (5, 0);
2496INSERT INTO `globalvotes` VALUES (6, 0);
2497INSERT INTO `globalvotes` VALUES (7, 2);
2498INSERT INTO `globalvotes` VALUES (8, 3);
2499INSERT INTO `globalvotes` VALUES (9, 0);
2500INSERT INTO `globalvotes` VALUES (10, 75);
2501
2502-- ----------------------------
2503-- Table structure for individualvotes
2504-- ----------------------------
2505DROP TABLE IF EXISTS `individualvotes`;
2506CREATE TABLE `individualvotes` (
2507 `voterIp` varchar(40) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL,
2508 `voteSite` tinyint(3) NOT NULL,
2509 `serverVotingTime` bigint(20) NULL DEFAULT NULL,
2510 `votingTimeSite` bigint(20) NULL DEFAULT NULL,
2511 `alreadyRewarded` tinyint(3) NULL DEFAULT NULL,
2512 PRIMARY KEY (`voterIp`, `voteSite`) USING BTREE
2513) ENGINE = InnoDB CHARACTER SET = latin1 COLLATE = latin1_swedish_ci ROW_FORMAT = Dynamic;