暇つぶしにマインクラフトの自動マイニングツールの開発をしたという話

友人とマイクラをやることになったものの素材集めが面倒だったから作成を始め、実装した流れやコードについての説明をしていく
なお、パラメーター等調整中

实施策略

    • W, P キー押しっぱなしで右クリックの代わりにPを利用(モジュールの都合)

 

    • 逐次画面を取得し、グレイスケールに変換を行い輝度を取得

輝度に応じて、マグマが近くにあるのか外に出そうなのか判別

閾値を超えたら180度回転し、一定時間経過後右を向く

ESCでプログラムを終了
一定時間経過後にピッケルの位置を変更

实际代码

import time
from PIL import ImageGrab
import numpy as np
import win32gui
import cv2
import schedule
import pydirectinput as direct
import threading
import queue
import keyboard
import sys


END_MAIN = queue.Queue()
def stop_program():
	while True:
		if keyboard.is_pressed("esc"):
			print("esc")
			END_MAIN.put(1)
			break


def get_screen():
	TARGET_NAME = 'Minecraft 1.18.1'
	TARGET_NAME = "Minecraft 1.18.1 - Multiplayer (3rd-party Server)"
	try:
		handle = win32gui.FindWindow(None, TARGET_NAME)
	except :
		TARGET_NAME = 'Minecraft 1.18.1'
		handle = win32gui.FindWindow(None, TARGET_NAME)
	IS_MAGMA_SCREEN = 2550000    
	IS_NOT_MINING =   3300000
	MAGMA_WAIT_TIME = 10
	while True:
	    rect = win32gui.GetWindowRect(handle)
	    img = ImageGrab.grab(rect)
	    ocv_im = np.asarray(img)
	    ocv_im = cv2.cvtColor(ocv_im, cv2.IMREAD_GRAYSCALE)
	    img= ocv_im.astype('float')
	    img /= 255
	    sum_gray=img.sum()

	    if sum_gray > IS_NOT_MINING:
	    	END_MAIN.put(1)
	    	return

	    elif sum_gray > IS_MAGMA_SCREEN:
	    	move_behind_from_now_cursor_position()
	    	time.sleep(MAGMA_WAIT_TIME)
	    	move_right_from_now_cursor_position()
	    	time.sleep(1)



now_choose_pickaxe_position = 1
def change_pickaxe():
	schedule.every(2).minutes.do(sup_change_pickaxe)
	while True:
		time.sleep(3)
		schedule.run_pending()

def sup_change_pickaxe():
	global now_choose_pickaxe_position
	direct.press(str(now_choose_pickaxe_position))
	now_choose_pickaxe_position += 1
	if now_choose_pickaxe_position == 10:
		now_choose_pickaxe_position = 1


def push_keys():
	time.sleep(3)
	print("START PROGRAM")
	STOP_TIME = 60 * 10
	threading.Thread(target=w_key_looper, daemon=True).start()
	threading.Thread(target=click_loop, daemon=True).start()
	threading.Thread(target=circle_mining, daemon=True).start()
	direct.keyDown('w')
	while True:
		time.sleep(30)
		schedule.run_pending()
	

def w_key_looper():
	direct.keyDown('w')


def click_loop():
	direct.keyDown('p')


def move_right_from_now_cursor_position():
	direct.move(1, -525)

def circle_mining():
	count = 8
	while True:
		move_right_from_now_cursor_position()
		time.sleep(count)
		count *= 2


def move_behind_from_now_cursor_position():
	move_right_from_now_cursor_position()
	move_right_from_now_cursor_position()

def main():
	threading.Thread(target=push_keys, daemon=True).start()
	threading.Thread(target=get_screen, daemon=True).start()
	threading.Thread(target=stop_program, daemon=True).start()
	threading.Thread(target=change_pickaxe, daemon=True).start()
	while True:
		time.sleep(3)
		if END_MAIN.empty() != True:
			sys.exit()

main()

另外,根据鼠标灵敏度,可以调整适当的旋转值。根据我的游戏内感度设置,鼠标灵敏度为11时可以左右和向后旋转。