PDA

Просмотр полной версии : Мифы о заточке в Lineage II


DzumoHu4
05.04.2009, 12:41
Видел много тем на разных форумах про заточки, методы точки всякие "Баги" и про "способы" заточки, и скажу прямо это Глупость.
Существует 3 типа серверов.
Java сервера различных команд.(L2j,L2Free,etc)
C++ сервера обычно самописи etc...
Ну и офф Lineage.com.
В каждом по своему реализована функция Random.А значит и процесс заточки в зависимости от платформы отличается
Бред про "Корейский рандом" прошу засунуть в кладовку сумасшедших умозаключений.
поскольку официально проект C успешно загнулся, поговорим про самую распространённую платформу java.
Рандом в Java серверах реализован классом java.security.SecureRandom который импортируется из rt.jar который идёт в комплекте с Java Development Kit компании Sun Microsystems.
В классе Рандом реализован вот такой вот нехитрой функцией
package java.security;
import java.io.Serializable;
import java.util.Random;
import java.util.Enumeration;
public class SecureRandom extends Random
{
long counter = 0;
MessageDigest digest = null;
Provider provider = null;
byte[] randomBytes = null;
int randomBytesUsed = 0;
SecureRandomSpi secureRandomSpi = null;
byte[] state = null;
public SecureRandom()
{
Provider p[] = Security.getProviders();

String key;
String classname = null;
int i, flag = 0;
Enumeration e;
for (i = 0; i < p.length; i++)
{
e = p[i].propertyNames();
while (e.hasMoreElements())
{
key = (String) e.nextElement();
if (key.startsWith("SecureRandom."))
if ((classname = p[i].getProperty(key)) != null)
break;
}
if (classname != null)
break;
}

//if( classname == null)
// throw new NoSuchAlgorithmException();

try
{
this.secureRandomSpi =
(SecureRandomSpi) Class.forName(classname).newInstance();

//s.algorithm = algorithm;
this.provider = p[i];
}
catch (ClassNotFoundException cnfe)
{
//throw new NoSuchAlgorithmException("Class not found");
}
catch (InstantiationException ie)
{
//throw new NoSuchAlgorithmException("Class instantiation failed");
}
catch (IllegalAccessException iae)
{
//throw new NoSuchAlgorithmException("Illegal Access");
}
}
public SecureRandom(byte[] seed)
{
this();
setSeed(seed);
}
protected SecureRandom(SecureRandomSpi secureRandomSpi, Provider provider)
{
this.secureRandomSpi = secureRandomSpi;
this.provider = provider;
}

public static SecureRandom getInstance(String algorithm) throws
NoSuchAlgorithmException
{
Provider p[] = Security.getProviders();

//Format of Key: SecureRandom.algname
StringBuffer key = new StringBuffer("SecureRandom.");
key.append(algorithm);

String classname = null;
int i;
for (i = 0; i < p.length; i++)
{
if ((classname = p[i].getProperty(key.toString())) != null)
break;
}

if (classname == null)
throw new NoSuchAlgorithmException();

try
{
return new SecureRandom((SecureRandomSpi) Class.forName(classname).
newInstance(), p[i]);
}
catch (ClassNotFoundException cnfe)
{
throw new NoSuchAlgorithmException("Class not found");
}
catch (InstantiationException ie)
{
throw new NoSuchAlgorithmException("Class instantiation failed");
}
catch (IllegalAccessException iae)
{
throw new NoSuchAlgorithmException("Illegal Access");
}

}


public static SecureRandom getInstance(String algorithm,
String provider) throws
NoSuchAlgorithmException, NoSuchProviderException
{
Provider p = Security.getProvider(provider);
if (p == null)
throw new NoSuchProviderException();

//Format of Key: SecureRandom.algName
StringBuffer key = new StringBuffer("SecureRandom.");
key.append(algorithm);

String classname = p.getProperty(key.toString());
if (classname == null)
throw new NoSuchAlgorithmException();

try
{
return new SecureRandom((SecureRandomSpi) Class.forName(classname).
newInstance(), p);
}
catch (ClassNotFoundException cnfe)
{
throw new NoSuchAlgorithmException("Class not found");
}
catch (InstantiationException ie)
{
throw new NoSuchAlgorithmException("Class instantiation failed");
}
catch (IllegalAccessException iae)
{
throw new NoSuchAlgorithmException("Illegal Access");
}

}
public final Provider getProvider()
{
return provider;
}


public void setSeed(byte[] seed)
{
secureRandomSpi.engineSetSeed(seed);
}


public void setSeed(long seed)
{

if (secureRandomSpi != null)
{
byte tmp[] = { (byte) (0xff & (seed >> 56)),
(byte) (0xff & (seed >> 48)),
(byte) (0xff & (seed >> 40)),
(byte) (0xff & (seed >> 32)),
(byte) (0xff & (seed >> 24)),
(byte) (0xff & (seed >> 16)),
(byte) (0xff & (seed >> 8)),
(byte) (0xff & seed)
};
secureRandomSpi.engineSetSeed(tmp);
}
}
public void nextBytes(byte[] bytes)
{
randomBytesUsed += bytes.length;
counter++;
secureRandomSpi.engineNextBytes(bytes);
}


protected final int next(int numBits)
{
if (numBits == 0)
return 0;

byte tmp[] = new byte[numBits / 8 + (1 * (numBits % 8))];

secureRandomSpi.engineNextBytes(tmp);
randomBytesUsed += tmp.length;
counter++;

int ret = 0;

for (int i = 0; i < tmp.length; i++)
ret |= tmp[i] << (8 * i);

return ret;
}

public static byte[] getSeed(int numBytes)
{
byte tmp[] = new byte[numBytes];

new Random().nextBytes(tmp);
return tmp;
//return secureRandomSpi.engineGenerateSeed( numBytes );
}

public byte[] generateSeed(int numBytes)
{
return secureRandomSpi.engineGenerateSeed(numBytes);
}

}

}
после чего на него давят RIPEMD-160. и лишь затем мы получаем рзультат вида(ура заточилось и б"ять сломалась)
Возникает вопрос а откуда берётся seed?
А Зернышко друзья мои берётся из Алгоритма Mersenne Twister
package net.sf.l2j.util;

import java.util.Random;

public class MTRandom extends Random {

private static final long serialVersionUID = -515082678588212038L;

private final static int UPPER_MASK = 0x80000000;
private final static int LOWER_MASK = 0x7fffffff;

private final static int N = 624;
private final static int M = 397;
private final static int MAGIC[] = { 0x0, 0x9908b0df };
private final static int MAGIC_FACTOR1 = 1812433253;
private final static int MAGIC_FACTOR2 = 1664525;
private final static int MAGIC_FACTOR3 = 1566083941;
private final static int MAGIC_MASK1 = 0x9d2c5680;
private final static int MAGIC_MASK2 = 0xefc60000;
private final static int MAGIC_SEED = 19650218;
private final static long DEFAULT_SEED = 5489L;

private transient int[] mt;
private transient int mti;
private transient boolean compat = false;

// Temporary buffer used during setSeed(long)
private transient int[] ibuf;

public MTRandom() { }

public MTRandom(boolean compatible) {
super(0L);
compat = compatible;
setSeed(compat?DEFAULT_SEED:System.currentTimeMill is());
}

public MTRandom(long seed) {
super(seed);
}

public MTRandom(byte[] buf) {
super(0L);
setSeed(buf);
}

public MTRandom(int[] buf) {
super(0L);
setSeed(buf);
}

private final void setSeed(int seed) {


if (mt == null) mt = new int[N];

// ---- Begin Mersenne Twister Algorithm ----
mt[0] = seed;
for (mti = 1; mti < N; mti++) {
mt[mti] = (MAGIC_FACTOR1 * (mt[mti-1] ^ (mt[mti-1] >>> 30)) + mti);
}
// ---- End Mersenne Twister Algorithm ----
}

@Override
public final synchronized void setSeed(long seed) {
if (compat) {
setSeed((int)seed);
} else {

if (ibuf == null) ibuf = new int[2];

ibuf[0] = (int)seed;
ibuf[1] = (int)(seed >>> 32);
setSeed(ibuf);
}
}

public final void setSeed(byte[] buf) {
setSeed(pack(buf));
}

public final synchronized void setSeed(int[] buf) {
int length = buf.length;
if (length == 0) throw new IllegalArgumentException("Seed buffer may not be empty");
// ---- Begin Mersenne Twister Algorithm ----
int i = 1, j = 0, k = (N > length ? N : length);
setSeed(MAGIC_SEED);
for (; k > 0; k--) {
mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >>> 30)) * MAGIC_FACTOR2)) + buf[j] + j;
i++; j++;
if (i >= N) { mt[0] = mt[N-1]; i = 1; }
if (j >= length) j = 0;
}
for (k = N-1; k > 0; k--) {
mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >>> 30)) * MAGIC_FACTOR3)) - i;
i++;
if (i >= N) { mt[0] = mt[N-1]; i = 1; }
}
mt[0] = UPPER_MASK; // MSB is 1; assuring non-zero initial array
// ---- End Mersenne Twister Algorithm ----
}

