 |
|

06.08.2015, 21:26
|
|
Флудер
Регистрация: 20.01.2015
Сообщений: 7,201
С нами:
5952720
Репутация:
6527
|
|
Сюда буду публиковать весь код, как выразился гринд раз я балабол то пускай все посмотрят и почитают данный код:
Сообщение от Спойлер
if(player.getVar("EnterAntharas") !=null)
return;
else
{
player.sendMessage(player.isLangRus() ? "Вы не можете находиться здесь." : "You can not be here.");
player.teleToLocation(82698, 148638, -3473);
}
Сообщение от Спойлер
if(player.getVar("EnterBaium") !=null)
return;
else
{
player.sendMessage(player.isLangRus() ? "Вы не можете находиться здесь." : "You can not be here.");
player.teleToLocation(147450, 27120, -2208);
}
Сообщение от Спойлер
if(player.getVar("EnterHellbound") !=null && player.getVar("EnterUrban") !=null && HellboundManager.getHellboundLevel() !=0 && (player.isQuestCompleted("_130_PathToHellbound") || player.isQuestCompleted("_133_ThatsBloodyHot")))
return;
else
{
player.sendMessage(player.isLangRus() ? "Вы не можете находиться здесь." : "You can not be here.");
player.teleToLocation(82698, 148638, -3473);
}
Сообщение от Спойлер
if(player.getVar("EnterHellbound") !=null && HellboundManager.getHellboundLevel() !=0 && (player.isQuestCompleted("_130_PathToHellbound") || player.isQuestCompleted("_133_ThatsBloodyHot")))
return;
else
{
player.sendMessage(player.isLangRus() ? "Вы не можете находиться здесь." : "You can not be here.");
player.teleToLocation(82698, 148638, -3473);
}
Сообщение от Спойлер
if(player.getVar("EnterValakas") !=null)
return;
else
{
player.sendMessage(player.isLangRus() ? "Вы не можете находиться здесь." : "You can not be here.");
player.teleToLocation(147725, -56517, -2780);
}
Вот так реализованы зоны у Grind-Team где реализован весь официальный контент, когда можно от многих багов избавиться глянув офф скрипты, но тут не суть даже в нём а суть в данном коде. Давайте насиловать бд и писать не нужное, а использовать статик методы видимо для лохов.
|
|
|

06.08.2015, 21:37
|
|
Участник форума
Регистрация: 05.08.2015
Сообщений: 216
С нами:
5669089
Репутация:
0
|
|
Ну, как бы, тут все ясно:
Сообщение от Grind
Забивать базу xD Ты наверно из тех днарей, что тащат все в xml
Я уже давал комментарии по-поводу приоритета использования mysql для хранения любых данных, которые требуют хранения.
Чтобы "забить базу" или "нагрузить" надо очень сильно постараться.
|
|
|

