Ассоциативные массивы

 

awarm

разработчик l2j-сервера

Вроде давно шла речь, а как с ними работать, так нигде и нету
 
+
-
edit
 

Diamond

втянувшийся

Пытаюсь написать вот такой запрос:
"SELECT * FROM characters WHERE account_name = 'admin'" query "char_name" p@
вроде аналогично указано в примере. Но не работает :(

Пишет ошибку:

java.lang.NoSuchMethodException: java.lang.Integer.getchar_name()
java.lang.NoSuchMethodException: java.lang.Integer.getchar_name()
at java.lang.Class.getMethod(Unknown Source)
at ru.balancer.jbforth.words.Java$dget.exec(Java.java:160)
at ru.balancer.jbforth.Word.exec(Word.java:56)
at ru.balancer.JBForth.do_word(JBForth.java:398)
at ru.balancer.JBForth.do_code(JBForth.java:248)
at ru.balancer.JBForth.do_code(JBForth.java:218)
at ru.balancer.JBForth.exec(JBForth.java:138)
at ru.balancer.JBForth.execp(JBForth.java:149)
at net.sf.l2j.gameserver.clientpackets.RequestBypassToServer.runImpl(Req
uestBypassToServer.java:124)
at net.sf.l2j.gameserver.clientpackets.ClientBasePacket.run(ClientBasePa
cket.java:37)
at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
at java.util.concurrent.FutureTask$Sync.innerRun(Unknown Source)
at java.util.concurrent.FutureTask.run(Unknown Source)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.
access$301(Unknown Source)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.
run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source
)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)

В стеке вроде как массив появляется:

Stack: [{z=-3773, y=142832, x=73897, hairColor=0, obj_Id=268465682, clan_privs=2
047, account_name=admin, sex=true, title=, nochannel=0, rec_left=11, accesslevel
=200, hairStyle=0, lastAccess=1148634174, pvpkills=0, face=0, clanid=268474130,
ccraftslots=50, pkkills=1, heading=33568, char_name=admin, online=true, wantspea
ce=0, onlinetime=90221, dcraftslots=50, deletetime=0, deleteclan=0, karma=9600,
rec_have=0}]

Как либо иначе вытащить оттуда значения не могу, т.к. нигде не написано как пользоваться такими массивами.
 
+
-
edit
 

Balancer

администратор
★★★★★
[{z=-3773, y=142832, x=73897, hairColor=0, obj_Id=268465682, clan_privs=2
047, account_name=admin, sex=true, title=, nochannel=0, rec_left=11, accesslevel
=200, hairStyle=0, lastAccess=1148634174, pvpkills=0, face=0, clanid=268474130,
ccraftslots=50, pkkills=1, heading=33568, char_name=admin, online=true, wantspea
ce=0, onlinetime=90221, dcraftslots=50, deletetime=0, deleteclan=0, karma=9600,
rec_have=0}]

Как либо иначе вытащить оттуда значения не могу

"z" m@ прочитает из хэшмапа значение z.
"account_name" m@ прочитает account_name.

Ошибку же выдаёт, так как query возвращает на стеке первым параметром код ошибки. А ты от него хочешь вызвать getchar_name() метод (именно такой метод вызывает "char_name" p@).

Тебе нужно проверить или просто сбросить (drop) код ошибки.
Останется спискок _хэшмапов_.

Если нужна одна только запись, прочитать её из списка можно, например, по "0 list@" - прочесть первый элемент списка.

Останется хэшмап.

Из него уже можешь читать по m@ нужные значания.

"SELECT * FROM characters WHERE account_name = 'admin'" query drop
0 list@
"char_name" m@
 
+
-
edit
 

Diamond

втянувшийся

Спасибо, вот теперь понятно :)

Еще вопрос, как быть когда mysql возвращает несколько строчек, и нужно в каждой выбрать например поле char_name и запихать например в массив? Вроде бы вот так должно работать:

"SELECT * FROM characters'" parse query 0 DO
n list@
n 1 + to n (так писать или короче можно? :) )
"char_name" m@ .
LOOP
 
+
-
edit
 

Diamond

втянувшийся

dup забыл :)

"SELECT * FROM characters'" parse query 0 DO
dup n list@
n 1 + to n (так писать или короче можно? :) )
"char_name" m@ .
LOOP