@Override
protected final synchronized int next(int bits) {
// ---- Begin Mersenne Twister Algorithm ----
int y, kk;
if (mti >= N) { // generate N words at one time



for (kk = 0; kk < N-M; kk++) {
y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK);
mt[kk] = mt[kk+M] ^ (y >>> 1) ^ MAGIC[y & 0x1];
}
for (;kk < N-1; kk++) {
y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK);
mt[kk] = mt[kk+(M-N)] ^ (y >>> 1) ^ MAGIC[y & 0x1];
}
y = (mt[N-1] & UPPER_MASK) | (mt[0] & LOWER_MASK);
mt[N-1] = mt[M-1] ^ (y >>> 1) ^ MAGIC[y & 0x1];

mti = 0;
}

y = mt[mti++];

// Tempering
y ^= (y >>> 11);
y ^= (y << 7) & MAGIC_MASK1;
y ^= (y << 15) & MAGIC_MASK2;
y ^= (y >>> 18);
// ---- End Mersenne Twister Algorithm ----
return (y >>> (32-bits));
}
public static int[] pack(byte[] buf) {
int k, blen = buf.length, ilen = ((buf.length+3) >>> 2);
int[] ibuf = new int[ilen];
for (int n = 0; n < ilen; n++) {
int m = (n+1) << 2;
if (m > blen) m = blen;
for (k = buf[--m]&0xff; (m & 0x3) != 0; k = (k << 8) | buf[--m]&0xff);
ibuf[n] = k;
}
return ibuf;
}
}
после чего состовляется в виртуальной памяти список + и - так сказать к которому во время заточки обращается сервер.
Процент лишь влияет на количество в этом "списке" "минусов" а точнее говоря 0.
Какой можно сделать из этого вывод?
Просчитать "рандом" по такому алгоритму теоретичиески можно но очень трудоёмко, на практике практически невозможно да и проще узнать у администратора сервера рейты заточек.
Например если шанс 75 и макс уровень 50 то заточив 100 вещей вы гарантировано заточите 2 - 3 до 50 уровня .Но это в тепличных условиях, без учёта времени и других игроков которые тоже используют данный "список".
Надеюсь этой статьёй я развею легенды и мифы про просчёт последовательности фейк заточки и прочие танцы с бубном.

