С Calendar будет слишком уж громоздкий и запутанный код расчетов такого времени, имхо.Calendar поможет рассчитать время для следующего спавна и время можно хранить в кэше/бд и его передавать в Announcements
long time = new SchedulingPattern("30 6 * * *|30 18 * * *").next(System.currentTimeMillis());
Если у тебя мобы в процессе телепортируются в разные места по времени, то подозреваю что ты просто не обновляешь после телепортации им точку спавна на актуальную и в итоге при атаке срабатывает проверка "моб слишком далеко ушел от точки спавна - надо вернуть его туда".Мобы появляются, но когда я бью их, они куда-то телепортируются.
Расчет будет не так часто происходить, с календарем 15 строк уходит на календарь. В календарь массив времени отправляем, он подбирает ближайший спавнС Calendar будет слишком уж громоздкий и запутанный код расчетов такого времени, имхо.
Тут лучше и удобней будет использовать работу с временем в стиле Cron для получений времени спавна и т.д., например через класс SchedulingPattern, который можно стянуть из того же овера, если в люцере нет ничего похожего. Ну или можно прицепить какую нибудь либу для работы с этим, напримерВы не можете просматривать ссылку пожалуйста воспользуйтесь следующими ссылками Вход или Регистрация, правда это как из пушки по воробьям будет в этом случае
Ну а в случае с SchedulingPattern полчение нужного времени можно уложить чуть ли не в одну строчку кода.
<spawn>
<npc id="20001" count="1" respawn="3600" respawn_random="1800" />
<point x="10000" y="10000" z="0" />
</spawn>
<spawn>
<npc id="20001" count="1" respawn_time="0 */2 * * *" />
<point x="10000" y="10000" z="0" />
</spawn>
малыш ты уже давно устарел и те на ком ты наварил бабок же давно поумнелиThreadPoolManager поможет удалить всех мобов, чтобы удалить нужно при спавне добавить всех мобов в список и через н-время удалять, также будет спавнить мобов по времени календаря
Announcements даст анонсы всем игрокам
Calendar поможет рассчитать время для следующего спавна и время можно хранить в кэше/бд и его передавать в Announcements
Список нужных Location + Rnd по локациям даст рандом локу, которую также можно записать и передать в анонс
Это хороший пример, но в моем случае все немного иначе.Ну я у себя для поддержки спавнов в конкретное время как раз в стандартные спавнеры овера впилил поддержку SchedulingPattern, что в целом удобно.
В итоге теперь могу в любом спавне вместо обычного респа через заданное время тупо задать время в виде строки для cron и оно будет работать как от него и ожидается.
Ну т.е. к примеру был респ в час +/- полчаса
просто задал вот так и будет респ при наступлении каждого нового четного часаXML:<spawn> <npc id="20001" count="1" respawn="3600" respawn_random="1800" /> <point x="10000" y="10000" z="0" /> </spawn>
XML:<spawn> <npc id="20001" count="1" respawn_time="0 */2 * * *" /> <point x="10000" y="10000" z="0" /> </spawn>
public class TeleporterInstance extends MerchantInstance {
private static final String DATA_PATH = "data/spawn/";
private static ScheduledFuture<?> zoneRotationTask;
private static List<NpcInstance> activeNpcs = new ArrayList<>();
// Constructor for TeleporterInstance
public TeleporterInstance(int objectId, NpcTemplate template) {
super(objectId, template);
startAutoZoneRotation(); // Automatically start zone rotation when NPC is created
}
// Automatically schedules zone rotation every day at midnight
public static void startAutoZoneRotation() {
runZoneRotation(); // Perform an immediate rotation
long timeUntilNextDay = calculateTimeUntilMidnight();
// Schedule daily zone rotation at 00:00
zoneRotationTask = ThreadPoolManager.getInstance().scheduleAtFixedRate(TeleporterInstance::runZoneRotation,
timeUntilNextDay,
86400000); // 24 hours
}
// Run the zone rotation logic (spawn/despawn NPCs)
public static void runZoneRotation() {
// Get the current day of the week to determine the active zone
DayOfWeek currentDay = LocalDate.now().getDayOfWeek();
String dayName = currentDay.name().toLowerCase(); // Get day in lowercase (e.g., "monday")
// Load NPCs from XML based on the day of the week
loadNpcsForDay(dayName);
}
// Load NPCs for the current day from XML files
public static void loadNpcsForDay(String dayName) {
// Define zone names for each day and load respective XML files
String[] zones = {"devilsisle", "cruma_marshlands", "pagan_temple", "ruins_of_despair"};
// Despawn current NPCs, if any
despawnNpcs();
// Load and spawn NPCs for each zone
for (String zone : zones) {
String filename = DATA_PATH + dayName + "_" + zone + ".xml";
spawnNpcsFromXml(filename);
}
// Announce the new active zone to players
Announcements.getInstance().announceByCustomMessage("CustomZonesEvent.ZoneActive." + dayName, null);
}
// Spawn NPCs from the given XML file
private static void spawnNpcsFromXml(String filename) {
try {
// Initialize the XML parser
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse(new File(filename));
NodeList spawnList = doc.getElementsByTagName("spawn");
for (int i = 0; i < spawnList.getLength(); i++) {
Node spawnNode = spawnList.item(i);
if (spawnNode.getNodeType() == Node.ELEMENT_NODE) {
Element spawnElement = (Element) spawnNode;
// Get the <npc> element inside <spawn>
NodeList npcList = spawnElement.getElementsByTagName("npc");
for (int j = 0; j < npcList.getLength(); j++) {
Element npcElement = (Element) npcList.item(j);
// Extract npc attributes
int npcId = Integer.parseInt(npcElement.getAttribute("id"));
int respawnTime = Integer.parseInt(npcElement.getAttribute("respawn"));
// Extract the position from the 'pos' attribute
String pos = npcElement.getAttribute("pos");
String[] positionData = pos.split(" ");
int x = Integer.parseInt(positionData[0]);
int y = Integer.parseInt(positionData[1]);
int z = Integer.parseInt(positionData[2]);
int heading = Integer.parseInt(positionData[3]); // Optional, for future use
// Spawn the NPC and set respawn timer
spawnAndRespawnNpc(npcId, x, y, z, respawnTime);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
// Method to spawn and respawn an NPC after a certain delay
private static void spawnAndRespawnNpc(int npcId, int x, int y, int z, int respawnTime) {
Location spawnLocation = new Location(x, y, z);
NpcInstance npc = NpcHolder.getInstance().getTemplate(npcId).getNewInstance();
// Spawn the NPC at the specified location
npc.spawnMe(spawnLocation);
// Prevent the NPC from walking (set AI to idle)
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE);
// Add to the active NPC list
activeNpcs.add(npc);
// Schedule the NPC to respawn after the specified time
ThreadPoolManager.getInstance().schedule(() -> {
// Despawn the NPC and respawn it after the delay
if (!npc.isDeleted()) {
npc.deleteMe();
activeNpcs.remove(npc);
}
spawnAndRespawnNpc(npcId, x, y, z, respawnTime); // Recursively respawn the NPC
}, respawnTime * 1000L); // Convert respawn time to milliseconds
}
мне кажется или ты вон в loadNpcsForDay как раз по всем зонам пробегаешься циклом и потому у тебя и везде спавн идет?Единственная проблема заключается в том, что код порождает монстров во всех зонах, а не только в активной зоне на текущий день.
Хорошая идея с названиями групп.мне кажется или ты вон в loadNpcsForDay как раз по всем зонам пробегаешься циклом и потому у тебя и везде спавн идет?
почему вместо этого просто одну не выбирать, случайным образмо там или последовательно.
З.Ы. в люцере поддержки групп спавнов нет кстати что ли? а то вместо подгрузки разных файлов спавнов можно было бы манипулировать посто спавном/деспавном по именам групп.
<spawn name="[custom_spawn_group]">
<npc id="40012" count="1" respawn="60" pos="83313 147901 -3430 52507" />
<npc id="40040" count="1" respawn="60" pos="44807 188983 -3581 27931" />
<npc id="40031" count="1" respawn="60" pos="44374 189418 -3581 44315" />
<npc id="48000" count="1" respawn="60" pos="44054 189613 -3581 44315" />
<npc id="48004" count="1" respawn="60" pos="44409 188725 -3512 40959" />
</spawn>
// Load NPCs for the current day from XML files
public static void loadNpcsForDay(String dayName) {
// Define zone names for each day and load respective XML files
String[] zones = {"devilsisle", "cruma_marshlands", "pagan_temple", "ruins_of_despair"};
// Despawn NPCs for the previous days
for (String zone : zones) {
if (!zone.equals(dayName)) {
despawnNpcsFromZone(zone); // Despawn NPCs that are not for the current day
}
}
// Now, spawn NPCs for the current day
String filename = DATA_PATH + dayName + "_" + "zone" + ".xml";
spawnNpcsFromXml(filename, dayName);
// Announce the new active zone to players
Announcements.getInstance().announceByCustomMessage("CustomZonesEvent.ZoneActive." + dayName, null);
}
// Spawn NPCs from the given XML file
private static void spawnNpcsFromXml(String filename, String zoneName) {
try {
// Initialize the XML parser
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse(new File(filename));
NodeList spawnList = doc.getElementsByTagName("spawn");
List<NpcInstance> spawnedNpcs = new ArrayList<>();
for (int i = 0; i < spawnList.getLength(); i++) {
Node spawnNode = spawnList.item(i);
if (spawnNode.getNodeType() == Node.ELEMENT_NODE) {
Element spawnElement = (Element) spawnNode;
// Get the <npc> element inside <spawn>
NodeList npcList = spawnElement.getElementsByTagName("npc");
for (int j = 0; j < npcList.getLength(); j++) {
Element npcElement = (Element) npcList.item(j);
// Extract npc attributes
int npcId = Integer.parseInt(npcElement.getAttribute("id"));
int respawnTime = Integer.parseInt(npcElement.getAttribute("respawn"));
// Extract the position from the 'pos' attribute
String pos = npcElement.getAttribute("pos");
String[] positionData = pos.split(" ");
int x = Integer.parseInt(positionData[0]);
int y = Integer.parseInt(positionData[1]);
int z = Integer.parseInt(positionData[2]);
// Spawn the NPC and set respawn timer
NpcInstance npc = spawnAndRespawnNpc(npcId, x, y, z, respawnTime);
spawnedNpcs.add(npc); // Track the spawned NPC
}
}
}
// Store the NPCs in the map, associating them with the zone
zoneNpcMap.put(zoneName, spawnedNpcs);
} catch (Exception e) {
e.printStackTrace();
}
}
// Method to spawn and respawn an NPC after a certain delay
private static NpcInstance spawnAndRespawnNpc(int npcId, int x, int y, int z, int respawnTime) {
Location spawnLocation = new Location(x, y, z);
NpcInstance npc = NpcHolder.getInstance().getTemplate(npcId).getNewInstance();
// Spawn the NPC at the specified location
npc.spawnMe(spawnLocation);
// Prevent the NPC from walking (set AI to idle)
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE);
// Schedule the NPC to respawn after the specified time
ThreadPoolManager.getInstance().schedule(() -> {
// Despawn the NPC and respawn it after the delay
if (!npc.isDeleted()) {
npc.deleteMe();
}
spawnAndRespawnNpc(npcId, x, y, z, respawnTime); // Recursively respawn the NPC
}, respawnTime * 1000L); // Convert respawn time to milliseconds
return npc; // Return the spawned NPC
}
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?