06.08.2015, 21:43
|
|
Флудер
Регистрация: 20.01.2015
Сообщений: 7,201
С нами:
5952720
Репутация:
6527
|
|
Сообщение от Спойлер
public class HeroItems extends Functions
{
//TODO: Bonux, переделать, чтобы было мультиязычное!
private static final String[][] HERO_ITEMS = {
{
"6611",
"weapon_the_sword_of_hero_i00",
"Infinity Blade",
"During a critical attack, decreases one's P. Def and increases de-buff casting ability, damage shield effect, Max HP, Max MP, Max CP, and shield defense power. Also enhances damage to target during PvP.",
"524/230",
"Sword" },
{
"6612",
"weapon_the_two_handed_sword_of_hero_i00",
"Infinity Cleaver",
"Increases Max HP, Max CP, critical power and critical chance. Inflicts extra damage when a critical attack occurs and has possibility of reflecting the skill back on the player. Also enhances damage to target during PvP.",
"638/230",
"Two Handed Sword" },
{
"6613",
"weapon_the_axe_of_hero_i00",
"Infinity Axe",
"During a critical attack, it bestows one the ability to cause internal conflict to one's opponent. Damage shield function, Max HP, Max MP, Max CP as well as one's shield defense rate are increased. It also enhances damage to one's opponent during PvP.",
"524/230",
"Blunt" },
{
"6614",
"weapon_the_mace_of_hero_i00",
"Infinity Rod",
"When good magic is casted upon a target, increases MaxMP, MaxCP, Casting Spd, and MP regeneration rate. Also recovers HP 100% and enhances damage to target during PvP.",
"420/307",
"Blunt" },
{
"6615",
"weapon_the_hammer_of_hero_i00",
"Infinity Crusher",
"Increases MaxHP, MaxCP, and Atk. Spd. Stuns a target when a critical attack occurs and has possibility of reflecting the skill back on the player. Also enhances damage to target during PvP.",
"638/230",
"Blunt" },
{
"6616",
"weapon_the_staff_of_hero_i00",
"Infinity Scepter",
"When casting good magic, it can recover HP by 100% at a certain rate, increases MAX MP, MaxCP, M. Atk., lower MP Consumption, increases the Magic Critical rate, and reduce the Magic Cancel. Enhances damage to target during PvP.",
"511/337",
"Blunt" },
{
"6617",
"weapon_the_dagger_of_hero_i00",
"Infinity Stinger",
"Increases MaxMP, MaxCP, Atk. Spd., MP regen rate, and the success rate of Mortal and Deadly Blow from the back of the target. Silences the target when a critical attack occurs and has Vampiric Rage effect. Also enhances damage to target during PvP.",
"458/230",
"Dagger" },
{
"6618",
"weapon_the_fist_of_hero_i00",
"Infinity Fang",
"Increases MaxHP, MaxMP, MaxCP and evasion. Stuns a target when a critical attack occurs and has possibility of reflecting the skill back on the player at a certain probability rate. Also enhances damage to target during PvP.",
"638/230",
"Dual Fist" },
{
"6619",
"weapon_the_bow_of_hero_i00",
"Infinity Bow",
"Increases MaxMP/MaxCP and decreases re-use delay of a bow. Slows target when a critical attack occurs and has Cheap Shot effect. Also enhances damage to target during PvP.",
"952/230",
"Bow" },
{
"6620",
"weapon_the_dualsword_of_hero_i00",
"Infinity Wing",
"When a critical attack occurs, increases MaxHP, MaxMP, MaxCP and critical chance. Silences the target and has possibility of reflecting the skill back on the target. Also enhances damage to target during PvP.",
"638/230",
"Dual Sword" },
{
"6621",
"weapon_the_pole_of_hero_i00",
"Infinity Spear",
"During a critical attack, increases MaxHP, Max CP, Atk. Spd. and Accuracy. Casts dispel on a target and has possibility of reflecting the skill back on the target. Also enhances damage to target during PvP.",
"524/230",
"Pole" },
{
"9388",
"weapon_infinity_rapier_i00",
"Infinity Rapier",
"Decreases the target P. Def and increases the de-buff casting ability, the damage shield ability, and the Max HP/Max MP/Max CP on a critical attack. Increases damage inflicted during PvP.A critical attack will have a chance to increase P. Atk., M. Atk., and healing power, and decrease MP consumption during skill use, for you and your party members.",
"475/230",
"Rapier" },
{
"9389",
"weapon_infinity_sword_i00",
"Infinity Sword",
"Increases critical attack success rate/power, MaxHP, MaxCP, and damage inflicted during PvP. Also inflicts extra damage on critical attacks, and reflects debuff attacks back on enemies.",
"568/230",
"Ancient Sword" },
{
"9390",
"weapon_infinity_shooter_i00",
"Infinity Shooter",
"Produces the following effects when a critical attack occurs: the target is slowed, decrease MP consumption for skill use, and increase Max MP/Max CP. Enhances damage done to the target during PvP.",
"584/230",
"Crossbow" } };
public void rendershop(String[] val)
{
Player player = getSelf();
NpcInstance npc = getNpc();
if(player == null || npc == null)
return;
String fileName = OLYMPIAD_HTML_PATH;
boolean succ = true;
if(!player.isHero())
{
fileName += "monument_weapon_no_hero.htm";
succ = false;
}
else
{
for(String heroItem[] : HERO_ITEMS)
{
int itemId = Integer.parseInt(heroItem[0]);
if(player.getInventory().getItemByItemId(itemId) != null)
{
fileName += "monument_weapon_have.htm";
succ = false;
break;
}
}
}
if(!succ)
{
npc.showChatWindow(player, fileName);
return;
}
boolean isKamael = player.getRace() == Race.kamael;
String htmltext = "";
if(val[0].equalsIgnoreCase("list"))
{
htmltext = "List of Hero Weapons:";
for(int i = isKamael ? 11 : 0; i ";
htmltext += "";
htmltext += "[" + HERO_ITEMS[2] + "]";
htmltext += "Type: " + HERO_ITEMS[5] + ", Patk/Matk: " + HERO_ITEMS[4];
htmltext += "";
}
htmltext += "";
}
else if(Integer.parseInt(val[0]) >= 0 && Integer.parseInt(val[0]) 10 ? 2234 : 1484;
htmltext = "Item Information:";
htmltext += "";
htmltext += "";
htmltext += "";
htmltext += "";
htmltext += "[" + HERO_ITEMS[itemIndex][2] + "]";
htmltext += "Type: " + HERO_ITEMS[itemIndex][5] + ", Patk/Matk: " + HERO_ITEMS[itemIndex][4] + "";
htmltext += "";
htmltext += "" + HERO_ITEMS[itemIndex][3] + "";
htmltext += "
";
htmltext += "
";
htmltext += "";
}
show(htmltext, player, npc);
}
public void getweapon(String[] var)
{
Player player = getSelf();
if(player == null)
return;
int item = Integer.parseInt(var[0]);
if(item 6621 || item 9390)
{
System.out.println(player.getName() + " tried to obtain non hero item using hero weapon service. Ban him!");
return;
}
NpcInstance npc = getNpc();
if(npc == null)
return;
String fileName = OLYMPIAD_HTML_PATH;
if(player.isHero())
{
boolean have = false;
for(String heroItem[] : HERO_ITEMS)
{
int itemId = Integer.parseInt(heroItem[0]);
if(player.getInventory().getItemByItemId(itemId) != null)
{
fileName += "monument_weapon_have.htm";
have = true;
break;
}
}
if(!have)
{
ItemFunctions.addItem(player, item, 1, true);
fileName += "monument_weapon_give.htm";
}
}
else
fileName += "monument_weapon_no_hero.htm";
npc.showChatWindow(player, fileName);
}
public String getcir()
{
Player player = getSelf();
if(player == null)
return null;
NpcInstance npc = getNpc();
if(npc == null)
return null;
String fileName = OLYMPIAD_HTML_PATH;
if(player.isHero())
{
if(player.getInventory().getItemByItemId(6842) != null)
fileName += "monument_circlet_have.htm";
else
{
ItemFunctions.addItem(player, 6842, 1, true); //Wings of Destiny Circlet
fileName += "monument_circlet_give.htm";
}
}
else
fileName += "monument_circlet_no_hero.htm";
npc.showChatWindow(player, fileName);
return null;
}
}
[/I]
Госпади упаси мои глаза, зачем сделать инстанс и в нём проверку на хиро оружия? Лучше фейк сервисов с кучей левого кода.
Сообщение от Спойлер
package services;
import java.util.ArrayList;
import core.gameserver.Config;
import core.gameserver.model.SimpleSpawner;
import core.gameserver.scripts.Functions;
import core.gameserver.scripts.ScriptFile;
public class FightClub extends Functions implements ScriptFile
{
private static final ArrayList _spawns_fight_club_manager = new ArrayList();
public static int FIGHT_CLUB_MANAGER = 13112;
private void spawnFightClub()
{
final int FIGHT_CLUB_MANAGER_SPAWN[][] = {
{ 82248, 147544, -3494, 13828 }, // Giran
{ 147480, 27288, -2228, 49151 }, // Aden
{ 82536, 53144, -1521, 0 }, // Oren
{ 16184, 144440, -3054, 16383 }, // Dion
{ 112488, 220264, -3627, 32767 }, // Heine
{ -15048, 121944, -3074, 0 }, // Gludio
{ 147384, -55352, -2759, 60699 }, // Goddard
{ 87688, -143352, -1318, 29412 }, // Shuttgard
{ -84776, 150904, -3154, 0 }, // Gludin
{ 36312, -48232, -1120, 0 }, // Rune
};
SpawnNPCs(FIGHT_CLUB_MANAGER, FIGHT_CLUB_MANAGER_SPAWN, _spawns_fight_club_manager);
}
@Override
public void onLoad()
{
if(Config.FIGHT_CLUB_ENABLED)
spawnFightClub();
}
@Override
public void onReload()
{}
@Override
public void onShutdown()
{}
}
Не легче ли создать группу спавна и сделать менеджером или в самом спавнере.
Сообщение от Спойлер
package services;
import java.util.ArrayList;
import java.util.List;
import core.gameserver.model.Creature;
import core.gameserver.model.Player;
import core.gameserver.model.base.Race;
import core.gameserver.model.instances.NpcInstance;
import core.gameserver.network.l2.s2c.MagicSkillUse;
import core.gameserver.scripts.Functions;
import core.gameserver.tables.SkillTable;
public class SupportMagic extends Functions
{
private final static int[][] _mageBuff = new int[][]{
// minlevel maxlevel skill skilllevel
{6, 75, 4322, 1}, // windwalk
{6, 75, 4323, 1}, // shield
{6, 75, 5637, 1}, // Magic Barrier 1
{6, 75, 4328, 1}, // blessthesoul
{6, 75, 4329, 1}, // acumen
{6, 75, 4330, 1}, // concentration
{6, 75, 4331, 1}, // empower
{16, 34, 4338, 1}, // life cubic
};
private final static int[][] _warrBuff = new int[][]{
// minlevel maxlevel skill
{6, 75, 4322, 1}, // windwalk
{6, 75, 4323, 1}, // shield
{6, 75, 5637, 1}, // Magic Barrier 1
{6, 75, 4324, 1}, // btb
{6, 75, 4325, 1}, // vampirerage
{6, 75, 4326, 1}, // regeneration
{6, 39, 4327, 1}, // haste 1
{40, 75, 5632, 1}, // haste 2
{16, 34, 4338, 1}, // life cubic
};
private final static int[][] _summonBuff = new int[][]{
// minlevel maxlevel skill
{6, 75, 4322, 1}, // windwalk
{6, 75, 4323, 1}, // shield
{6, 75, 5637, 1}, // Magic Barrier 1
{6, 75, 4324, 1}, // btb
{6, 75, 4325, 1}, // vampirerage
{6, 75, 4326, 1}, // regeneration
{6, 75, 4328, 1}, // blessthesoul
{6, 75, 4329, 1}, // acumen
{6, 75, 4330, 1}, // concentration
{6, 75, 4331, 1}, // empower
{6, 39, 4327, 1}, // haste 1
{40, 75, 5632, 1}, // haste 2
};
private final static int minSupLvl = 6;
private final static int maxSupLvl = 75;
public void getSupportMagic()
{
Player player = getSelf();
NpcInstance npc = getNpc();
doSupportMagic(npc, player, false);
}
public void getSupportServitorMagic()
{
Player player = getSelf();
NpcInstance npc = getNpc();
doSupportMagic(npc, player, true);
}
public void getProtectionBlessing()
{
Player player = getSelf();
NpcInstance npc = getNpc();
// Не выдаём блессиг протекшена ПКшникам.
if(player.getKarma() > 0)
return;
if(player.getLevel() > 39 || player.getClassId().getLevel() >= 3)
{
show("default/newbie_blessing_no.htm", player, npc);
return;
}
npc.doCast(SkillTable.getInstance().getInfo(5182, 1), player, true);
}
public static void doSupportMagic(NpcInstance npc, Player player, boolean servitor)
{
// Prevent a cursed weapon weilder of being buffed
if(player.isCursedWeaponEquipped())
return;
int lvl = player.getLevel();
if(servitor && (player.getPet() == null || !player.getPet().isSummon()))
{
show("default/newbie_nosupport_servitor.htm", player, npc);
return;
}
else
{
if(lvl maxSupLvl)
{
show("default/newbie_nosupport_max.htm", player, npc);
return;
}
}
List target = new ArrayList();
if(servitor)
{
target.add(player.getPet());
for(int[] buff : _summonBuff)
if(lvl >= buff[0] && lvl = buff[0] && lvl = buff[0] && lvl ";
append += "Список доступных локаций:
";
}
else
{
append += "Teleport to catacomb or necropolis. ";
append += "You may teleport to any of the following hunting locations.
";
}
if(player.getLevel() ";
append += "[scripts_Util:Gatekeeper 45248 124223 -5408 0|The Pilgrim's Necropolis (30-40)]";
append += "[scripts_Util:Gatekeeper 110911 174013 -5439 0|Necropolis of Worship (40-50)]";
append += "[scripts_Util:Gatekeeper -22101 77383 -5173 0|The Patriot's Necropolis (50-60)]";
append += "[scripts_Util:Gatekeeper -52654 79149 -4741 0|Necropolis of Devotion (60-70)]";
append += "[scripts_Util:Gatekeeper 117884 132796 -4831 0|Necropolis of Martyrdom (60-70)]";
append += "[scripts_Util:Gatekeeper 82750 209250 -5401 0|The Saint's Necropolis (70-80)]";
append += "[scripts_Util:Gatekeeper 171897 -17606 -4901 0|Disciples Necropolis(70-80)]
";
append += "[scripts_Util:Gatekeeper 42322 143927 -5381 0|Catacomb of the Heretic (30-40)]";
append += "[scripts_Util:Gatekeeper 45841 170307 -4981 0|Catacomb of the Branded (40-50)]";
append += "[scripts_Util:Gatekeeper 77348 78445 -5125 0|Catacomb of the Apostate (50-60)]";
append += "[scripts_Util:Gatekeeper 139955 79693 -5429 0|Catacomb of the Witch (60-70)]";
append += "[scripts_Util:Gatekeeper -19827 13509 -4901 0|Catacomb of Dark Omens (70-80)]";
append += "[scripts_Util:Gatekeeper 113573 84513 -6541 0|Catacomb of the Forbidden Path (70-80)]";
}
else
{
append += "[scripts_Util:Gatekeeper -41567 209463 -5080 10000|Necropolis of Sacrifice (20-30) - 10000 Adena]";
append += "[scripts_Util:Gatekeeper 45248 124223 -5408 20000|The Pilgrim's Necropolis (30-40) - 20000 Adena]";
append += "[scripts_Util:Gatekeeper 110911 174013 -5439 30000|Necropolis of Worship (40-50) - 30000 Adena]";
append += "[scripts_Util:Gatekeeper -22101 77383 -5173 40000|The Patriot's Necropolis (50-60) - 40000 Adena]";
append += "[scripts_Util:Gatekeeper -52654 79149 -4741 50000|Necropolis of Devotion (60-70) - 50000 Adena]";
append += "[scripts_Util:Gatekeeper 117884 132796 -4831 50000|Necropolis of Martyrdom (60-70) - 50000 Adena]";
append += "[scripts_Util:Gatekeeper 82750 209250 -5401 60000|The Saint's Necropolis (70-80) - 60000 Adena]";
append += "[scripts_Util:Gatekeeper 171897 -17606 -4901 60000|Disciples Necropolis(70-80) - 60000 Adena]
";
append += "[scripts_Util:Gatekeeper 42322 143927 -5381 20000|Catacomb of the Heretic (30-40) - 20000 Adena]";
append += "[scripts_Util:Gatekeeper 45841 170307 -4981 30000|Catacomb of the Branded (40-50) - 30000 Adena]";
append += "[scripts_Util:Gatekeeper 77348 78445 -5125 40000|Catacomb of the Apostate (50-60) - 40000 Adena]";
append += "[scripts_Util:Gatekeeper 139955 79693 -5429 50000|Catacomb of the Witch (60-70) - 50000 Adena]";
append += "[scripts_Util:Gatekeeper -19827 13509 -4901 60000|Catacomb of Dark Omens (70-80) - 60000 Adena]";
append += "[scripts_Util:Gatekeeper 113573 84513 -6541 60000|Catacomb of the Forbidden Path (70-80) - 60000 Adena]";
}
return append;
}
}
Ну просто отличная реализация в катакомбы нечего сказать.
Остальные фейк сервисы(да да фейк, это не сервисы) я не стану расписывать т.к однотипно оно сделано, я пойду дальше в кб.
Сообщение от Спойлер
package services.community;
import java.util.StringTokenizer;
import core.gameserver.Config;
import core.gameserver.data.htm.HtmCache;
import core.gameserver.handler.bbs.CommunityBoardManager;
import core.gameserver.model.base.Element;
import core.gameserver.network.l2.s2c.ShowBoard;
import core.gameserver.scripts.Functions;
import core.gameserver.model.Player;
import core.gameserver.model.items.ItemInstance;
import core.gameserver.data.xml.holder.ItemHolder;
import core.gameserver.network.l2.s2c.InventoryUpdate;
import core.gameserver.handler.bbs.ICommunityBoardHandler ;
import core.gameserver.templates.item.EtcItemTemplate;
import core.gameserver.network.l2.components.SystemMsg;
import core.gameserver.model.base.TeamType;
import core.gameserver.templates.item.ItemTemplate;
import core.gameserver.scripts.ScriptFile;
import core.gameserver.templates.item.ArmorTemplate.Armor Type;
import core.gameserver.templates.item.support.EnchantItem ;
import core.gameserver.utils.BbsUtil;
import core.gameserver.utils.Log;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ManageEnchant extends Functions implements ScriptFile, ICommunityBoardHandler
{
static final Logger _log = LoggerFactory.getLogger(ManageEnchant.class);
private int enchant_item = Config.COMMUNITYBOARD_ENCHANT_ITEM;
private int max_enchant = Config.COMMUNITYBOARD_MAX_ENCHANT;
private int[] enchant_level = Config.COMMUNITYBOARD_ENCHANT_LVL;
private int[] ench_price_weapon = Config.COMMUNITYBOARD_ENCHANT_PRICE_WEAPON;
private int[] ench_price_armor = Config.COMMUNITYBOARD_ENCHANT_PRICE_ARMOR;
private int[] atr_lvl_weapon = Config.COMMUNITYBOARD_ENCHANT_ATRIBUTE_LVL_WEAPON;
private int[] atr_price_weapon = Config.COMMUNITYBOARD_ENCHANT_ATRIBUTE_PRICE_WEAPO N;
private int[] atr_lvl_armor = Config.COMMUNITYBOARD_ENCHANT_ATRIBUTE_LVL_ARMOR;
private int[] atr_price_armor = Config.COMMUNITYBOARD_ENCHANT_ATRIBUTE_PRICE_ARMOR ;
private boolean atr_pvp = Config.COMMUNITYBOARD_ENCHANT_ATRIBUTE_PVP;
@Override
public void onLoad(){
if(Config.COMMUNITYBOARD_ENABLED)
{
_log.info("CommunityBoard: Enchant Community service loaded.");
CommunityBoardManager.getInstance().registerHandle r(this);
}
}
@Override
public void onReload(){
if(Config.COMMUNITYBOARD_ENABLED)
{
CommunityBoardManager.getInstance().removeHandler( this);
}
}
@Override
public void onShutdown(){}
@Override
public String[] getBypassCommands(){
return new String[] {
"_cbbsechant",
"_cbbsechantlist",
"_cbbsechantChus",
"_cbbsechantAtr",
"_cbbsechantgo",
"_cbbsechantuseAtr"
};
}
@Override
public void onBypassCommand(Player activeChar, String bypass){
if(!CheckCondition(activeChar))
return;
if (bypass.startsWith("_cbbsechant"))
{
String name = "None Name";
String html = HtmCache.getInstance().getNotNull(Config.BBS_HOME_ DIR + "pages/enchant.htm", activeChar);
name = ItemHolder.getInstance().getTemplate(enchant_item) .getName();
StringBuilder sb = new StringBuilder("");
sb.append("");
ItemInstance[] arr = activeChar.getInventory().getItems();
int len = arr.length;
for (int i = 0; i = 7816 && _item.getItemId() = (max_enchant + 1) || !_item.canBeEnchanted(true)
|| _item.getEquipSlot() == ItemTemplate.SLOT_HAIR || _item.getEquipSlot() == ItemTemplate.SLOT_DHAIR)
continue;
sb.append(new StringBuilder(""));
sb.append(new StringBuilder("" + _item.getTemplate().getName() + " " + (_item.getEnchantLevel() Заточено на: +" + _item.getEnchantLevel())) + ""));
sb.append(new StringBuilder("Заточка за: " + name + ""));
sb.append("");
sb.append("");
if(Config.ALLOW_BBS_ENCHANT_ELEMENTAR)
sb.append(new StringBuilder(""));
sb.append("");
if(Config.ALLOW_BBS_ENCHANT_ATT)
sb.append(new StringBuilder(""));
sb.append("");
}
sb.append("");
html = html.replace("%enchanter%", sb.toString());
html = BbsUtil.htmlBuff(html, activeChar);
ShowBoard.separateAndSend(html, activeChar);
}
if (bypass.startsWith("_cbbsechantlist"))
{
StringTokenizer st2 = new StringTokenizer(bypass, ";");
String[] mBypass = st2.nextToken().split(":");
int ItemForEchantObjID = Integer.parseInt(mBypass[1]);
String name = "None Name";
String html = HtmCache.getInstance().getNotNull(Config.BBS_HOME_ DIR + "pages/enchant.htm", activeChar);
name = ItemHolder.getInstance().getTemplate(enchant_item) .getName();
ItemInstance EhchantItem = activeChar.getInventory().getItemByObjectId(ItemFo rEchantObjID);
StringBuilder sb = new StringBuilder("");
sb.append("Для обычной заточки выбрана вещь:");
sb.append(new StringBuilder(" "));
sb.append(new StringBuilder("" + EhchantItem.getTemplate().getName() + " " + (EhchantItem.getEnchantLevel() Заточено на: +" + EhchantItem.getEnchantLevel())) + ""));
sb.append(new StringBuilder("Заточка производится за: " + name + ""));
sb.append("");
sb.append(new StringBuilder(" "));
sb.append("");
sb.append("");
sb.append("
");
sb.append("
");
sb.append("");
for(int i = 0; i "));
//sb.append("");
}
sb.append("");
html = html.replace("%enchanter%", sb.toString());
html = BbsUtil.htmlBuff(html, activeChar);
ShowBoard.separateAndSend(html, activeChar);
}
if (bypass.startsWith("_cbbsechantChus"))
{
StringTokenizer st2 = new StringTokenizer(bypass, ";");
String[] mBypass = st2.nextToken().split(":");
int ItemForEchantObjID = Integer.parseInt(mBypass[1]);
String name = "None Name";
String html = HtmCache.getInstance().getNotNull(Config.BBS_HOME_ DIR + "pages/enchant.htm", activeChar);
name = ItemHolder.getInstance().getTemplate(enchant_item) .getName();
ItemInstance EhchantItem = activeChar.getInventory().getItemByObjectId(ItemFo rEchantObjID);
StringBuilder sb = new StringBuilder("");
sb.append("Для заточки на атрибут выбрана вещь:
");
sb.append(new StringBuilder(" "));
sb.append(new StringBuilder("" + EhchantItem.getTemplate().getName() + " " + (EhchantItem.getEnchantLevel() Заточено на: +" + EhchantItem.getEnchantLevel())) + ""));
sb.append(new StringBuilder("Заточка производится за: " + name + ""));
sb.append("");
sb.append(new StringBuilder(" "));
sb.append("");
sb.append("");
sb.append("
");
sb.append("
");
sb.append("");
sb.append("
");
sb.append(new StringBuilder(""));
sb.append("
");
sb.append(new StringBuilder(""));
sb.append("
");
sb.append(new StringBuilder(""));
sb.append("");
sb.append("
");
sb.append(new StringBuilder(""));
sb.append("
");
sb.append(new StringBuilder(""));
sb.append("
");
sb.append(new StringBuilder(""));
sb.append("");
html = html.replace("%enchanter%", sb.toString());
html = BbsUtil.htmlBuff(html, activeChar);
ShowBoard.separateAndSend(html, activeChar);
}
if (bypass.startsWith("_cbbsechantAtr"))
{
StringTokenizer st2 = new StringTokenizer(bypass, ";");
String[] mBypass = st2.nextToken().split(":");
int AtributType = Integer.parseInt(mBypass[1]);
int ItemForEchantObjID = Integer.parseInt(mBypass[2]);
String ElementName = "";
if (AtributType == 0)
ElementName = "Fire";
else if (AtributType == 1)
ElementName = "Water";
else if (AtributType == 2)
ElementName = "Wind";
else if (AtributType == 3)
ElementName = "Earth";
else if (AtributType == 4)
ElementName = "Divine";
else if (AtributType == 5)
ElementName = "Dark";
String name = "None Name";
String html = HtmCache.getInstance().getNotNull(Config.BBS_HOME_ DIR + "pages/enchant.htm", activeChar);
name = ItemHolder.getInstance().getTemplate(enchant_item) .getName();
ItemInstance EhchantItem = activeChar.getInventory().getItemByObjectId(ItemFo rEchantObjID);
StringBuilder sb = new StringBuilder("");
sb.append(new StringBuilder("Выбран элемент: " + ElementName + " Для заточки выбрана вещь:"));
sb.append(new StringBuilder(" "));
sb.append(new StringBuilder("" + EhchantItem.getTemplate().getName() + " " + (EhchantItem.getEnchantLevel() Заточено на: +" + EhchantItem.getEnchantLevel())) + ""));
sb.append(new StringBuilder("Заточка производится за: " + name + ""));
sb.append("");
sb.append(new StringBuilder(" "));
sb.append("");
sb.append("");
sb.append("");
if (EhchantItem.getTemplate().getCrystalType() == ItemTemplate.Grade.S || EhchantItem.getTemplate().getCrystalType() == ItemTemplate.Grade.S80 || EhchantItem.getTemplate().getCrystalType() == ItemTemplate.Grade.S84)
{
sb.append("");
for(int i = 0; i "));
sb.append("");
}
sb.append("");
}
else if (EhchantItem.getTemplate().getCrystalType() == ItemTemplate.Grade.S || EhchantItem.getTemplate().getCrystalType() == ItemTemplate.Grade.S80 || EhchantItem.getTemplate().getCrystalType() == ItemTemplate.Grade.S84)
{
sb.append("");
for(int i = 0; i "));
sb.append("");
}
sb.append("");
sb.append("");
}
else
{
sb.append("");
sb.append("");
sb.append("");
sb.append("");
sb.append("");
sb.append("Заточка данной вещи не возможна!");
sb.append("");
sb.append("");
sb.append("");
sb.append("");
sb.append("");
}
sb.append("");
html = html.replace("%enchanter%", sb.toString());
html = BbsUtil.htmlBuff(html, activeChar);
ShowBoard.separateAndSend(html, activeChar);
}
if (bypass.startsWith("_cbbsechantgo"))
{
StringTokenizer st2 = new StringTokenizer(bypass, ";");
String[] mBypass = st2.nextToken().split(":");
int EchantVal = Integer.parseInt(mBypass[1]);
int EchantPrice = Integer.parseInt(mBypass[2]);
int EchantObjID = Integer.parseInt(mBypass[3]);
ItemTemplate item = ItemHolder.getInstance().getTemplate(enchant_item) ;
ItemInstance pay = activeChar.getInventory().getItemByItemId(item.get ItemId());
ItemInstance EhchantItem = activeChar.getInventory().getItemByObjectId(Echant ObjID);
if (pay != null && pay.getCount() >= EchantPrice)
{
activeChar.getInventory().destroyItem(pay, EchantPrice);
EhchantItem.setEnchantLevel(EchantVal);
activeChar.getInventory().equipItem(EhchantItem);
activeChar.sendPacket(new InventoryUpdate().addModifiedItem(EhchantItem));
activeChar.broadcastUserInfo(true);
activeChar.broadcastCharInfo();
activeChar.sendMessage(new StringBuilder("" + EhchantItem.getTemplate().getName() + " было заточено до " + EchantVal + ".").toString());
Log.add(new StringBuilder(activeChar.getName() + " enchant item:" + EhchantItem.getTemplate().getName() + " val: " + EchantVal + "").toString(), "wmzSeller");
onBypassCommand(activeChar, "_cbbsechant");
}
else
activeChar.sendPacket(SystemMsg.INCORRECT_ITEM_COU NT);
}
if (bypass.startsWith("_cbbsechantuseAtr"))
{
StringTokenizer st2 = new StringTokenizer(bypass, ";");
String[] mBypass = st2.nextToken().split(":");
int EchantVal = Integer.parseInt(mBypass[1]);
int AtrType = Integer.parseInt(mBypass[2]);
int EchantPrice = Integer.parseInt(mBypass[3]);
int EchantObjID = Integer.parseInt(mBypass[4]);
ItemTemplate item = ItemHolder.getInstance().getTemplate(enchant_item) ;
ItemInstance pay = activeChar.getInventory().getItemByItemId(item.get ItemId());
ItemInstance EhchantItem = activeChar.getInventory().getItemByObjectId(Echant ObjID);
if(EhchantItem.isWeapon()){
if (pay != null && pay.getCount() >= EchantPrice){
activeChar.getInventory().destroyItem(pay, EchantPrice);
activeChar.getInventory().unEquipItem(EhchantItem) ;
EhchantItem.setAttributeElement(getAttr(AtrType), EchantVal);
activeChar.getInventory().equipItem(EhchantItem);
activeChar.sendPacket(new InventoryUpdate().addModifiedItem(EhchantItem));
activeChar.broadcastUserInfo(true);
activeChar.sendMessage(new StringBuilder("Значение атрибута " + EhchantItem.getTemplate().getName() + " увеличено до " + EchantVal + ".").toString());
Log.add(new StringBuilder(activeChar.getName() + " enchant item:" + EhchantItem.getTemplate().getName() + " val: " + EchantVal + " AtributType:" + AtrType).toString(), "wmzSeller");
onBypassCommand(activeChar, "_cbbsechant");
}
else
activeChar.sendPacket(SystemMsg.INCORRECT_ITEM_COU NT);
}
else if(EhchantItem.isArmor()){
if(!canEnchantArmorAttribute(AtrType, EhchantItem)){
activeChar.sendMessage("Невозможно вставить аттрибут в броню, не соблюдены условия");
return;
}
if (pay != null && pay.getCount() >= EchantPrice){
activeChar.getInventory().destroyItem(pay, EchantPrice);
activeChar.getInventory().unEquipItem(EhchantItem) ;
EhchantItem.setAttributeElement(getAttr(AtrType), EchantVal);
activeChar.getInventory().equipItem(EhchantItem);
activeChar.sendPacket(new InventoryUpdate().addModifiedItem(EhchantItem));
activeChar.broadcastUserInfo(true);
activeChar.sendMessage(new StringBuilder("Значение атрибута " + EhchantItem.getTemplate().getName() + " увеличено до " + EchantVal + ".").toString());
Log.add(new StringBuilder(activeChar.getName() + " enchant item:" + EhchantItem.getTemplate().getName() + " val: " + EchantVal + " AtributType:" + AtrType).toString(), "wmzSeller");
onBypassCommand(activeChar, "_cbbsechant");
}
}
else{
if (activeChar.isLangRus())
activeChar.sendMessage("В данную вещь нельзя вставить атрибут.");
else
activeChar.sendMessage("In this thing you can not insert the attribute.");
}
}
}
public void onWriteCommand(Player player, String bypass, String arg1, String arg2, String arg3, String arg4, String arg5) {
//To change body of implemented methods use File | Settings | File Templates.
}
private boolean canEnchantArmorAttribute(int attr, ItemInstance item){
switch(attr)
{
case 0:
if(item.getDefenceWater() != 0)
return false;
break;
case 1:
if(item.getDefenceFire() != 0)
return false;
break;
case 2:
if(item.getDefenceEarth() != 0)
return false;
break;
case 3:
if(item.getDefenceWind() != 0)
return false;
break;
case 4:
if(item.getDefenceUnholy() != 0)
return false;
break;
case 5:
if(item.getDefenceHoly() != 0)
return false;
break;
}
return true;
}
private Element getAttr(int attr){
Element El = Element.NONE;
switch(attr)
{
case 0:
El = Element.FIRE;
break;
case 1:
El = Element.WATER;
break;
case 2:
El = Element.WIND;
break;
case 3:
El = Element.EARTH;
break;
case 4:
El = Element.HOLY;
break;
case 5:
El = Element.UNHOLY;
break;
}
return El;
}
private static boolean CheckCondition(Player player){
if(player == null)
return false;
if(player.isDead())
return false;
if((player.getPvpFlag() != 0 || player.isInDuel() || player.isInCombat() || player.isAttackingNow()))
{
if (player.isLangRus())
player.sendMessage("Во время боя нельзя использовать данную функцию.");
else
player.sendMessage("During combat, you can not use this feature.");
return false;
}
if (player.isInOlympiadMode())
{
if (player.isLangRus())
player.sendMessage("Во время Олимпиады нельзя использовать данную функцию.");
else
player.sendMessage("During the Olympics you can not use this feature.");
return false;
}
if (!Config.COMMUNITYBOARD_ENCHANT_ENABLED)
{
if (player.isLangRus())
player.sendMessage("Функция заточки отключена.");
else
player.sendMessage("Enchant off function.");
return false;
}
if (player.getTeam() != TeamType.NONE)
{
if (player.isLangRus())
player.sendMessage("Нельзя использовать заточку во время эвентов.");
else
player.sendMessage("You can not use the enchant during Events.");
return false;
}
return true;
}
}
Сообщение от Спойлер
[/I][/I][/I][/I][/I][/I][/I][/I][/I][/I][/I][/I][/I][/I][/I][/I][/I][/I][/I]
А теперь берём в руки hxd редактором и ловим веселье. Код просто отменного качества, достоин почёта и уважения. Остальные скрипты кб не стоит смотреть, там чёрт ногу сломит.
Сообщение от Спойлер
services/villagemaster
services/petelove
Не смотреть сюда, опасно может убить
[/I][/I][/I][/I]
|
|
|

06.08.2015, 21:46
|
|
Флудер
Регистрация: 20.01.2015
Сообщений: 7,201
С нами:
5952720
Репутация:
6527
|
|
Сообщение от Спойлер
package scriptconfig;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;
import core.gameserver.scripts.Functions;
import core.gameserver.scripts.ScriptFile;
import core.gameserver.utils.Util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ScriptConfig extends Functions implements ScriptFile
{
private static final Logger _log = LoggerFactory.getLogger(ScriptConfig.class);
private static final String dir = "./config/ScripsConfig";
private static ConcurrentHashMap properties;
@Override
public void onLoad()
{
properties = new ConcurrentHashMap();
LoadConfig();
_log.info("Loaded Service: ScripsConfig");
}
@Override
public void onReload()
{
onLoad();
}
@Override
public void onShutdown()
{}
public static void LoadConfig()
{
File files = new File(dir);
if (!files.exists())
_log.warn("WARNING! " + dir + " not exists! Config not loaded!");
else
parseFiles(files.listFiles());
}
private static void parseFiles(File[] files)
{
for (File f : files)
{
if (f.isHidden())
continue;
if (f.isDirectory() && !f.getName().contains("defaults"))
parseFiles(f.listFiles());
else if (f.getName().endsWith(".ini"))
{
try
{
InputStream is = new FileInputStream(f);
Properties p = new Properties();
p.load(is);
loadProperties(p);
}
catch (FileNotFoundException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
}
private static void loadProperties(Properties p)
{
for (String name : p.stringPropertyNames())
{
if (properties.get(name) != null)
{
properties.replace(name, p.getProperty(name).trim());
_log.info("Duplicate properties name \"" + name + "\" replaced with new value.");
}
else if (p.getProperty(name) == null)
_log.info("Null property for key " + name);
else
properties.put(name, p.getProperty(name).trim());
}
p.clear();
}
public static String get(String name)
{
if(properties.get(name) == null)
_log.warn("ConfigSystem: Null value for key: " + name);
return properties.get(name);
}
public static float getFloat(String name)
{
return getFloat(name, Float.MAX_VALUE);
}
public static boolean getBoolean(String name)
{
return getBoolean(name, false);
}
public static int getInt(String name)
{
return getInt(name, Integer.MAX_VALUE);
}
public static int[] getIntArray(String name)
{
return getIntArray(name, new int[0]);
}
public static int getIntHex(String name)
{
return getIntHex(name, Integer.decode("0xFFFFFF"));
}
public static byte getByte(String name)
{
return getByte(name, Byte.MAX_VALUE);
}
public static long getLong(String name)
{
return getLong(name, Long.MAX_VALUE);
}
public static double getDouble(String name)
{
return getDouble(name, Double.MAX_VALUE);
}
public static String get(String name, String def)
{
return get(name) == null ? def : get(name);
}
public static float getFloat(String name, float def)
{
return Float.parseFloat(get(name, String.valueOf(def)));
}
public static boolean getBoolean(String name, boolean def)
{
return Boolean.parseBoolean(get(name, String.valueOf(def)));
}
public static int getInt(String name, int def)
{
return Integer.parseInt(get(name, String.valueOf(def)));
}
public static int[] getIntArray(String name, int[] def)
{
return get(name, null) == null ? def : Util.parseCommaSeparatedIntegerArray(get(name, null));
}
public static int getIntHex(String name, int def)
{
if(!get(name, String.valueOf(def)).trim().startsWith("0x"))
return Integer.decode("0x"+get(name, String.valueOf(def)));
else
return Integer.decode(get(name, String.valueOf(def)));
}
public static byte getByte(String name, byte def)
{
return Byte.parseByte(get(name, String.valueOf(def)));
}
public static double getDouble(String name, double def)
{
return Double.parseDouble(get(name, String.valueOf(def)));
}
public static long getLong(String name, long def)
{
return Long.parseLong(get(name, String.valueOf(def)));
}
public static void set(String name, String param)
{
properties.replace(name, param);
}
public static void set(String name, Object obj)
{
set(name, String.valueOf(obj));
}
}
WTF? Мозгов что ли нету, что бы подобную хрень впиливать в эмуль так ещё и в сервисы
|
|
|

06.08.2015, 21:56
|
|
Флудер
Регистрация: 20.01.2015
Сообщений: 7,201
С нами:
5952720
Репутация:
6527
|
|
Квесты я не собираюсь тестить. Возьму для начала начальный квест
Проверка снабжения — Энциклопедия Lineage 2 смотрим. Теперь проверяем и видим, что квест то не верный, награда то выдаётся одна для всех, а посмотрим теперь на квест где заявлено, что реализован весь официальный контент:
[QUOTE="Спойлер"]
[COLOR="#363940"]
package quests;
import core.gameserver.model.base.ClassId;
import core.gameserver.model.instances.NpcInstance;
import core.gameserver.model.quest.Quest;
import core.gameserver.model.quest.QuestState;
import core.gameserver.network.l2.s2c.ExShowScreenMessage ;
import core.gameserver.network.l2.s2c.ExShowScreenMessage .ScreenMessageAlign;
import core.gameserver.scripts.ScriptFile;
public class _174_SupplyCheck extends Quest implements ScriptFile
{
@Override
public void onLoad()
{
}
@Override
public void onReload()
{
}
@Override
public void onShutdown()
{
}
int Marcela = 32173;
int Benis = 32170; // warehouse keeper
int Nika = 32167; // grocerer
//int Erinu = 32164; // weapon seller
//int Casca = 32139; // vice hierarch
int WarehouseManifest = 9792;
int GroceryStoreManifest = 9793;
//int WeaponShopManifest = 9794;
//int SupplyReport = 9795;
int WoodenBreastplate = 23;
int WoodenGaiters = 2386;
int LeatherTunic = 429;
int LeatherStockings = 464;
int WoodenHelmet = 43;
int LeatherShoes = 37;
int Gloves = 49;
public _174_SupplyCheck()
{
super(false);
addStartNpc(Marcela);
addTalkId(Benis, Nika); //Erinu, Casca
addQuestItem(WarehouseManifest, GroceryStoreManifest); // WeaponShopManifest, SupplyReport
}
@Override
public String onEvent(String event, QuestState qs, NpcInstance npc)
{
String htmltext = event;
if(event.equalsIgnoreCase("zerstorer_morsell_q0174 _04.htm"))
{
qs.setCond(1);
qs.setState(STARTED);
qs.playSound(SOUND_ACCEPT);
}
return htmltext;
}
@Override
public String onTalk(NpcInstance npc, QuestState st)
{
String htmltext = "noquest";
int npcId = npc.getNpcId();
int cond = st.getCond();
if(npcId == Marcela)
{
if(cond == 0)
{
if(st.getPlayer().getLevel() == 1)
{
st.exitCurrentQuest(true);
htmltext = "zerstorer_morsell_q0174_02.htm";
}
else
htmltext = "zerstorer_morsell_q0174_01.htm";
}
else if(cond == 1)
htmltext = "zerstorer_morsell_q0174_05.htm";
else if(cond == 2)
{
st.setCond(3);
st.takeItems(WarehouseManifest, -1);
htmltext = "zerstorer_morsell_q0174_06.htm";
}
else if(cond == 3)
htmltext = "zerstorer_morsell_q0174_07.htm";
else if(cond == 4)
{
if(st.getPlayer().getClassId().isMage() && !st.getPlayer().getClassId().equalsOrChildOf(Class Id.orcMage))
{
st.giveItems(LeatherTunic, 1);
st.giveItems(LeatherStockings, 1);
}
else
{
st.giveItems(WoodenBreastplate, 1);
st.giveItems(WoodenGaiters, 1);
}
st.giveItems(WoodenHelmet, 1);
st.giveItems(LeatherShoes, 1);
st.giveItems(Gloves, 1);
st.giveItems(ADENA_ID, 2466, true);
st.getPlayer().addExpAndSp(5672, 446);
if(st.getPlayer().getClassId().getLevel() == 1 && !st.getPlayer().getVarB("ng1"))
st.getPlayer().sendPacket(new ExShowScreenMessage(" Delivery duty complete.\nGo find the Newbie Guide.", 5000, ScreenMessageAlign.TOP_CENTER, true));
st.exitCurrentQuest(false);
htmltext = "zerstorer_morsell_q0174_12.htm";
}
/*
{
st.setCond(5);
st.takeItems(GroceryStoreManifest, -1);
htmltext = "zerstorer_morsell_q0174_08.htm";
}
else if(cond == 5)
htmltext = "zerstorer_morsell_q0174_09.htm";
else if(cond == 6)
{
st.setCond(7);
st.takeItems(WeaponShopManifest, -1);
st.giveItems(SupplyReport, 1);
htmltext = "zerstorer_morsell_q0174_10.htm";
}
else if(cond == 7)
htmltext = "zerstorer_morsell_q0174_11.htm";
else if(cond == 8)
{
if(st.getPlayer().getClassId().isMage() && !st.getPlayer().getClassId().equalsOrChildOf(Class Id.orcMage))
{
st.giveItems(LeatherTunic, 1);
st.giveItems(LeatherStockings, 1);
}
else
{
st.giveItems(WoodenBreastplate, 1);
st.giveItems(WoodenGaiters, 1);
}
st.giveItems(WoodenHelmet, 1);
st.giveItems(LeatherShoes, 1);
st.giveItems(Gloves, 1);
st.giveItems(ADENA_ID, 2466, true);
st.getPlayer().addExpAndSp(5672, 446, false, false);
if(st.getPlayer().getClassId().getLevel() == 1 && !st.getPlayer().getVarB("ng1"))
st.getPlayer().sendPacket(new ExShowScreenMessage(" Delivery duty complete.\nGo find the Newbie Guide.", 5000, ScreenMessageAlign.TOP_CENTER, true));
st.exitCurrentQuest(false);
htmltext = "zerstorer_morsell_q0174_12.htm";
}
*/
}
else if(npcId == Benis)
if(cond == 1)
{
st.setCond(2);
st.giveItems(WarehouseManifest, 1);
htmltext = "warehouse_keeper_benis_q0174_01.htm";
}
else
htmltext = "warehouse_keeper_benis_q0174_02.htm";
else if(npcId == Nika)
if(cond
|
|
|

06.08.2015, 22:12
|
|
Флудер
Регистрация: 20.01.2015
Сообщений: 7,201
С нами:
5952720
Репутация:
6527
|
|
Веселая система валидации байпасов который гордится гринд и заявляет типо он придумал и реализовал.
Смотрим и веселимся:
Сообщение от Спойлер
package core.gameserver.enums;
public enum HtmlActionScope
{
NPC_HTML,
NPC_QUEST_HTML,
COMMUNITY_BOARD_HTML,
TUTORIAL_HTML
}
Смотрим лыжу:
http://svn.l2jserver.com/trunk/L2J_S...tionScope.java
Видимо лыжа украла у гринда создав машину времени и раньше залив себе. а FBIagent вообще не достоин быть автором.
Дальше смотрим его мего защиту байпассов:
[QUOTE="Спойлер"]
[COLOR="#363940"]
package core.gameserver.utils;
import java.util.Locale;
import core.gameserver.enums.HtmlActionScope;
import core.gameserver.model.Player;
public class ActionCacheUtil
{
public static final char VAR_PARAM_START_CHAR = '$';
private static final void buildHtmlBypassCache(Player player, HtmlActionScope scope, String html)
{
String htmlLower = html.toLowerCase(Locale.ENGLISH);
int bypassEnd = 0;
int bypassStart = htmlLower.indexOf("=\"bypass ", bypassEnd);
int bypassStartEnd;
while (bypassStart != -1)
{
bypassStartEnd = bypassStart + 9;
bypassEnd = htmlLower.indexOf("\"", bypassStartEnd);
if (bypassEnd == -1)
{
break;
}
int hParamPos = htmlLower.indexOf("-h ", bypassStartEnd);
String bypass;
if ((hParamPos != -1) && (hParamPos _replaces = new ArrayList();
protected boolean have_appends = false;
public NpcHtmlMessage(Player player, int npcId, String filename, int val)
{
List appends = Scripts.dialogAppends.get(npcId);
if(appends != null && appends.size() > 0)
{
have_appends = true;
if(filename != null && filename.equalsIgnoreCase("npcdefault.htm"))
setHtml(""); // контент задается скриптами через DialogAppend_
else
setFile(filename);
String replaces = "";
// Добавить в конец странички текст, определенный в скриптах.
Object[] script_args = new Object[] { new Integer(val) };
for(ScriptClassAndMethod append : appends)
{
Object obj = Scripts.getInstance().callScripts(player, append.className, append.methodName, script_args);
if(obj != null)
replaces += obj;
}
if(!replaces.equals(""))
replace("", "\n" + Strings.bbParse(replaces) + "");
}
else
setFile(filename);
}
public NpcHtmlMessage(Player player, NpcInstance npc, String filename, int val)
{
this(player, npc.getNpcId(), filename, val);
_npcObjId = npc.getObjectId();
//FIXME [G1ta0] не есть истина, исправить
player.setLastNpc(npc);
replace("%npcId%", String.valueOf(npc.getNpcId()));
replace("%npcname%", npc.getName());
replace("%festivalMins%", SevenSignsFestival.getInstance().getTimeToNextFest ivalStr());
}
public NpcHtmlMessage(Player player, NpcInstance npc)
{
if(npc == null)
{
_npcObjId = 5;
player.setLastNpc(null);
}
else
{
_npcObjId = npc.getObjectId();
player.setLastNpc(npc);
}
}
public NpcHtmlMessage(int npcObjId)
{
_npcObjId = npcObjId;
}
public final NpcHtmlMessage setHtml(String text)
{
if(!text.contains(""))
text = "" + text + ""; //Message:
_html = text;
return this;
}
public final NpcHtmlMessage setFile(String file)
{
_file = file;
if(_file.startsWith("data/html/"))
{
_log.info("NpcHtmlMessage: need fix : " + file, new Exception());
_file = _file.replace("data/html/", "");
}
return this;
}
public NpcHtmlMessage replace(String pattern, String value)
{
if(pattern == null || value == null)
return this;
_replaces.add(pattern);
_replaces.add(value);
return this;
}
// npcstring-?.dat
public NpcHtmlMessage replaceNpcString(String pattern, NpcString npcString, Object... arg)
{
if(pattern == null)
return this;
if(npcString.getSize() != arg.length)
throw new IllegalArgumentException("Not valid size of parameters: " + npcString);
_replaces.add(pattern);
_replaces.add(HtmlUtils.htmlNpcString(npcString, arg));
return this;
}
@Override
protected void writeImpl()
{
Player player = getClient().getActiveChar();
if(player == null)
return;
if(_file != null) //TODO может быть не очень хорошо здесь это делать...
{
if(player.isGM())
Functions.sendDebugMessage(player, "HTML: " + _file);
String content = HtmCache.getInstance().getNotNull(_file, player);
String content2 = HtmCache.getInstance().getNullable(_file, player);
if(content2 == null)
setHtml(have_appends && _file.endsWith(".htm") ? "" : content);
else
setHtml(content);
}
for(int i = 0; i
|
|
|

06.08.2015, 22:14
|
|
Флудер
Регистрация: 20.01.2015
Сообщений: 7,201
С нами:
5952720
Репутация:
6527
|
|
А вот теперь задумайтесь, все его наработки так же могут быть портированы с l2j подобных сборок будьте осторожны
|
|
|

06.08.2015, 22:31
|
|
Флудер
Регистрация: 20.01.2015
Сообщений: 7,201
С нами:
5952720
Репутация:
6527
|
|
Опять таки вернёмся к реализации согласно официальному серверу. Давайте посмотрим такой механизм как Магазин(Итем-малл):
Смотрим пакеты:
Сообщение от Спойлер
package core.gameserver.network.l2.c2s;
public class RequestExBR_RecentProductList extends L2GameClientPacket
{
@Override
public void readImpl()
{
// триггер
}
@Override
public void runImpl()
{
/* L2Player activeChar = getClient().getActiveChar();
if(activeChar == null)
return;*/
//activeChar.sendMessage("triggered BrRecentProductList()");
}
}
Ага, а не реализован то пакет.
А реализации самих механизмов осталось на том же уровне, что предоставлено овером которая далеко не верная
|
|
|

06.08.2015, 22:38
|
|
Флудер
Регистрация: 20.01.2015
Сообщений: 7,201
С нами:
5952720
Репутация:
6527
|
|
Пошли по пакетам, которые до сих пор не реализованы:
Сообщение от Спойлер
public class WithdrawAlliance extends L2GameServerPacket
{
@Override
protected final void writeImpl()
{
writeC(0xAB);
//TODO d
}
}
ValidatePosition - сюда не смотреть, вы убьёте свои глаза и нервы
Сообщение от Спойлер
package core.gameserver.network.l2.s2c;
import core.gameserver.Config;
import core.gameserver.data.xml.holder.NpcHolder;
import core.gameserver.instancemanager.CursedWeaponsManag er;
import core.gameserver.model.Player;
import core.gameserver.model.Skill;
import core.gameserver.model.Zone;
import core.gameserver.model.base.Element;
import core.gameserver.model.base.Experience;
import core.gameserver.model.base.TeamType;
import core.gameserver.model.entity.events.GlobalEvent;
import core.gameserver.model.items.Inventory;
import core.gameserver.model.matching.MatchingRoom;
import core.gameserver.model.pledge.Alliance;
import core.gameserver.model.pledge.Clan;
import core.gameserver.skills.effects.EffectCubic;
import core.gameserver.utils.Location;
public class UserInfo extends L2GameServerPacket
{
private boolean can_writeImpl = false, partyRoom;
private int _runSpd, _walkSpd, _swimRunSpd, _swimWalkSpd, _flRunSpd, _flWalkSpd, _flyRunSpd, _flyWalkSpd, _relation;
private double move_speed, attack_speed, col_radius, col_height;
private int[][] _inv;
private Location _loc, _fishLoc;
private int obj_id, vehicle_obj_id, _race, sex, base_class, level, curCp, maxCp, _enchant, _weaponFlag;
private long _exp;
private int curHp, maxHp, curMp, maxMp, curLoad, maxLoad, rec_left, rec_have;
private int _str, _con, _dex, _int, _wit, _men, _sp, ClanPrivs, InventoryLimit;
private int _patk, _patkspd, _pdef, evasion, accuracy, crit, _matk, _matkspd;
private int _mdef, pvp_flag, karma, hair_style, hair_color, face, gm_commands, fame, vitality;
private int clan_id, clan_crest_id, ally_id, ally_crest_id, large_clan_crest_id;
private int private_store, can_crystalize, pk_kills, pvp_kills, class_id, agathion;
private int _abnormalEffect, _abnormalEffect2, noble, hero, mount_id, cw_level;
private int name_color, running, pledge_class, pledge_type, title_color, transformation;
private int defenceFire, defenceWater, defenceWind, defenceEarth, defenceHoly, defenceUnholy;
private int mount_type;
private String _name, title;
private EffectCubic[] cubics;
private Element attackElement;
private int attackElementValue;
private boolean isFlying, _allowMap;
private int talismans;
private boolean openCloak;
private double _expPercent;
private TeamType _team;
public UserInfo(Player player)
{
if(player.getTransformationName() != null)
{
_name = player.getTransformationName();
title = "";
clan_crest_id = 0;
ally_crest_id = 0;
large_clan_crest_id = 0;
cw_level = CursedWeaponsManager.getInstance().getLevel(player .getCursedWeaponEquippedId());
}
else
{
_name = player.getName();
Clan clan = player.getClan();
Alliance alliance = clan == null ? null : clan.getAlliance();
//
clan_id = clan == null ? 0 : clan.getClanId();
clan_crest_id = clan == null ? 0 : clan.getCrestId();
large_clan_crest_id = clan == null ? 0 : clan.getCrestLargeId();
//
ally_id = alliance == null ? 0 : alliance.getAllyId();
ally_crest_id = alliance == null ? 0 : alliance.getAllyCrestId();
cw_level = 0;
title = player.getTitle();
}
if(player.getPlayerAccess().GodMode && player.isInvisible())
title += "";
if(player.isPolymorphed())
if(NpcHolder.getInstance().getTemplate(player.getP olyId()) != null)
title += " - " + NpcHolder.getInstance().getTemplate(player.getPoly Id()).name;
else
title += " - Polymorphed";
if(player.isMounted())
{
_enchant = 0;
mount_id = player.getMountNpcId() + 1000000;
mount_type = player.getMountType();
}
else
{
_enchant = player.getEnchantEffect();
mount_id = 0;
mount_type = 0;
}
_weaponFlag = player.getActiveWeaponInstance() == null ? 0x14 : 0x28;
move_speed = player.getMovementSpeedMultiplier();
_runSpd = (int) (player.getRunSpeed() / move_speed);
_walkSpd = (int) (player.getWalkSpeed() / move_speed);
_flRunSpd = 0; // TODO
_flWalkSpd = 0; // TODO
if(player.isFlying())
{
_flyRunSpd = _runSpd;
_flyWalkSpd = _walkSpd;
}
else
{
_flyRunSpd = 0;
_flyWalkSpd = 0;
}
_swimRunSpd = player.getSwimSpeed();
_swimWalkSpd = player.getSwimSpeed();
_inv = new int[Inventory.PAPERDOLL_MAX][3];
for(int PAPERDOLL_ID : Inventory.PAPERDOLL_ORDER)
{
_inv[PAPERDOLL_ID][0] = player.getInventory().getPaperdollObjectId(PAPERDO LL_ID);
_inv[PAPERDOLL_ID][1] = player.getInventory().getPaperdollItemId(PAPERDOLL _ID);
_inv[PAPERDOLL_ID][2] = player.getInventory().getPaperdollAugmentationId(P APERDOLL_ID);
}
_relation = player.isClanLeader() ? 0x40 : 0;
for(GlobalEvent e : player.getEvents())
_relation = e.getUserRelation(player, _relation);
_loc = player.getLoc();
obj_id = player.getObjectId();
vehicle_obj_id = player.isInBoat() ? player.getBoat().getObjectId() : 0x00;
_race = player.getRace().ordinal();
sex = player.getSex();
base_class = player.getBaseClassId();
level = player.getLevel();
_exp = player.getExp();
_expPercent = Experience.getExpPercent(player.getLevel(), player.getExp());
_str = player.getSTR();
_dex = player.getDEX();
_con = player.getCON();
_int = player.getINT();
_wit = player.getWIT();
_men = player.getMEN();
curHp = (int) player.getCurrentHp();
maxHp = player.getMaxHp();
curMp = (int) player.getCurrentMp();
maxMp = player.getMaxMp();
curLoad = player.getCurrentLoad();
maxLoad = player.getMaxLoad();
_sp = player.getIntSp();
_patk = player.getPAtk(null);
_patkspd = player.getPAtkSpd();
_pdef = player.getPDef(null);
evasion = player.getEvasionRate(null);
accuracy = player.getAccuracy();
crit = player.getCriticalHit(null, null);
_matk = player.getMAtk(null, null);
_matkspd = player.getMAtkSpd();
_mdef = player.getMDef(null, null);
pvp_flag = Config.RVRMODE_ENABLE ? 0 : player.getPvpFlag(); // 0=white, 1=purple, 2=purpleblink
karma = player.getKarma();
attack_speed = player.getAttackSpeedMultiplier();
col_radius = player.getColRadius();
col_height = player.getColHeight();
if(player.isBeautyShopWearing() && player.getWearHairStyle() != -1)
hair_style = player.getWearHairStyle();
else
hair_style = player.getHairStyle();
if(player.isBeautyShopWearing() && player.getWearHairColor() != -1)
hair_color = player.getWearHairColor();
else
hair_color = player.getHairColor();
if(player.isBeautyShopWearing() && player.getWearFace() != -1)
face = player.getWearFace();
else
face = player.getFace();
gm_commands = player.isGM() || player.getPlayerAccess().CanUseGMCommand ? 1 : 0;
// builder level активирует в клиенте админские команды
clan_id = player.getClanId();
ally_id = player.getAllyId();
private_store = player.getPrivateStoreType();
can_crystalize = player.getSkillLevel(Skill.SKILL_CRYSTALLIZE) > 0 ? 1 : 0;
pk_kills = player.getPkKills();
pvp_kills = player.getPvpKills();
cubics = player.getCubics().toArray(new EffectCubic[player.getCubics().size()]);
_abnormalEffect = player.getAbnormalEffect();
_abnormalEffect2 = player.getAbnormalEffect2();
ClanPrivs = player.getClanPrivileges();
rec_left = player.getRecomLeft(); //c2 recommendations remaining
rec_have = player.getRecomHave(); //c2 recommendations received
InventoryLimit = player.getInventoryLimit();
class_id = player.getClassId().getId();
maxCp = player.getMaxCp();
curCp = (int) player.getCurrentCp();
_team = player.getTeam();
noble = player.isNoble() || player.isGM() && Config.GM_HERO_AURA ? 1 : 0; //0x01: symbol on char menu ctrl+I
hero = player.isHero() || player.isFakeHero() || player.isGM() && Config.GM_HERO_AURA ? 1 : 0; //0x01: Hero Aura and symbol
//fishing = _cha.isFishing() ? 1 : 0; // Fishing Mode
_fishLoc = player.getFishLoc();
name_color = player.getNameColor();
running = player.isRunning() ? 0x01 : 0x00; //changes the Speed display on Status Window
pledge_class = player.getPledgeClass();
pledge_type = player.getPledgeType();
title_color = player.getTitleColor();
transformation = player.getTransformation();
attackElement = player.getAttackElement();
attackElementValue = player.getAttack(attackElement);
defenceFire = player.getDefence(Element.FIRE);
defenceWater = player.getDefence(Element.WATER);
defenceWind = player.getDefence(Element.WIND);
defenceEarth = player.getDefence(Element.EARTH);
defenceHoly = player.getDefence(Element.HOLY);
defenceUnholy = player.getDefence(Element.UNHOLY);
agathion = player.getAgathionId();
fame = player.getFame();
vitality = player.getNevitSystem().isBlessingActive() ? Config.VITALITY_LEVELS[4] : (int) player.getVitality();
partyRoom = player.getMatchingRoom() != null && player.getMatchingRoom().getType() == MatchingRoom.PARTY_MATCHING && player.getMatchingRoom().getLeader() == player;
isFlying = player.isInFlyingTransform();
talismans = player.getTalismanCount();
openCloak = player.getOpenCloak();
_allowMap = player.isActionBlocked(Zone.BLOCKED_ACTION_MINIMAP );
can_writeImpl = true;
}
@Override
protected final void writeImpl()
{
if(!can_writeImpl)
return;
writeC(0x32);
writeD(_loc.x);
writeD(_loc.y);
writeD(_loc.z + Config.CLIENT_Z_SHIFT);
writeD(vehicle_obj_id);
writeD(obj_id);
writeS(_name);
writeD(_race);
writeD(sex);
writeD(base_class);
writeD(level);
writeQ(_exp);
writeF(_expPercent);
writeD(_str);
writeD(_dex);
writeD(_con);
writeD(_int);
writeD(_wit);
writeD(_men);
writeD(maxHp);
writeD(curHp);
writeD(maxMp);
writeD(curMp);
writeD(_sp);
writeD(curLoad);
writeD(maxLoad);
writeD(_weaponFlag);
for(int PAPERDOLL_ID : Inventory.PAPERDOLL_ORDER)
writeD(_inv[PAPERDOLL_ID][0]);
for(int PAPERDOLL_ID : Inventory.PAPERDOLL_ORDER)
writeD(_inv[PAPERDOLL_ID][1]);
for(int PAPERDOLL_ID : Inventory.PAPERDOLL_ORDER)
writeD(_inv[PAPERDOLL_ID][2]);
writeD(talismans);
writeD(openCloak ? 0x01 : 0x00);
writeD(_patk);
writeD(_patkspd);
writeD(_pdef);
writeD(evasion);
writeD(accuracy);
writeD(crit);
writeD(_matk);
writeD(_matkspd);
writeD(_patkspd);
writeD(_mdef);
writeD(pvp_flag);
writeD(karma);
writeD(_runSpd);
writeD(_walkSpd);
writeD(_swimRunSpd); // swimspeed
writeD(_swimWalkSpd); // swimspeed
writeD(_flRunSpd);
writeD(_flWalkSpd);
writeD(_flyRunSpd);
writeD(_flyWalkSpd);
writeF(move_speed);
writeF(attack_speed);
writeF(col_radius);
writeF(col_height);
writeD(hair_style);
writeD(hair_color);
writeD(face);
writeD(gm_commands);
writeS(title);
writeD(clan_id);
writeD(clan_crest_id);
writeD(ally_id);
writeD(ally_crest_id);
// 0x40 leader rights
// siege flags: attacker - 0x180 sword over name, defender - 0x80 shield, 0xC0 crown (|leader), 0x1C0 flag (|leader)
writeD(_relation);
writeC(mount_type); // mount type
writeC(private_store);
writeC(can_crystalize);
writeD(pk_kills);
writeD(pvp_kills);
writeH(cubics.length);
for(EffectCubic cubic : cubics)
writeH(cubic == null ? 0 : cubic.getId());
writeC(partyRoom ? 0x01 : 0x00); //1-find party members
writeD(_abnormalEffect);
writeC(isFlying ? 0x02 : 0x00);
writeD(ClanPrivs);
writeH(rec_left);
writeH(rec_have);
writeD(mount_id);
writeH(InventoryLimit);
writeD(class_id);
writeD(0x00); // special effects? circles around player...
writeD(maxCp);
writeD(curCp);
writeC(_enchant);
writeC(_team.ordinal());
writeD(large_clan_crest_id);
writeC(noble);
writeC(hero);
writeC(0x00);
writeD(_fishLoc.x);
writeD(_fishLoc.y);
writeD(_fishLoc.z);
writeD(name_color);
writeC(running);
writeD(pledge_class);
writeD(pledge_type);
writeD(title_color);
writeD(cw_level);
writeD(transformation); // Transformation id
// AttackElement (0 - Fire, 1 - Water, 2 - Wind, 3 - Earth, 4 - Holy, 5 - Dark, -2 - None)
writeH(attackElement.getId());
writeH(attackElementValue); // AttackElementValue
writeH(defenceFire); // DefAttrFire
writeH(defenceWater); // DefAttrWater
writeH(defenceWind); // DefAttrWind
writeH(defenceEarth); // DefAttrEarth
writeH(defenceHoly); // DefAttrHoly
writeH(defenceUnholy); // DefAttrUnholy
writeD(agathion);
// T2 Starts
writeD(fame); // Fame
writeD(_allowMap ? 1 : 0); // Minimap on Hellbound
writeD(vitality); // Vitality Points
writeD(_abnormalEffect2);
}
}
UserInfo.java - Откуда там нули? Ведь все реализовано согласно официальному серверу
Сообщение от Спойлер
package core.gameserver.network.l2.s2c;
import core.gameserver.model.Player;
import core.gameserver.model.instances.DoorInstance;
import core.gameserver.model.instances.StaticObjectInstan ce;
public class StaticObject extends L2GameServerPacket
{
private final int _staticObjectId;
private final int _objectId;
private final int _type;
private final int _isTargetable;
private final int _meshIndex;
private final int _isClosed;
private final int _isEnemy;
private final int _maxHp;
private final int _currentHp;
private final int _showHp;
private final int _damageGrade;
public StaticObject(StaticObjectInstance obj)
{
_staticObjectId = obj.getUId();
_objectId = obj.getObjectId();
_type = 0;
_isTargetable = 1;
_meshIndex = obj.getMeshIndex();
_isClosed = 0;
_isEnemy = 0;
_maxHp = 0;
_currentHp = 0;
_showHp = 0;
_damageGrade = 0;
}
public StaticObject(DoorInstance door, Player player)
{
_staticObjectId = door.getDoorId();
_objectId = door.getObjectId();
_type = 1;
_isTargetable = door.getTemplate().isTargetable() ? 1 : 0;
_meshIndex = 1;
_isClosed = door.isOpen() ? 0 : 1; //opened 0 /closed 1
_isEnemy = door.isAutoAttackable(player) ? 1 : 0;
_currentHp = (int) door.getCurrentHp();
_maxHp = door.getMaxHp();
_showHp = door.isHPVisible() ? 1 : 0; //TODO [G1ta0] статус двери для осаждающих
_damageGrade = door.getDamage();
}
@Override
protected final void writeImpl()
{
writeC(0x9f);
writeD(_staticObjectId);
writeD(_objectId);
writeD(_type);
writeD(_isTargetable);
writeD(_meshIndex);
writeD(_isClosed);
writeD(_isEnemy);
writeD(_currentHp);
writeD(_maxHp);
writeD(_showHp);
writeD(_damageGrade);
}
}
Всё так же не доделан статус двери для осаждающих
Сообщение от Спойлер
package core.gameserver.network.l2.s2c;
public class SkillRemainSec extends L2GameServerPacket
{
@Override
protected void writeImpl()
{
writeC(0xD8);
//TODO ddddddd
}
}
Ну классные пакеты.
Сообщение от Спойлер
package core.gameserver.network.l2.s2c;
public class ShowRadar extends L2GameServerPacket
{
@Override
protected final void writeImpl()
{
writeC(0xAA);
//TODO ddddd
}
}
ShopPreviewList - Опять через жопу работает:
Сообщение от Спойлер
public static int getWearPrice(ItemTemplate item)
{
for(int costume : ItemTemplate.ITEM_ID_FORMAL_WEAR)
if(item.getItemId() == costume)
return 10000;
switch(item.getItemGrade())
{
case D:
return 50;
case C:
return 100;
//TODO: Не известно сколько на оффе стоит примерка B - S84 ранга.
case B:
return 200;
case A:
return 500;
case S:
return 1000;
case S80:
return 2000;
case S84:
return 2500;
default:
return 10;
}
}
И данный человек с 2011 года толком и ничего не сделал
Сообщение от Спойлер
package core.gameserver.network.l2.s2c;
/**
* Пример дампа:
* 0000: 92 2c 05 10 58 77 bb 0f 00 00 00 00 00 00 00 00 .,..Xw..........
* 0010: 54 ff ff b0 42 fe ff 14 ff ff ff 00 00 00 00 00 T...B...........
* 0020: 00 00 00 00 00 f0 3f 00 00 00 00 00 00 f0 3f 00 ......?.......?.
* 0030: 00 00 00 00 00 3e 40 00 00 00 00 00 00 3e 40 00 .....>@......>@.
* 0040: 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00 ...............
*/
public class ServerObjectInfo extends L2GameServerPacket
{
@Override
protected void writeImpl()
{
writeC(0x92);
// TODO ddSdddddffffdddd ServerObjectInfo ID:%d, ClassID:%d, CanBeAttacked:%d, X:%d, Y:%d, Z:%d
}
}
Не ну реализация оставляет желать лучшего. И это можно считать реализован весь официальный контент? Нет. Завтра дополню темам по пакетам.
|
|
|

06.08.2015, 22:43
|
|
Флудер
Регистрация: 20.01.2015
Сообщений: 7,201
С нами:
5952720
Репутация:
6527
|
|
Я вот помню, мне написал пойнтер( @b3trayer):
Вы никогда не задумывались какой максимальный размер у пакета в л2? Ну хотя бы приблизительно Подумайте над этим, а после этого скажите есть ли резон выделять по 64 кб на главный буфер и вспомогательные (принадлежащие конкретно клиентам). Так же, подумайте, чем отличается директ буфер от хип буфера в джаве и как директ буфер работает с сетевой картой и какой его размер наиболее эффективен. Так же рекомендую задуматься, как начинает работать селектор при количестве коннектов более 1000. Ну и конечно же провести микро-тесты, я уверяю, что Вы откроете много нового для себя. И это разьяснение только по одной, малой части, из мною перечисленного
Так вот сеть осталась та же ниошная ничем не изменилась у этих исходников. А теперь смотрим например даже эту тему DDOS гейм порта Классный эмулятор, достойный. Завтра продолжу писать про пакеты, и думаю многим разработчикам станет интересны некоторые офф фишки
|
|
|
|
 |
|
|
Здесь присутствуют: 1 (пользователей: 0 , гостей: 1)
|
|
|
|