Проверил, так работает, только почему query возвращат всегда 0? Она же вроде число строк должна возвращать.. Как тогда do параметр задавать?
 

Styx

разработчик l2j-сервера
query верхним параметром возвращает на стеке код ошибки, а не число строк

ты можешь сделать так:

"SELECT ...." query
?dup IF . drop exit THEN
'"char_name" m@ .' do-list
...and what better way to say goodbye than to kill everyone in sight? © Syntari  
+
-
edit
 

Balancer

администратор
★★★★★
Проверил, так работает, только почему query возвращат всегда 0? Она же вроде число строк должна возвращать..
 


Нет, она возвращает код ошибки. 0 - всё ок. Не ноль - на стеке ошибка (можно её распечатать). Примерно так:

.... query ?dup if type exit then ...

>Как тогда do параметр задавать?

А зачем? Тебе возвращается список. Вот и работай с ним как со списком по do-list. Если же именно циклом do .. loop пройти нужно, то используй list# - возвращает размер списка

... query drop
dup list# 0 swap ?do
dup i list@ .
loop
drop

Этот код распечатает циклом do .. loop все элементы списка.
 
+
-
edit
 

Diamond

втянувшийся

До do-list и list# еще не докопался ;D
Буквально второй день форт учу :)
Спасибо, с массивами вроде разобрался, дальше кажись сам пойму.
 
+
-
edit
 

Diamond

втянувшийся

А вот тут написано что она возвращает число строк :)
http://la2.balancer.ru/wiki/index.php/Работа_с_SQL
 
+
-
edit
 

Diamond

втянувшийся

?dup IF . drop exit THEN
'"admin" m@ .' do-list

После этого упал весь форт ;D
Перестало работать абсолютно все связанное с фортом, даже после рестарта :)
 
+
-
edit
 

Diamond

втянувшийся

Вроде бы последний вопрос :)
Как имея имя чара телепортировать его в заданные координаты? Т.е. он не текущий, и не выделен таргетом.
 
+
-
edit
 

Balancer

администратор
★★★★★
Вроде бы последний вопрос :)
Как имея имя чара телепортировать его в заданные координаты? Т.е. он не текущий, и не выделен таргетом.
 


find_player вернёт тебе одентификатор игрока по имени (естественно - только онлайнового).

Дальше или
x y z player teleport_player_to

или

"x y z jump" player do-player

Т.е.

123456 78901 -4500 "vasya" find_player teleport_player_to

или

"123456 78901 -4500 jump" "vasya" find_player do-player

...

Кстати, JBForth немного обновлён - Changeset 19 – JBForth
 
+
-
edit
 

Diamond

втянувшийся

{
{ 122068 -221032 -3674 }
{ 194628 -183403 0571 }
{ -115197 222523 -2948 }
{ 177643 -177243 -544 }
{ 63853 29202 -3841 }
} value team1-points

"SELECT * FROM arena_team where team=1" query ?dup IF . drop exit THEN
'"name" m@ team1_list +list' do-list

team1_list ._s list> 0 ._s ?DO
find_player >r team1-points I list@ list-rev> drop r> ._s teleport_player_to
LOOP

В точке где указано ._s выводит: 122068 -221032 -3674 player 'admin'

И далее пишет что ошибка в слове TELEPORT_PLAYER_TO

В чем может быть дело?
 
Это сообщение редактировалось 28.05.2006 в 06:16
+
-
edit
 

Diamond

втянувшийся

Поменял teleport_player_to на teleport-char-to, заработало :)

Теперь телепортирует, но после этого пишет почему-то ошибку в слове >R
Не понимаю почему, ведь оно нормально работает... Разве что цикл второй раз выполняется, но я проверял, перед ?DO стоит 1 0

team1_list list> 0 ?DO
find_player >R team1-points I list@ list-rev> drop R> teleport-char-to
LOOP
 
Это сообщение редактировалось 28.05.2006 в 06:15
+
-
edit
 

Diamond

втянувшийся

Вобщем заработало, но только так:

team1_list dup list# 0 ?DO
list> drop find_player >R team1-points I list@ list-rev> drop R> teleport-char-to
LOOP

Странно, прежний вариант не хуже был :)
 