xkor
05.04.2009, 14:02
астрология нас спасет!))

alexteam
05.04.2009, 14:45
ога. период этого генератора псевдослучайных 2^219937.
танцуйте с бубном, господа.

Grinch
05.04.2009, 15:58
бубен рулит :)

Xa4ik
05.04.2009, 16:15
Уже по количеству кода видно что он медленный и в нем есть баги.

KrazyKeNNy
05.04.2009, 16:17
Лучше всего точить с бубном, стоя на стуле и прыгая на левой ноге, приговаривая:"ааалааахмааа амааахаа", характерно подмигивая сначала одним глазом потом другим с периодом 3 раза в секунду, размахивая руками.

lexachg
05.04.2009, 17:58
Лучше всего точить с бубном, стоя на стуле и прыгая на левой ноге, приговаривая:"ааалааахмааа амааахаа", характерно подмигивая сначала одним глазом потом другим с периодом 3 раза в секунду, размахивая руками.

это мой способ точения))):moil: я так уже все серва нагинаю)))

Eisbrecher
05.04.2009, 19:26
Танцы с бубном реально помогают, я заточил дарк скример на 4 !!! Юзайте.

lexachg
05.04.2009, 20:10
Танцы с бубном реально помогают, я заточил дарк скример на 4 !!! Юзайте.

+5 or nub?:p

DzumoHu4
06.04.2009, 01:49
Уже по количеству кода видно что он медленный и в нем есть баги.

Ну друг мой, если этим кодом пользуются все приложения написанные на Java (и использующие функции псевдослучайных значений) поскольку это стандартный класс, то вряд ли там найдётся хотя бы с десяток багов.
Создатель L2J просто перекрасил в другой цвет раму, велосипед изобрела Sun Microsystems:D

KrazyKeNNy
06.04.2009, 15:03
А вобще как сказал TAMBIK:

DzumoHu4
06.04.2009, 16:48
А вобще как сказал TAMBIK:
О чём ты?.
З.ы Оффтоп спасёт мир!!!:D:rofl:

Insane*
06.04.2009, 22:19
DzumoHu4, а теперь надо всех идиотов дружно загнать в эту тему=)
Благоразумие и факты спасут мир=)

lexayar
09.04.2009, 18:39
Описав функцию рандома, ты еще не обосновал того, что все зависит только от него. При заточке проверяются еще различные другие факторы и делаются определенные действия, на которых и может быть баг.
Хотя я сам в эти все читы не верю, но это все реально, и кроме функции рандом зависит от пряморукости разработчиков, которые этот самый рандом используют:)

DzumoHu4
20.04.2009, 14:33
Описав функцию рандома, ты еще не обосновал того, что все зависит только от него. При заточке проверяются еще различные другие факторы и делаются определенные действия, на которых и может быть баг.
Хотя я сам в эти все читы не верю, но это все реально, и кроме функции рандом зависит от пряморукости разработчиков, которые этот самый рандом используют:)

А от чего по твоему зависит заточка? От скорости клацанья мышки?Или от молебен и песнопений?
кстати вот интересная программка, якобы рассчитывает заточку полагаясь на шанс.
Тестируйте, автора я незнаю, нашёл случайно и за точность результатов тем более не ручаюсь.

bumctik
20.04.2009, 15:21
имхо какой то бред а не прога....
если ниче не заполнять и нажать просчитать.... то выдаст результаты )))))аффтар етой проги дичь безпонтовая, видать даже сам ее не тестировал нифига

DzumoHu4
20.04.2009, 15:24
имхо какой то бред а не прога....
если ниче не заполнять и нажать просчитать.... то выдаст результаты )))))аффтар етой проги дичь безпонтовая, видать даже сам ее не тестировал нифига

Ну перед тем как говорить нужно наверное почитать, во первых по умолчанию точит 15 вещей на +14 с шансом 40% 100 раз.
Остальное так фенечки