안녕하세요. JST금빛 입니다.
제가 전에 일팩코드로 올려드리고나서 에바팩에는 적용하신 분이 거의 손에 꼽을정도로 적은 것 같아서
다시 한번 에바팩에 맞게 코딩하여 올려드립니다. 아래 소스코드들은 최근에 올라온 감자를 그대로 다운받아서 작성하였습니다.
따라서, 감자가 아닌 다른 에바팩은 호환이 안될 수 있습니다.
호환이 되지 않을 경우, 암/복호화 부분을 주의깊게 살펴주시길 바라겠습니다.
먼저 아래 링크에서 자료를 다운받아주시고, 지금부터 자세하게 읽고 천천히 진행하시면 누구나 다 한번에 하실 수 있습니다.
자, 그럼 먼저 받으신 압축파일을 압축해제하시고 전에 제가 배포했던 컨넥터 소스파일중 ClientReadHandler.java 파일을 교체해줍니다.
그리고 accounts.sql 디비에서 approved 필드를 하나 생성해야한다고 말씀드렸었는데,
생성을 잘 할줄 모르시는 분들도 계실 것 같아서 제가 감자 현재 최신버전에서 디비를 수정하여 빼온 것 이니
기존 accounts 테이블을 삭제하시고 제가 올려드린 것으로 교체하시길 바랍니다.
다음은 netty 폴더에 있는 4가지 파일에 대한 내용입니다.
전에 드린 파일들은 일팩코드여서 에바팩과는 전혀 호환되지 않았었습니다.
패키지 경로는 server.netty 이며, 현재 감자 기준으로 ED.java 라는 파일이 보이실 것입니다.
그 경로에 드래그해서 넣어주시면 됩니다. 당연히 기존의 것들은 삭제해주세요.
자 그럼 지금부터 집중해서 한번에 끝내시길 바랍니다.
특히 설명 부분에서 파란색은 여러분이 검색하실 키워드 부분이고, 주황색은 붙여넣으실 부분이니 잘 구분해주세요.
그리고 주석부분에 윗줄, 또는 아랫줄 이라고 명시한 부분들도 주의하셔서 실수하지 않도록 해주시기 바랍니다.
--------------------------------------------------
build.xml <-- 컴파일 하실때 사용하는 xml 파일입니다.
<include name="commons-pool-1.6.jar" /> // 검색하셔서 아랫줄에 추가
<include name="netty-all-4.0.29.Final.jar" />
--------------------------------------------------
ServerStart.bat <-- 서버구동시 사용되는 파일이죠? 편집으로 여시고 안에 내용에서 주황색깔 부분을 추가
@java -server -Xms8G -Xmx8G -XX:SurvivorRatio=32 -XX:+UseG1GC -XX:+PrintGCDetails -cp l1jserver.jar;lib\xmlapi;lib\c3p0-0.9.1.2.jar;lib\commons-dbcp-1.4.jar;lib\commons-pool-1.6.jar;lib\mysql-connector-java-5.1.21-bin.jar;lib\javolution.jar;lib\netty-all-4.0.29.Final.jar server.Start
@pause
감자 이신 분들은 위 내용을 통째로 교체하셔도 좋습니다. 단, 메모리만 지금 8GB로 되어있으니 다시 알아서 수정해주세요.
--------------------------------------------------
accounts.sql <-- 디비 입니다.
필드명 : approved 타입 : tinyint 길이 : 1 새로생성
이해가 안되시는 분들은 첨부해드린 accounts.sql 디비로 교체
--------------------------------------------------
server.properties <-- 서버셋팅 파일이죠? Config 폴더에 있습니다.
jstconnector = true
jstconnectorport = 6000
cipher = true
sameIpCreatAccountLimit = 3
sameIpAccessAccountLimit = 3
jstconnectorport = 6000
cipher = true
sameIpCreatAccountLimit = 3
sameIpAccessAccountLimit = 3
--------------------------------------------------
이제부터 소스에 추가하실 부분입니다.
--------------------------------------------------
Config.java
public static int CLIENT_LANGUAGE; // 검색하셔서 그 부근에
public static boolean JST_CONNECTOR;
public static int JST_CONNECTOR_PORT;
public static boolean JST_CIPHER;
public static int SAME_IP_CREAT_ACCOUNT_LIMIT;
public static int SAME_IP_ACCESS_ACCOUNT_LIMIT;
CLIENT_LANGUAGE = Integer.parseInt(serverSettings.getProperty("ClientLanguage", "4")); // 이 부분을 검색하셔서 그 부근에 아랫줄에 추가
JST_ConNECTOR = Boolean.parseBoolean(serverSettings.getProperty("jstconnector", "true"));
JST_CONNECTOR_PORT = Integer.parseInt(serverSettings.getProperty("jstconnectorport", "6000"));
JST_CIPHER = Boolean.parseBoolean(serverSettings.getProperty("cipher", "true"));
SAME_IP_CREAT_ACCOUNT_LIMIT = Integer.parseInt(serverSettings.getProperty("sameIpCreatAccountLimit", "3"));
SAME_IP_ACCESS_ACCOUNT_LIMIT = Integer.parseInt(serverSettings.getProperty("sameIpAccessAccountLimit", "3"));
} else if (pName.equalsIgnoreCase("ClientLanguage")) { // 이 부분을 검색하셔서 그 부근에 주황글씨들 추가
CLIENT_LANGUAGE = Integer.parseInt(pValue);
} else if (pName.equalsIgnoreCase("jstconnector")) {
JST_ConNECTOR = Boolean.parseBoolean(pValue);
} else if (pName.equalsIgnoreCase("jstconnectorport")) {
JST_CONNECTOR_PORT = Integer.parseInt(pValue);
} else if (pName.equalsIgnoreCase("cipher")) {
JST_CIPHER = Boolean.parseBoolean(pValue);
} else if (pName.equalsIgnoreCase("sameIpCreatAccountLimit")) {
SAME_IP_CREAT_ACCOUNT_LIMIT = Integer.parseInt(pValue);
} else if (pName.equalsIgnoreCase("sameIpAccessAccountLimit")) {
SAME_IP_ACCESS_ACCOUNT_LIMIT = Integer.parseInt(pValue);
--------------------------------------------------
Account.java
// 아래 두줄을 적당한 곳에 알아서 추가
private boolean _isApproved;
public boolean isApproved() { return _isApproved; }
account._lastQuit = (rs.getTimestamp("LastQuit")); // 검색하셔서 바로 아랫줄에
account._isApproved = rs.getBoolean("approved");
account._isApproved = rs.getBoolean("approved");
// 파란색부분으로 검색해서 주황색부분만 추가 (특히 쉼표 주의해주세요.)
point_time=?,Point_time_ready=?,CharPassword=?,approved=?";
point_time=?,Point_time_ready=?,CharPassword=?,approved=?";
pstm.setString(13, null); // 검색하셔서 바로 아랫줄에
pstm.setBoolean(14, true);
pstm.setBoolean(14, true);
// 아래 메서드 통으로 추가
public static void updateApproved(final String name, boolean f) {
Connection con = null;
PreparedStatement pstm = null;
try {
con = L1DatabaseFactory.getInstance().getConnection();
String sqlstr = "UPDATE accounts SET approved=? WHERE login=?";
pstm = con.prepareStatement(sqlstr);
pstm.setBoolean(1, f);
pstm.setString(2, name);
pstm.executeUpdate();
} catch (Exception e) {
_log.log(Level.SEVERE, e.getLocalizedMessage(), e);
} finally {
SQLUtil.close(pstm);
SQLUtil.close(con);
}
}
public static void updateApproved(final String name, boolean f) {
Connection con = null;
PreparedStatement pstm = null;
try {
con = L1DatabaseFactory.getInstance().getConnection();
String sqlstr = "UPDATE accounts SET approved=? WHERE login=?";
pstm = con.prepareStatement(sqlstr);
pstm.setBoolean(1, f);
pstm.setString(2, name);
pstm.executeUpdate();
} catch (Exception e) {
_log.log(Level.SEVERE, e.getLocalizedMessage(), e);
} finally {
SQLUtil.close(pstm);
SQLUtil.close(con);
}
}
// 아래 메서드 통으로 추가
public static int creatCountByIp(String ip) {
int count = 0;
Connection con = null;
PreparedStatement pstm = null;
ResultSet rs = null;
try {
con = L1DatabaseFactory.getInstance().getConnection();
String sqlstr = "SELECT * FROM accounts WHERE ip=?";
pstm = con.prepareStatement(sqlstr);
pstm.setString(1, ip);
rs = pstm.executeQuery();
while (rs.next()) count++;
} catch (Exception e) {
_log.log(Level.SEVERE, e.getLocalizedMessage(), e);
} finally {
SQLUtil.close(rs);
SQLUtil.close(pstm);
SQLUtil.close(con);
}
return count;
}
--------------------------------------------------
Authorization.java
Account account = Account.load(accountName); // 검색해서 바로 위에 추가해주세요. 윗부분입니다.
int accountLength = accountName.getBytes().length;
int passwordLength = password.getBytes().length;
if (accountLength > 12 || passwordLength > 12 || accountLength < 6 || passwordLength < 6) {
client.close();
return;
}
int passwordLength = password.getBytes().length;
if (accountLength > 12 || passwordLength > 12 || accountLength < 6 || passwordLength < 6) {
client.close();
return;
}
if (!ip.equals("127.0.0.1")) { // 아이피당 최대 클라접속 허용 체크
int creatCount = Account.creatCountByIp(ip);
if (creatCount >= Config.SAME_IP_ACCESS_ACCOUNT_LIMIT) {
client.kick();
return;
}
}
int creatCount = Account.creatCountByIp(ip);
if (creatCount >= Config.SAME_IP_ACCESS_ACCOUNT_LIMIT) {
client.kick();
return;
}
}
L1Account account = L1Account.findByName(accountName); // 조금전 검색했던 거죠? 다시 그 바로 아랫부분 보시면
if (account == null) { // 여길 검색해서 아래 구문으로 변경해주세요.
if (!Config.JST_CONNECTOR && account == null) { // 이렇게 말이죠.
LoginController.getInstance().login(client, account); // 검색하셔서 바로 윗줄에 아래내용 추가. 윗줄입니다.
if (!account.isApproved()) { // 바로 밑에 부분에 추가
client.close();
return;
}
client.close();
return;
}
--------------------------------------------------
GameServer.java
Runtime.getRuntime().addShutdownHook(Shutdown.getInstance()); // 검색하셔서 바로 윗줄에 추가. 윗줄입니다.
AccountInspectServer.getInstance();
--------------------------------------------------
S_LoginResult.java
// 상단에 추가
public static final int REASON_LOGIN_OK_ConNECTOR = 0x01;
public static final int REASON_CREAT_ACCOUNT = 0x02;
public static final int REASON_ACCOUNT_CREAT_FAIL = 0x17;
public static final int REASON_LOGIN_OK_ConNECTOR = 0x01;
public static final int REASON_CREAT_ACCOUNT = 0x02;
public static final int REASON_ACCOUNT_CREAT_FAIL = 0x17;
--------------------------------------------------
LineageClient.java
LoginController.getInstance().logout(this); // 검색해서 바로 아랫줄에 추가
Account.updateApproved(getAccountName(), false);
if (temp.length < 4) return; // 검색하셔서 바로 아랫줄에 이렇게 수정해주세요.
if (Config.JST_CONNECTOR) {
buf1 = temp;
} else {
buf1 = le.decrypt(temp); // 이건 기존 코드
}
buf1 = temp;
} else {
buf1 = le.decrypt(temp); // 이건 기존 코드
}
--------------------------------------------------
LineagePacketEncoder
buffer = buffer(client.encryptE(bp.getBytes()), length); // 검색하셔서 이 줄을 아래처럼 변경해주세요.
if (Config.JST_CONNECTOR) {
buffer = buffer(bp.getBytes(), length);
} else {
buffer = buffer(client.encryptE(bp.getBytes()), length);
}
buffer = buffer(bp.getBytes(), length);
} else {
buffer = buffer(client.encryptE(bp.getBytes()), length);
}
여기까지 따라오시느라 고생 많으셨습니다.
워낙 급하게 짜느라 빠뜨린 부분이 있을 수도 있습니다.
만약 정상작동이 안된다면 네이트온으로 대화 주시길 바랍니다.
눈치가 빠르신 분들은 아시겠지만, 접속기의 자체 암/복호화 처리를 아예 On으로 해둔 상태입니다.
패킷 스니핑에 의한 계정 해킹의 위험이 있긴 하지만, 불안하신 분들은 계정정보 전송 부분에만
암호화를 하시면 될 것 같습니다. 물론 받을때도 별도 복호화가 필요하겠죠.
아무튼 많이 기다리셨을 텐데 너무 많이 기다리게 해드려 죄송합니다.
이 컨넥터는 아직 완벽하지 않기때문에 보안해야할 점이 분명히 있습니다.
혹여 사용하시다가 큰 문제점을 발견하면 저희에게 연락주시기 바랍니다.
앞으로도 게임서버와는 별개인 채팅방, 공지게시판 등을 추가로 Add on 해드릴 계획이며,
모든 소스는 무료로 배포할 예정입니다.
최근에 수많은 분들이 정말 감사하게도 의뢰를 많이 주셔서 사실 지금 거의 포화상태입니다.
시간이 되는대로 최대한 빠른 업데이트를 해드리겠습니다.
본 컨넥터는 그 어떠한 빈 파일과도 호환이되며, 버전이 오래된 빈 파일의 경우 날짜변경모드를 true로 바꿔주시길 바랍니다.
앞으로도 많은 관심과 성원 부탁드리겠습니다.
감사합니다.
-JST 일동-
저기머시냐 궁금한게 잇는데 네이트주소가 없내여? 주소좀 알려주새요
답글삭제