+
-
edit
 

Diamond

втянувшийся

: pvp_paralyze
team1_list dup list# 0 ?DO
list> find_player drop c.paralyze
LOOP

team2_list dup list# 0 ?DO
list> drop find_player c.paralyze
LOOP
;
Имеется список имен (для двух команд игроков) хочется парализовать их всех, но c.paralyze как и teleport_player_to не хочет принимать на входе результат find_player :( (однако teleport-char-to работает)
 
+
-
edit
 

Balancer

администратор
★★★★★
list> find_player
 


list> возвращает на вершине стека число элементов, выдернутых из списка

{ 1 2 3 } list> даст на стеке 3 2 1 3 (кажущийся "обратный" порядок именно кажущийся - первый элемент списка - на вершине стека, если нужен обратный порядок, то list-rev> )

Соответственно, find_player ищет игрока с числовым именем :)

...

Вообще, не ленитесь перед каждым "неработающим" словом выводить на печать стек (.s в текущий поток вывода или ._s - в stdout). Сразу станет понятно, что чего-то не хватает :)
 
+
-
edit
 

Diamond

втянувшийся

Уже не по теме, но заодно спрошу - как определить уровень игрока? Каким словом?
 

Murkt

Pythoneer

"Level" p. Возможно работает просто level@
[team Їжачки - сумні падлюки]  
+
-
edit
 

Diamond

втянувшийся

"Level" p. Возможно работает просто level@
 

Хм. Я вроде пробовал - не работает. Я ж это первым делом попробовал :)
Ладно, сейчас еще раз попробую, может ошибся.
 

Murkt

Pythoneer

Может ты маленькую букву L написал в "Level". Это же не паскаль, здесь критично.
[team Їжачки - сумні падлюки]  
+
-
edit
 
"getLevel" 0 jget
Пытаясь понять рекурсию, следи за тем, чтобы она не поняла тебя первой...  
+
-
edit
 

masterXL

разработчик OpenWorlds
player@ "Level" p@
Трудно быть богом... Не веришь? Спроси любого админа! можешь спросить у меня 175506816 ServerIP=193.41.172.19 Перенос доступен  

Murkt

Pythoneer

"getLevel" 0 jget
 

ну так сокращение этой записи и выглядит как "Level" p@
[team Їжачки - сумні падлюки]  
AD Реклама Google — средство выживания форумов :)
+
-
edit
 

Diamond

втянувшийся

Всем спасибо, да, оказывается маленькую L написал.
Наконец-то доделал то что хотел, вышло неплохо :)

Описание:
Игрок подходит к Arena Manager, создает бой. Указывает:
- ставку (10к - 1кк)
- размер команд (например 2 vs 3)
- диапазон уровней команд (например 45-47 vs 40-42)
- время до начала (от 1 до 10 минут)
Далее идет отсчет времени, каждую минуту выводится аннонс с текстом "игрок такой-то создал бой с параметрами такими-то, до начала столько-то минут"
В это время любые желающие (и подходящие по уровню) могут зарегистрироваться либо за, либо против него, заплатив указанную сумму.
Как только время истекает, все зарегистрировавшиеся телепортируются на арену, в четко определенные позиции.
Парализуются на 30 сек (время, выделенное для того чтобы все успели телепортироваться), потом паралич снимается и дается команда на старт.
Убитые парализуются до окончания боя, чтобы не помогали. В конце автоматически определяются победители, и все вложенные деньги делятся между ними.

Все работает, вроде бы без ошибок, проверял на игроках, им понравилось :)

Есть один недостаток - посторонние игроки могут вмешиваться, но надеюсь есть какой-либо метод этого избежать? Нужен способ отследить атаку незарегистрированного игрока, чтобы например парализовать либо кинуть в тюрьму ненадолго.

Если что-то написано неправильно или невыгодно или просто некрасиво - поправьте, это мое первое творение на форте :)

ps: огромное спасибо балансеру и masterXL за помощь :)
 
Это сообщение редактировалось 07.06.2006 в 13:28

в начало страницы | новое
 
Поиск
Поддержка
Поддержи форум!
ЯндексЯндекс. ДеньгиХочу такую же кнопку
Настройки
Твиттер сайта
Статистика
Рейтинг@Mail.ru