SHOW:
|
|
- or go back to the newest paste.
1 | diff --git a/java/net/sf/l2j/gameserver/taskmanager/SoloZoneTaskManager.java b/java/net/sf/l2j/gameserver/taskmanager/SoloZoneTaskManager.java | |
2 | new file mode 100644 | |
3 | index 0000000..6b7ef6f | |
4 | --- /dev/null | |
5 | +++ a/java/net/sf/l2j/gameserver/taskmanager/SoloZoneTaskManager.java | |
6 | @@ -0,0 +1,98 @@ | |
7 | +package net.sf.l2j.gameserver.taskmanager; | |
8 | + | |
9 | +import java.security.SecureRandom; | |
10 | +import java.util.ArrayList; | |
11 | +import java.util.logging.Logger; | |
12 | + | |
13 | +import net.sf.l2j.commons.random.Rnd; | |
14 | + | |
15 | +import net.sf.l2j.gameserver.data.manager.ZoneManager; | |
16 | +import net.sf.l2j.gameserver.enums.ZoneId; | |
17 | +import net.sf.l2j.gameserver.handler.voicecommandhandlers.VoiceExitSoloZone; | |
18 | +import net.sf.l2j.gameserver.model.World; | |
19 | +import net.sf.l2j.gameserver.model.actor.Player; | |
20 | +import net.sf.l2j.gameserver.model.location.Location; | |
21 | +import net.sf.l2j.gameserver.model.zone.type.SoloZone; | |
22 | + | |
23 | + | |
24 | +/** | |
25 | + * @author MarGaZeaS | |
26 | + */ | |
27 | +public class SoloZoneTaskManager implements Runnable { | |
28 | + | |
29 | + private static final Location EXIT_LOCATION = VoiceExitSoloZone.getExitLocation(); // Λαμβάνουμε την έξοδο από το VoiceExitSoloZone | |
30 | + | |
31 | + @Override | |
32 | + public void run() | |
33 | + { | |
34 | + // Διασχίζουμε όλους τους παίκτες του κόσμου | |
35 | + for (Player player : World.getInstance().getPlayers()) | |
36 | + { | |
37 | + // Ελέγχουμε αν ο παίκτης είναι στο SoloZone | |
38 | + if (player.isInsideZone(ZoneId.SOLO)) | |
39 | + { | |
40 | + // Μεταφέρουμε τον παίκτη στην έξοδο | |
41 | + player.teleportTo(EXIT_LOCATION.getX(), EXIT_LOCATION.getY(), EXIT_LOCATION.getZ(), 0); | |
42 | + player.sendMessage("The server is restarting, you have been moved out of the Solo Zone."); | |
43 | + } | |
44 | + } | |
45 | + } | |
46 | + | |
47 | + private int _id; | |
48 | + | |
49 | + private static final Logger _log = Logger.getLogger(SoloZoneTaskManager.class.getName()); | |
50 | + private static final ArrayList<String> _rndNames = new ArrayList<>(); | |
51 | + private static final int RANDOM_NAMES = 500; | |
52 | + private static final String CHARS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; | |
53 | + private int _playersInSoloZone = 0; | |
54 | + | |
55 | + public int getPlayersInside() { | |
56 | + return _playersInSoloZone; | |
57 | + } | |
58 | + | |
59 | + public void setPlayersInside(int val) { | |
60 | + _playersInSoloZone = val; | |
61 | + } | |
62 | + | |
63 | + public SoloZoneTaskManager() { | |
64 | + _log.info("Solo Zone System: Loading..."); | |
65 | + for (int i = 0; i < RANDOM_NAMES; i++) { | |
66 | + String name = generateName(); | |
67 | + _rndNames.add(name); | |
68 | + _log.info("Generated name: " + name); | |
69 | + } | |
70 | + _log.info("Solo Zone System: Loaded " + _rndNames.size() + " names."); | |
71 | + } | |
72 | + | |
73 | + public String getAName() { | |
74 | + if (_rndNames.isEmpty()) { | |
75 | + _log.warning("SoloZoneManager: No random names available."); | |
76 | + return "Unknown"; | |
77 | + } | |
78 | + return _rndNames.get(Rnd.get(5, RANDOM_NAMES - 5)); | |
79 | + } | |
80 | + | |
81 | + private static String generateName() { | |
82 | + SecureRandom rnd = new SecureRandom(); | |
83 | + StringBuilder sb = new StringBuilder(15); | |
84 | + for (int i = 0; i < 15; i++) { | |
85 | + sb.append(CHARS.charAt(rnd.nextInt(CHARS.length()))); | |
86 | + } | |
87 | + return sb.toString(); | |
88 | + } | |
89 | + | |
90 | + public int getZoneId() | |
91 | + { | |
92 | + return _id; | |
93 | + } | |
94 | + | |
95 | + public final static SoloZone getCurrentZone() { | |
96 | + return ZoneManager.getInstance().getAllZones(SoloZone.class) | |
97 | + .stream() | |
98 | + .findFirst() // Επιστρέφει την πρώτη SoloZone (αν υπάρχει μόνο μία) | |
99 | + .orElse(null); | |
100 | + } | |
101 | + | |
102 | + public static SoloZoneTaskManager getInstance() { | |
103 | + return SingletonHolder._instance; | |
104 | + } | |
105 | + | |
106 | + private static class SingletonHolder { | |
107 | + private static final SoloZoneTaskManager _instance = new SoloZoneTaskManager(); | |
108 | + } | |
109 | +} | |
110 | diff --git a/aCis_gameserver/java/net/sf/l2j/gameserver/taskmanager/PvpFlagTaskManager.java b/aCis_gameserver/java/net/sf/l2j/gameserver/taskmanager/PvpFlagTaskManager.java | |
111 | index a707ce5..d247e2e 100644 | |
112 | --- a/aCis_gameserver/java/net/sf/l2j/gameserver/taskmanager/PvpFlagTaskManager.java | |
113 | final Player player = entry.getKey(); | |
114 | final long timeLeft = entry.getValue(); | |
115 | ||
116 | + if(player.isInsideZone(ZoneId.SOLO)) | |
117 | + continue; | |
118 | ||
119 | if(player.isInsideZone(ZoneId.BOSS)) | |
120 | continue; | |
121 | ||
122 | // Time is running out, clear PvP flag and remove from list. | |
123 | if (currentTime > timeLeft) | |
124 | diff --git a/aCis_gameserver/java/net/sf/l2j/gameserver/network/clientpackets/RequestCharacterCreate.java b/aCis_gameserver/java/net/sf/l2j/gameserver/network/clientpackets/RequestCharacterCreate.java | |
125 | index a707ce5..d247e2e 100644 | |
126 | +++ b/aCis_gameserver/java/net/sf/l2j/gameserver/network/clientpackets/RequestCharacterCreate.java | |
127 | ||
128 | if (Config.ALLOW_FISH_CHAMPIONSHIP) | |
129 | FishingChampionshipManager.getInstance(); | |
130 | ||
131 | + if (Config.ENABLE_STARTUP) | |
132 | + StartupManager.getInstance(); | |
133 | ||
134 | diff --git a/java/net/sf/l2j/gameserver/handler/admincommandhandlers/AdminMaintenance.java b/java/net/sf/l2j/gameserver/handler/admincommandhandlers/AdminMaintenance.java | |
135 | new file mode 100644 | |
136 | index 0000000..6b7ef6f | |
137 | --- /dev/null | |
138 | +++ a/java/net/sf/l2j/gameserver/handler/admincommandhandlers/AdminMaintenance.java | |
139 | if (!st.hasMoreTokens()) | |
140 | { | |
141 | sendHtmlForm(player); | |
142 | return; | |
143 | } | |
144 | ||
145 | try | |
146 | { | |
147 | switch (st.nextToken()) | |
148 | { | |
149 | case "shutdown": | |
150 | + SoloZoneTaskManager exitTask = new SoloZoneTaskManager(); | |
151 | + ThreadPool.schedule(exitTask, 0); | |
152 | Shutdown.getInstance().startShutdown(player, null, Integer.parseInt(st.nextToken()), false); | |
153 | break; | |
154 | ||
155 | case "restart": | |
156 | + exitTask = new SoloZoneTaskManager(); | |
157 | + ThreadPool.schedule(exitTask, 0); | |
158 | Shutdown.getInstance().startShutdown(player, null, Integer.parseInt(st.nextToken()), true); | |
159 | break; | |
160 | ||
161 | case "abort": | |
162 | Shutdown.getInstance().abort(player); | |
163 | break; | |
164 | diff --git a/java/net/sf/l2j/gameserver/handler/voicecommandhandlers/VoiceExitSoloZone.java b/java/net/sf/l2j/gameserver/handler/voicecommandhandlers/VoiceExitSoloZone.java | |
165 | new file mode 100644 | |
166 | index 0000000..6b7ef6f | |
167 | --- /dev/null | |
168 | +++ a/java/net/sf/l2j/gameserver/handler/voicecommandhandlers/VoiceExitSoloZone.java | |
169 | +package net.sf.l2j.gameserver.handler.voicecommandhandlers; | |
170 | + | |
171 | +import net.sf.l2j.commons.pool.ThreadPool; | |
172 | + | |
173 | +import net.sf.l2j.gameserver.enums.ZoneId; | |
174 | +import net.sf.l2j.gameserver.handler.IVoiceCommandHandler; | |
175 | +import net.sf.l2j.gameserver.model.actor.Player; | |
176 | +import net.sf.l2j.gameserver.model.location.Location; | |
177 | +import net.sf.l2j.gameserver.network.serverpackets.MagicSkillUse; | |
178 | + | |
179 | +/** | |
180 | + * Handles the voice command for exiting the Solo Zone with delay and effects. | |
181 | + * | |
182 | + * @author MarGaZeaS | |
183 | + */ | |
184 | +public class VoiceExitSoloZone implements IVoiceCommandHandler | |
185 | +{ | |
186 | + private static final String[] VOICE_COMMANDS = | |
187 | + { | |
188 | + "exit" | |
189 | + }; | |
190 | + | |
191 | + // Default location to teleport players when exiting the Solo Zone | |
192 | + private static final Location EXIT_LOCATION = new Location(81318, 148064, -3464); // Replace with your desired coordinates | |
193 | + | |
194 | + // Προσθήκη της μεθόδου για να πάρουμε την τοποθεσία εξόδου | |
195 | + public static Location getExitLocation() { | |
196 | + return EXIT_LOCATION; | |
197 | + } | |
198 | + | |
199 | + @Override | |
200 | + public void useVoiceCommand(Player player, String command) | |
201 | + { | |
202 | + if (command.equalsIgnoreCase("exit")) | |
203 | + { | |
204 | + if (!player.isInsideZone(ZoneId.SOLO)) | |
205 | + { | |
206 | + player.sendMessage("You are not inside the Solo Zone."); | |
207 | + return; | |
208 | + } | |
209 | + | |
210 | + // Notify the player about the delay | |
211 | + player.sendMessage("You will be teleported out of the Solo Zone in 2 seconds."); | |
212 | + | |
213 | + // Cast skill effect (Skill ID: 2100, Level: 1) | |
214 | + player.broadcastPacket(new MagicSkillUse(player, player, 2100, 1, 2000, 0)); | |
215 | + | |
216 | + // Schedule the teleportation after a 2-second delay | |
217 | + ThreadPool.schedule(() -> { | |
218 | + // Teleport the player to the designated exit location | |
219 | + player.teleportTo(EXIT_LOCATION.getX(), EXIT_LOCATION.getY(), EXIT_LOCATION.getZ(), 0); | |
220 | + | |
221 | + // Inform the player | |
222 | + player.sendMessage("You have exited the Solo Zone."); | |
223 | + }, 2000); // Delay in milliseconds (2000ms = 2 seconds) | |
224 | + } | |
225 | + } | |
226 | + | |
227 | + @Override | |
228 | + public String[] getVoiceCommandList() | |
229 | + { | |
230 | + return VOICE_COMMANDS; | |
231 | + } | |
232 | +} | |
233 | diff --git a/java/net/sf/l2j/gameserver/handler/VoiceCommandHandler.java b/java/net/sf/l2j/gameserver/handler/VoiceCommandHandler.java | |
234 | new file mode 100644 | |
235 | index 0000000..6b7ef6f | |
236 | --- /dev/null | |
237 | +++ a/java/net/sf/l2j/gameserver/handler/VoiceCommandHandler.java | |
238 | public class VoiceCommandHandler | |
239 | { | |
240 | private final Map<String, IVoiceCommandHandler> _entries = new HashMap<>(); | |
241 | ||
242 | protected VoiceCommandHandler() | |
243 | { | |
244 | ............ | |
245 | ............ | |
246 | + registerHandler(new VoiceExitSoloZone()); | |
247 | ||
248 | } | |
249 | ||
250 | public void registerHandler(IVoiceCommandHandler handler) | |
251 | { | |
252 | for (String command : handler.getVoiceCommandList()) | |
253 | _entries.put(command, handler); | |
254 | } | |
255 | diff --git a/java/net/sf/l2j/gameserver/model/actor/Npc.java b/java/net/sf/l2j/gameserver/model/actor/Npc.java | |
256 | new file mode 100644 | |
257 | index 0000000..6b7ef6f | |
258 | --- /dev/null | |
259 | +++ a/java/net/sf/l2j/gameserver/model/actor/Npc.java | |
260 | else if (command.startsWith("Chat")) | |
261 | { | |
262 | int val = 0; | |
263 | try | |
264 | { | |
265 | val = Integer.parseInt(command.substring(5)); | |
266 | } | |
267 | catch (final IndexOutOfBoundsException ioobe) | |
268 | { | |
269 | } | |
270 | catch (final NumberFormatException nfe) | |
271 | { | |
272 | } | |
273 | ||
274 | showChatWindow(player, val); | |
275 | + ) | |
276 | + else if (command.startsWith("solopvp")) | |
277 | + { | |
278 | + SoloZoneTaskManager.getInstance(); | |
279 | + player.teleportTo(SoloZoneTaskManager.getCurrentZone().getLoc(), 25); | |
280 | + } | |
281 | else if (command.startsWith("Link")) | |
282 | { | |
283 | final String path = command.substring(5).trim(); | |
284 | if (path.indexOf("..") != -1) | |
285 | return; | |
286 | ||
287 | final NpcHtmlMessage html = new NpcHtmlMessage(getObjectId()); | |
288 | html.setFile("data/html/" + path); | |
289 | html.replace("%objectId%", getObjectId()); | |
290 | player.sendPacket(html); | |
291 | } | |
292 | diff --git a/java/net/sf/l2j/gameserver/network/clientpackets/RequestRestartPoint.java b/java/net/sf/l2j/gameserver/network/clientpackets/RequestRestartPoint.java | |
293 | new file mode 100644 | |
294 | index 0000000..6b7ef6f | |
295 | --- /dev/null | |
296 | +++ a/java/net/sf/l2j/gameserver/network/clientpackets/RequestRestartPoint.java | |
297 | // Fixed. | |
298 | - else if (_requestType == 4) | |
299 | - { | |
300 | - if (!player.isGM() && !player.isFestivalParticipant()) | |
301 | - return; | |
302 | - | |
303 | - loc = player.getPosition(); | |
304 | - } | |
305 | + if (_requestType == 4) | |
306 | + { | |
307 | + // Έλεγχος αν ο παίκτης δεν είναι GM, δεν είναι μέρος του φεστιβάλ και δεν είναι στην Solo Zone | |
308 | + if (!player.isGM() && !player.isFestivalParticipant() && !player.isInsideZone(ZoneId.SOLO)) | |
309 | + { | |
310 | + return; | |
311 | + } | |
312 | + | |
313 | + SoloZoneTaskManager.getInstance(); | |
314 | + SoloZone currentZone = SoloZoneTaskManager.getCurrentZone(); | |
315 | + if (currentZone != null && currentZone.getLoc() != null) | |
316 | + { | |
317 | + // Αν υπάρχει ζώνη και οι τοποθεσίες δεν είναι κενές, χρησιμοποιούμε τυχαία τοποθεσία από την ζώνη | |
318 | + loc = currentZone.getLoc(); | |
319 | + } else | |
320 | + { | |
321 | + // Διαφορετικά, κάνουμε respawn στην τρέχουσα θέση του παίκτη | |
322 | + loc = player.getPosition(); | |
323 | + } | |
324 | + } | |
325 | diff --git a/java/net/sf/l2j/gameserver/network/clientpackets/RequestRestart.java b/java/net/sf/l2j/gameserver/network/clientpackets/RequestRestart.java | |
326 | new file mode 100644 | |
327 | index 0000000..6b7ef6f | |
328 | --- /dev/null | |
329 | +++ a/java/net/sf/l2j/gameserver/network/clientpackets/RequestRestart.java | |
330 | if (player.isFestivalParticipant() && FestivalOfDarknessManager.getInstance().isFestivalInitialized()) | |
331 | { | |
332 | player.sendPacket(SystemMessageId.NO_RESTART_HERE); | |
333 | sendPacket(RestartResponse.valueOf(false)); | |
334 | return; | |
335 | } | |
336 | ||
337 | + if (player.isInsideZone(ZoneId.SOLO)) | |
338 | + { | |
339 | + player.sendMessage("You cannot restart your character while in Solo Zone. Use .exit to leave"); | |
340 | + player.setFakeName(null); | |
341 | + sendPacket(RestartResponse.valueOf(false)); | |
342 | + return; | |
343 | + } | |
344 | ||
345 | player.removeFromBossZone(); | |
346 | diff --git a/java/net/sf/l2j/gameserver/network/clientpackets/Logout.java b/java/net/sf/l2j/gameserver/network/clientpackets/Logout.java | |
347 | new file mode 100644 | |
348 | index 0000000..6b7ef6f | |
349 | --- /dev/null | |
350 | +++ a/java/net/sf/l2j/gameserver/network/clientpackets/Logout.java | |
351 | player.removeFromBossZone(); | |
352 | player.logout(true); | |
353 | } | |
354 | } | |
355 | + | |
356 | + if (player.isInsideZone(ZoneId.SOLO)) | |
357 | + { | |
358 | + player.sendMessage("You cannot logout or restart your character while in Solo Zone. Use .exit to leave"); | |
359 | + player.setFakeName(null); | |
360 | + player.sendPacket(ActionFailed.STATIC_PACKET); | |
361 | + return; | |
362 | + } | |
363 | + | |
364 | player.removeFromBossZone(); | |
365 | player.logout(true); | |
366 | } | |
367 | } | |
368 | diff --git a/java/net/sf/l2j/gameserver/model/zone/type/SoloZone.java b/java/net/sf/l2j/gameserver/model/zone/type/SoloZone.java | |
369 | new file mode 100644 | |
370 | index 0000000..6b7ef6f | |
371 | --- /dev/null | |
372 | +++ a/java/net/sf/l2j/gameserver/model/zone/type/SoloZone.java | |
373 | +package net.sf.l2j.gameserver.model.zone.type; | |
374 | + | |
375 | +import java.util.ArrayList; | |
376 | +import java.util.List; | |
377 | +import java.util.Random; | |
378 | + | |
379 | +import net.sf.l2j.commons.random.Rnd; | |
380 | + | |
381 | +import net.sf.l2j.Config; | |
382 | +import net.sf.l2j.gameserver.enums.MessageType; | |
383 | +import net.sf.l2j.gameserver.enums.ZoneId; | |
384 | +import net.sf.l2j.gameserver.handler.voicecommandhandlers.VoiceExitSoloZone; | |
385 | +import net.sf.l2j.gameserver.model.World; | |
386 | +import net.sf.l2j.gameserver.model.actor.Creature; | |
387 | +import net.sf.l2j.gameserver.model.actor.Player; | |
388 | +import net.sf.l2j.gameserver.model.location.Location; | |
389 | +import net.sf.l2j.gameserver.model.zone.type.subtype.ZoneType; | |
390 | +import net.sf.l2j.gameserver.network.SystemMessageId; | |
391 | +import net.sf.l2j.gameserver.network.serverpackets.EtcStatusUpdate; | |
392 | +import net.sf.l2j.gameserver.taskmanager.PvpFlagTaskManager; | |
393 | +import net.sf.l2j.gameserver.taskmanager.SoloZoneTaskManager; | |
394 | + | |
395 | +/** | |
396 | + * @author MarGaZeaS | |
397 | + * | |
398 | + */ | |
399 | +public class SoloZone extends ZoneType | |
400 | +{ | |
401 | + private String _name; | |
402 | + private List<Location> _locations = new ArrayList<>(); | |
403 | + | |
404 | + public SoloZone(int id) | |
405 | + { | |
406 | + super(id); | |
407 | + } | |
408 | + | |
409 | + @Override | |
410 | + public void setParameter(String name, String value) | |
411 | + { | |
412 | + if (name.equals("name")) | |
413 | + _name = value; | |
414 | + else if (name.equals("locs")) | |
415 | + { | |
416 | + for (String locs : value.split(";")) | |
417 | + { | |
418 | + String[] coordinates = locs.split(","); | |
419 | + if (coordinates.length == 3) | |
420 | + { | |
421 | + int x = Integer.parseInt(coordinates[0]); | |
422 | + int y = Integer.parseInt(coordinates[1]); | |
423 | + int z = Integer.parseInt(coordinates[2]); | |
424 | + _locations.add(new Location(x, y, z)); | |
425 | + } | |
426 | + else | |
427 | + { | |
428 | + LOGGER.warn("Invalid location format: " + locs); | |
429 | + } | |
430 | + } | |
431 | + } | |
432 | + } | |
433 | + | |
434 | + | |
435 | + @Override | |
436 | + protected void onEnter(Creature character) | |
437 | + { | |
438 | + if (character instanceof Player) | |
439 | + { | |
440 | + final Player player = (Player) character; | |
441 | + | |
442 | + if ((player.getClassId().getId() == 15 || player.getClassId().getId() == 16 || player.getClassId().getId() == 97)) | |
443 | + { | |
444 | + Location respawnLocation = VoiceExitSoloZone.getExitLocation(); | |
445 | + player.instantTeleportTo(respawnLocation, 20); | |
446 | + player.sendMessage("Your class is not allowed in this zone."); | |
447 | + return; | |
448 | + } | |
449 | + | |
450 | + String randomName = SoloZoneTaskManager.getInstance().getAName(); | |
451 | + if (randomName == null || randomName.isEmpty() || !isValidName(randomName)) | |
452 | + { | |
453 | + randomName = generateRandomName(); | |
454 | + } | |
455 | + if (isNameAlreadyTaken(randomName)) | |
456 | + { | |
457 | + randomName = generateRandomName(); | |
458 | + } | |
459 | + player.setFakeName(randomName); | |
460 | + player.sendMessage("Welcome to the Solo Zone, your random name is: " + randomName); | |
461 | + player.sendPacket(SystemMessageId.ENTERED_COMBAT_ZONE); | |
462 | + character.setInsideZone(ZoneId.SOLO, true); | |
463 | + character.setInsideZone(ZoneId.NO_STORE, true); | |
464 | + character.setInsideZone(ZoneId.NO_SUMMON_FRIEND, true); | |
465 | + | |
466 | + if (player.getParty() != null) | |
467 | + { | |
468 | + player.getParty().removePartyMember(player, MessageType.DISCONNECTED); | |
469 | + } | |
470 | + | |
471 | + if (player.getPvpFlag() > 0) | |
472 | + PvpFlagTaskManager.getInstance().remove(player, true); | |
473 | + | |
474 | + player.updatePvPStatus(); | |
475 | + player.broadcastUserInfo(); | |
476 | + } | |
477 | + } | |
478 | + | |
479 | + private static boolean isValidName(String name) { | |
480 | + return name.matches("[a-zA-Z0-9_]+"); | |
481 | + } | |
482 | + | |
483 | + private static String generateRandomName() { | |
484 | + Random rand = new Random(); | |
485 | + int nameLength = rand.nextInt(12) + 4; | |
486 | + StringBuilder nameBuilder = new StringBuilder(); | |
487 | + | |
488 | + for (int i = 0; i < nameLength; i++) { | |
489 | + char randomChar = (char) (rand.nextInt(26) + 'a'); | |
490 | + nameBuilder.append(randomChar); | |
491 | + } | |
492 | + | |
493 | + return nameBuilder.toString(); | |
494 | + } | |
495 | + | |
496 | + private static boolean isNameAlreadyTaken(String name) { | |
497 | + return World.getInstance().getPlayers().stream().anyMatch(player -> player.getFakeName().equals(name)); | |
498 | + } | |
499 | + | |
500 | + @Override | |
501 | + protected void onExit(Creature character) | |
502 | + { | |
503 | + character.setInsideZone(ZoneId.SOLO, false); // Solo zone | |
504 | + character.setInsideZone(ZoneId.NO_STORE, false); // Allow making a store | |
505 | + character.setInsideZone(ZoneId.NO_SUMMON_FRIEND, false); // Allow summon | |
506 | + | |
507 | + if (character instanceof Player) | |
508 | + { | |
509 | + final Player player = (Player) character; | |
510 | + | |
511 | + if (player.getFakeName() != null) | |
512 | + { | |
513 | + player.setFakeName(null); | |
514 | + } | |
515 | + | |
516 | + player.sendPacket(SystemMessageId.LEFT_COMBAT_ZONE); | |
517 | + { | |
518 | + if(!player.isInObserverMode() && player.getPvpFlag() > 0) | |
519 | + PvpFlagTaskManager.getInstance().add(player, Config.PVP_NORMAL_TIME); | |
520 | + | |
521 | + player.sendPacket(new EtcStatusUpdate(player)); | |
522 | + player.broadcastUserInfo(); | |
523 | + } | |
524 | + } | |
525 | + } | |
526 | + | |
527 | + public String getName() | |
528 | + { | |
529 | + return _name; | |
530 | + } | |
531 | + | |
532 | + public Location getLoc() | |
533 | + { | |
534 | + if (_locations.isEmpty()) | |
535 | + { | |
536 | + return null; // Αν η λίστα είναι κενή, επιστρέφουμε null | |
537 | + } | |
538 | + return _locations.get(Rnd.get(0, _locations.size() - 1)); // Επιλέγουμε τυχαία τοποθεσία | |
539 | + } | |
540 | +} | |
541 | diff --git a/java/net/sf/l2j/gameserver/GameServer.java b/java/net/sf/l2j/gameserver/GameServer.java | |
542 | new file mode 100644 | |
543 | index 0000000..6b7ef6f | |
544 | --- /dev/null | |
545 | +++ a/java/net/sf/l2j/gameserver/GameServer.java | |
546 | if (Config.ALLOW_FISH_CHAMPIONSHIP) | |
547 | FishingChampionshipManager.getInstance(); | |
548 | ||
549 | + StringUtil.printSection("Custom Features"); | |
550 | + SoloZoneTaskManager.getInstance(); | |
551 | ||
552 | StringUtil.printSection("Handlers"); | |
553 | LOGGER.info("Loaded {} admin command handlers.", AdminCommandHandler.getInstance().size()); | |
554 | diff --git a/java/net/sf/l2j/gameserver/GameServer.java b/java/net/sf/l2j/gameserver/Shutdown.java | |
555 | new file mode 100644 | |
556 | index 0000000..6b7ef6f | |
557 | --- /dev/null | |
558 | +++ a/java/net/sf/l2j/gameserver/Shutdown.java | |
559 | // disconnect players | |
560 | try | |
561 | { | |
562 | disconnectAllPlayers(); | |
563 | LOGGER.info("All players have been disconnected."); | |
564 | } | |
565 | catch (Exception e) | |
566 | { | |
567 | // Silent catch. | |
568 | } | |
569 | ||
570 | + // Restore real names for players in SoloZone | |
571 | + restoreRealNamesInSoloZone(); | |
572 | ||
573 | // stop all threadpolls | |
574 | ThreadPool.shutdown(); | |
575 | ||
576 | try | |
577 | { | |
578 | LoginServerThread.getInstance().interrupt(); | |
579 | } | |
580 | catch (Exception e) | |
581 | { | |
582 | // Silent catch. | |
583 | } | |
584 | ||
585 | ||
586 | ||
587 | // avoids new players from logging in | |
588 | if (_secondsShut <= 60 && LoginServerThread.getInstance().getServerType() != ServerType.DOWN) | |
589 | LoginServerThread.getInstance().setServerType(ServerType.DOWN); | |
590 | ||
591 | _secondsShut--; | |
592 | ||
593 | Thread.sleep(1000); | |
594 | } | |
595 | } | |
596 | catch (InterruptedException e) | |
597 | { | |
598 | } | |
599 | } | |
600 | ||
601 | + // This method restores the real names of players in SoloZone | |
602 | + private static void restoreRealNamesInSoloZone() | |
603 | + { | |
604 | + for (Player player : World.getInstance().getPlayers()) | |
605 | + { | |
606 | + // Check if player is inside the SoloZone | |
607 | + if (player.isInsideZone(ZoneId.SOLO)) | |
608 | + { | |
609 | + // Restore the real name by removing the fake name | |
610 | + if (player.getFakeName() != null) | |
611 | + { | |
612 | + player.setFakeName(null); // Restore the real name | |
613 | + LOGGER.info("Player {}'s fake name has been removed and real name restored.", player.getName()); | |
614 | + } | |
615 | + } | |
616 | + } | |
617 | + } | |
618 | ||
619 | private static void sendServerQuit(int seconds) | |
620 | { | |
621 | World.toAllOnlinePlayers(SystemMessage.getSystemMessage(SystemMessageId.THE_SERVER_WILL_BE_COMING_DOWN_IN_S1_SECONDS).addNumber(seconds)); | |
622 | } | |
623 | diff --git a/java/net/sf/l2j/gameserver/enums/ZoneId.java b/java/net/sf/l2j/gameserver/enums/ZoneId.java | |
624 | new file mode 100644 | |
625 | index 0000000..6b7ef6f | |
626 | --- /dev/null | |
627 | +++ a/java/net/sf/l2j/gameserver/enums/ZoneId.java | |
628 | public enum ZoneId | |
629 | { | |
630 | PVP(0), | |
631 | PEACE(1), | |
632 | SIEGE(2), | |
633 | MOTHER_TREE(3), | |
634 | CLAN_HALL(4), | |
635 | NO_LANDING(5), | |
636 | WATER(6), | |
637 | JAIL(7), | |
638 | MONSTER_TRACK(8), | |
639 | CASTLE(9), | |
640 | SWAMP(10), | |
641 | NO_SUMMON_FRIEND(11), | |
642 | NO_STORE(12), | |
643 | TOWN(13), | |
644 | HQ(14), | |
645 | DANGER_AREA(15), | |
646 | CAST_ON_ARTIFACT(16), | |
647 | NO_RESTART(17), | |
648 | SCRIPT(18), | |
649 | - BOSS(19), | |
650 | + BOSS(19), | |
651 | + SOLO(20); | |
652 | ||
653 | private final int _id; | |
654 | ||
655 | private ZoneId(int id) | |
656 | { | |
657 | _id = id; | |
658 | } | |
659 | diff --git a/java/net/sf/l2j/gameserver/network/serverpackets/Die.java b/java/net/sf/l2j/gameserver/network/serverpackets/Die.java | |
660 | new file mode 100644 | |
661 | index 0000000..6b7ef6f | |
662 | --- /dev/null | |
663 | +++ a/java/net/sf/l2j/gameserver/network/serverpackets/Die.java | |
664 | if (creature instanceof Player) | |
665 | { | |
666 | Player player = (Player) creature; | |
667 | - _allowFixedRes = player.getAccessLevel().allowFixedRes(); | |
668 | + _allowFixedRes = player.getAccessLevel().allowFixedRes() || player.isInsideZone(ZoneId.SOLO); | |
669 | _clan = player.getClan(); | |
670 | ||
671 | } | |
672 | diff --git a/java/net/sf/l2j/gameserver/model/actor/Player.java b/java/net/sf/l2j/gameserver//model/actor/Player.java | |
673 | new file mode 100644 | |
674 | index 0000000..6b7ef6f | |
675 | --- /dev/null | |
676 | +++ a/java/net/sf/l2j/gameserver/network/clientpackets/EnterWorld.java | |
677 | // Attacker or spectator logging into a siege zone will be ported at town. | |
678 | if (player.isInsideZone(ZoneId.SIEGE) && player.getSiegeState() < 2) | |
679 | player.teleportTo(TeleportType.TOWN); | |
680 | ||
681 | + if (player.isInsideZone(ZoneId.SOLO)) | |
682 | + { | |
683 | + ThreadPool.schedule(() -> { | |
684 | + Location exitLocation = VoiceExitSoloZone.getExitLocation(); | |
685 | + | |
686 | + if (exitLocation != null) | |
687 | + { | |
688 | + player.teleportTo(exitLocation.getX(), exitLocation.getY(), exitLocation.getZ(), 0); | |
689 | + player.sendMessage("You have been moved to the exit of the SoloZone."); | |
690 | + } | |
691 | + }, 5000); // 5000 milliseconds (5sec) | |
692 | + } | |
693 | diff --git a/java/net/sf/l2j/gameserver/model/actor/Player.java b/java/net/sf/l2j/gameserver/model/actor/Player.java | |
694 | new file mode 100644 | |
695 | index 0000000..6b7ef6f | |
696 | --- /dev/null | |
697 | +++ a/java/net/sf/l2j/gameserver/model/actor/Player.java | |
698 | @Override | |
699 | public void doRevive() | |
700 | { | |
701 | super.doRevive(); | |
702 | ||
703 | stopEffects(EffectType.CHARM_OF_COURAGE); | |
704 | sendPacket(new EtcStatusUpdate(this)); | |
705 | ||
706 | getStatus().setCpHpMp(getStatus().getMaxCp(), getStatus().getMaxHp(), getStatus().getMaxMp()); | |
707 | ||
708 | _reviveRequested = 0; | |
709 | _revivePower = 0; | |
710 | ||
711 | if (isMounted()) | |
712 | startFeed(_mountNpcId); | |
713 | + if (isInsideZone(ZoneId.SOLO)) | |
714 | + { | |
715 | + // Give Nobless (1323 ID) | |
716 | + L2Skill no = SkillTable.getInstance().getInfo(1323, 1); | |
717 | + no.getEffects(this, this); | |
718 | + sendMessage("You have received the Nobless status in the Solo Zone."); | |
719 | + } | |
720 | + } |