Dự đoán chuyển động cho người không bắn


35

Tôi đang làm việc trên một trò chơi 2D isometric với nhiều người chơi ở quy mô vừa phải, khoảng 20-30 người chơi được kết nối cùng một lúc với một máy chủ liên tục. Tôi đã gặp một số khó khăn khi triển khai dự đoán chuyển động tốt.

Vật lý / Chuyển động

Trò chơi không có triển khai vật lý thực sự, nhưng sử dụng các nguyên tắc cơ bản để thực hiện chuyển động. Thay vì liên tục bỏ phiếu đầu vào, các thay đổi trạng thái (tức là / chuột xuống / lên / di chuyển sự kiện) được sử dụng để thay đổi trạng thái của thực thể nhân vật mà người chơi đang điều khiển. Hướng của người chơi (tức là / đông bắc) được kết hợp với tốc độ không đổi và biến thành một vectơ 3D thực sự - vận tốc của thực thể.

Trong vòng lặp trò chơi chính, "Cập nhật" được gọi trước khi "Vẽ". Logic cập nhật kích hoạt "nhiệm vụ cập nhật vật lý" theo dõi tất cả các thực thể với vận tốc khác không sử dụng tích hợp rất cơ bản để thay đổi vị trí thực thể. Ví dụ: entity.Pocation + = entity.Velocity.Scale (ElapsedTime.Seconds) (trong đó "Giây" là một giá trị dấu phẩy động, nhưng cách tiếp cận tương tự sẽ hoạt động với các giá trị số nguyên mili giây).

Điểm mấu chốt là không có phép nội suy nào được sử dụng cho chuyển động - động cơ vật lý thô sơ không có khái niệm về "trạng thái trước" hay "trạng thái hiện tại", chỉ có một vị trí và vận tốc.

Gói thay đổi và cập nhật trạng thái

Khi vận tốc của thực thể nhân vật mà người chơi đang kiểm soát thay đổi, gói "di chuyển avatar" sẽ được gửi đến máy chủ chứa loại hành động của thực thể (đứng, đi, chạy), hướng (đông bắc) và vị trí hiện tại. Điều này khác với cách trò chơi 3D người đầu tiên hoạt động. Trong trò chơi 3D, vận tốc (hướng) có thể thay đổi khung hình thành khung hình khi người chơi di chuyển xung quanh. Gửi mọi thay đổi trạng thái sẽ truyền tải hiệu quả một gói trên mỗi khung, quá tốn kém. Thay vào đó, các trò chơi 3D dường như bỏ qua các thay đổi trạng thái và gửi các gói "cập nhật trạng thái" trong một khoảng thời gian cố định - giả sử, cứ sau 80-150ms.

Vì cập nhật tốc độ và hướng xảy ra ít thường xuyên hơn trong trò chơi của tôi, tôi có thể thoát khỏi việc gửi mọi thay đổi trạng thái. Mặc dù tất cả các mô phỏng vật lý xảy ra ở cùng một tốc độ và mang tính quyết định, độ trễ vẫn là một vấn đề. Vì lý do đó, tôi gửi các gói cập nhật vị trí thường xuyên (tương tự như trò chơi 3D) nhưng ít thường xuyên hơn - ngay bây giờ cứ sau 250ms, nhưng tôi nghi ngờ với dự đoán tốt tôi có thể dễ dàng tăng tốc lên 500ms. Vấn đề lớn nhất là bây giờ tôi đã đi lệch khỏi định mức - tất cả các tài liệu, hướng dẫn và mẫu trực tuyến khác đều gửi các cập nhật thường xuyên và nội suy giữa hai trạng thái. Nó dường như không tương thích với kiến ​​trúc của tôi và tôi cần đưa ra một thuật toán dự đoán chuyển động tốt hơn gần với kiến ​​trúc "vật lý mạng" (rất cơ bản).

Sau đó, máy chủ sẽ nhận gói tin và xác định tốc độ của người chơi từ loại chuyển động dựa trên tập lệnh (Người chơi có thể chạy không? Lấy tốc độ chạy của người chơi). Khi nó có tốc độ, nó kết hợp nó với hướng để có được một vectơ - vận tốc của thực thể. Một số phát hiện gian lận và xác nhận cơ bản xảy ra và thực thể ở phía máy chủ được cập nhật với vận tốc, hướng và vị trí hiện tại. Điều chỉnh cơ bản cũng được thực hiện để ngăn người chơi tràn vào máy chủ với các yêu cầu di chuyển.

Sau khi cập nhật thực thể riêng của mình, máy chủ sẽ phát gói "cập nhật vị trí avatar" cho tất cả người chơi khác trong phạm vi. Gói cập nhật vị trí được sử dụng để cập nhật các mô phỏng vật lý phía máy khách (trạng thái thế giới) của các máy khách từ xa và thực hiện dự đoán và bù độ trễ.

Dự đoán và bồi thường Lag

Như đã đề cập ở trên, khách hàng có thẩm quyền cho vị trí riêng của họ. Ngoại trừ các trường hợp gian lận hoặc dị thường, hình đại diện của khách hàng sẽ không bao giờ được máy chủ định vị lại. Không ngoại suy ("di chuyển ngay bây giờ và sửa lại sau") là bắt buộc đối với hình đại diện của khách hàng - những gì người chơi thấy chính xác. Tuy nhiên, một số loại ngoại suy hoặc nội suy là cần thiết cho tất cả các thực thể từ xa đang di chuyển. Một số loại dự đoán và / hoặc bù trễ rõ ràng là cần thiết trong công cụ mô phỏng / vật lý cục bộ của khách hàng.

Các vấn đề

Tôi đã vật lộn với các thuật toán khác nhau, và có một số câu hỏi và vấn đề:

  1. Tôi nên ngoại suy, nội suy, hoặc cả hai? "Cảm giác ruột" của tôi là tôi nên sử dụng phép ngoại suy thuần túy dựa trên vận tốc. Khách hàng nhận được sự thay đổi trạng thái, khách hàng tính toán vận tốc "dự đoán" bù cho độ trễ và hệ thống vật lý thông thường làm phần còn lại. Tuy nhiên, nó cảm thấy mâu thuẫn với tất cả các mã và bài viết mẫu khác - tất cả chúng dường như lưu trữ một số trạng thái và thực hiện phép nội suy mà không cần động cơ vật lý.

  2. Khi một gói đến, tôi đã thử nội suy vị trí của gói với vận tốc của gói trong một khoảng thời gian cố định (giả sử, 200ms). Sau đó, tôi lấy sự khác biệt giữa vị trí nội suy và vị trí "lỗi" hiện tại để tính toán một vectơ mới và đặt nó trên thực thể thay vì vận tốc được gửi. Tuy nhiên, giả định là một gói khác sẽ đến trong khoảng thời gian đó và rất khó để "đoán" khi gói tiếp theo sẽ đến - đặc biệt là vì chúng không đến vào các khoảng thời gian cố định (tức là cũng thay đổi trạng thái). Là khái niệm về cơ bản là thiếu sót, hoặc nó là chính xác nhưng cần một số sửa chữa / điều chỉnh?

  3. Điều gì xảy ra khi một người chơi từ xa dừng lại? Tôi có thể ngay lập tức dừng thực thể, nhưng nó sẽ được đặt ở vị trí "sai" cho đến khi nó di chuyển trở lại. Nếu tôi ước tính một vectơ hoặc cố gắng nội suy, tôi có một vấn đề vì tôi không lưu trữ trạng thái trước đó - công cụ vật lý không có cách nào để nói "bạn cần dừng lại sau khi bạn đạt đến vị trí X". Nó chỉ đơn giản là hiểu một vận tốc, không có gì phức tạp hơn. Tôi miễn cưỡng thêm thông tin "trạng thái chuyển động gói" vào các thực thể hoặc công cụ vật lý, vì nó vi phạm các nguyên tắc thiết kế cơ bản và làm chảy mã mạng trên phần còn lại của công cụ trò chơi.

  4. Điều gì sẽ xảy ra khi các thực thể va chạm? Có ba kịch bản - trình phát điều khiển va chạm cục bộ, hai thực thể va chạm trên máy chủ trong khi cập nhật vị trí hoặc cập nhật thực thể từ xa va chạm vào máy khách cục bộ. Trong mọi trường hợp, tôi không chắc chắn làm thế nào để xử lý vụ va chạm - ngoài việc gian lận, cả hai trạng thái đều "chính xác" nhưng ở các khoảng thời gian khác nhau. Trong trường hợp của một thực thể ở xa, sẽ không có ý nghĩa gì khi vẽ nó đi xuyên qua tường, vì vậy tôi thực hiện phát hiện va chạm trên máy khách cục bộ và khiến nó "dừng lại". Dựa trên điểm số 2 ở trên, tôi có thể tính toán một "vectơ đã sửa" liên tục cố gắng di chuyển thực thể "xuyên tường" sẽ không bao giờ thành công - hình đại diện từ xa bị kẹt ở đó cho đến khi lỗi quá cao và nó "chộp" vào Chức vụ. Làm thế nào để các trò chơi làm việc xung quanh này?


1
Trò chơi là 3D hoặc 2D có liên quan gì với loại máy chủ bạn sử dụng? và tại sao máy chủ không hoạt động sẽ làm việc cho trò chơi của bạn?
Tấn

1
@Roy T. đánh đổi băng thông. Băng thông là tài nguyên quý giá nhất trong các hệ thống máy tính ngày nay.
FxIII

1
Điều đó không đúng, các trò chơi trực tuyến chủ yếu bị chi phối bởi thời gian phản hồi, ví dụ trên dòng 10Mbit (1,25 MB / giây) độ trễ giữa máy chủ-máy khách là 20ms, gửi gói 1,25kb sẽ mất 20ms + 1ms. Gửi một gói 12,5kb sẽ mất 30ms. Trên đường truyền nhanh gấp đôi, gói 1,25kb vẫn sẽ mất 20ms + 0,5ms và 20ms + 5ms cho gói 12.kb. Độ trễ là yếu tố giới hạn, không phải băng thông. Dù sao, tôi không biết có bao nhiêu dữ liệu, nhưng gửi 50 vector3 (vị trí 25x + xoay 25x) chỉ là 600 byte, gửi 20 giây này sẽ tốn 30kb / s. (+ Chi phí gói).
Roy T.

2
Động cơ Quake có dự đoán kể từ phiên bản đầu tiên. Dự đoán trận động đất được mô tả ở đó và trên một số nơi khác. Kiểm tra nó ra.
dùng712092

1
Bạn có thực hiện vị trí này + = vận tốc * deltatime cho từng thực thể song song (bắt buộc: trong mã Bạn có 2 mảng tham số vật lý của các thực thể, cách nhau một khung, Bạn cập nhật cái cũ hơn để mới hơn và hoán đổi chúng)? Có một số vấn đề với việc lặp lại bởi Sean Barret, người đã tạo ra cơ sở của Thief 1 engine .
dùng712092

Câu trả lời:


3

Điều duy nhất để nói là 2D, isometric, 3D, tất cả đều giống nhau khi gặp vấn đề này. Bởi vì bạn thấy nhiều ví dụ về 3D và bạn chỉ đang sử dụng hệ thống đầu vào giới hạn quãng tám 2D với vận tốc tức thời không có nghĩa là bạn có thể loại bỏ các nguyên tắc mạng đã phát triển trong hơn 20 năm qua.

Nguyên tắc thiết kế bị nguyền rủa khi chơi trò chơi bị xâm phạm!

Bằng cách loại bỏ trước đây và hiện tại bạn đang loại bỏ một vài thông tin có thể giải quyết vấn đề của bạn. Với những dữ liệu đó, tôi sẽ thêm dấu thời gian và độ trễ tính toán để phép ngoại suy có thể dự đoán tốt hơn vị trí của người chơi đó và phép nội suy có thể làm giảm tốc độ thay đổi vận tốc theo thời gian tốt hơn.

Trên đây là một lý do lớn tại sao các máy chủ dường như gửi rất nhiều thông tin trạng thái và không kiểm soát đầu vào. Một lý do lớn khác là dựa trên giao thức bạn đang sử dụng. UDP với mất gói được chấp nhận và giao hàng ngoài đơn đặt hàng? TCP có đảm bảo giao hàng và thử lại không? Với bất kỳ giao thức nào, bạn sẽ nhận được các gói vào những thời điểm kỳ lạ, bị trì hoãn hoặc chồng chất lên nhau trong một loạt các hoạt động. Tất cả các gói kỳ lạ đó cần phải phù hợp với một bối cảnh để khách hàng có thể biết được chuyện gì đang xảy ra.

Cuối cùng, mặc dù đầu vào của bạn rất hạn chế ở 8 hướng, thay đổi thực tế có thể xảy ra bất cứ lúc nào - thực thi chu kỳ 250ms sẽ chỉ khiến người chơi nhanh chóng nản chí. 30 người chơi là không có gì lớn cho bất kỳ máy chủ để xử lý. Nếu bạn đang nói về hàng ngàn ... thậm chí sau đó các nhóm trong số họ được chia thành nhiều boxen để các máy chủ riêng lẻ chỉ mang tải hợp lý.

Bạn đã bao giờ cấu hình một động cơ vật lý như Havok hoặc Bullet đang chạy chưa? Chúng thực sự khá tối ưu và rất, rất nhanh. Bạn có thể rơi vào cái bẫy giả định rằng hoạt động ABC sẽ chậm và tối ưu hóa một cái gì đó không cần nó.


Lời khuyên hiền nhất định ở đây! Thật dễ dàng để mất tầm nhìn của bức tranh lớn. Tôi đang sử dụng TCP trong trường hợp này. Vấn đề "8 hướng" không phải là vấn đề liên quan đến đầu vào - đó là vấn đề với phép nội suy và ngoại suy. Đồ họa được giới hạn ở các góc đó và sử dụng các họa tiết hoạt hình - lối chơi "trông lạ" nếu người chơi di chuyển ở một góc hoặc vận tốc khác quá xa so với chuẩn mực.
ShadowChaser

1

Vì vậy, máy chủ của bạn về cơ bản là một "trọng tài"? Trong trường hợp này, tôi tin rằng mọi thứ trong khách hàng của bạn phải mang tính quyết định; bạn cần đảm bảo rằng mọi thứ trên mỗi máy khách sẽ luôn cho cùng một kết quả.

Đối với câu hỏi đầu tiên của bạn, một khi người chơi địa phương nhận được hướng của người chơi khác, ngoài việc có thể giải mã chuyển động của anh ta theo thời gian và áp dụng các va chạm, tôi không thấy bạn có thể dự đoán hướng nào mà người chơi sẽ rẽ tiếp theo, đặc biệt là trong một Môi trường 8 hướng.

Khi bạn nhận được cập nhật "vị trí thực" của mỗi người chơi (có lẽ bạn có thể thử sử dụng so le trên máy chủ), vâng, bạn sẽ cần phải nội suy vị trí và hướng của người chơi. Nếu vị trí "đoán" rất sai (tức là người chơi đã thay đổi hoàn toàn hướng ngay sau khi gói hướng cuối cùng được gửi), bạn sẽ có một khoảng cách rất lớn. Điều này có nghĩa là người chơi nhảy vị trí hoặc bạn có thể nội suy đến vị trí đoán tiếp theo . Điều này sẽ cung cấp nội suy mượt mà hơn theo thời gian.

Khi các thực thể va chạm, nếu bạn có thể tạo một hệ thống xác định, mỗi người chơi có thể mô phỏng sự va chạm cục bộ và kết quả của chúng không nên quá xa thực tế. Mỗi máy cục bộ nên mô phỏng sự va chạm cho cả hai người chơi, trong trường hợp đó đảm bảo rằng trạng thái cuối cùng sẽ không bị chặn và chấp nhận được.

Đối với phía máy chủ, máy chủ trọng tài vẫn có thể thực hiện các phép tính đơn giản để kiểm tra ví dụ về tốc độ của người chơi trong thời gian ngắn để sử dụng như một cơ chế chống gian lận đơn giản. Nếu bạn lặp lại theo dõi từng người chơi trên 1 giây, phát hiện gian lận của bạn sẽ có thể mở rộng, chỉ mất nhiều thời gian hơn để tìm ra kẻ gian lận.


Cảm ơn - nghe có vẻ khá gần với những gì tôi cần, đặc biệt là ở phía máy chủ. Một điểm thú vị là mặc dù người chơi bị khóa thành 8 hướng, chuyển động bên trong là một vectơ 3D. Tôi đã nghĩ về điều này nhiều hơn một chút trong ngày hôm qua và tôi nghĩ rằng tôi đang vật lộn với thực tế là tôi hoàn toàn không thực hiện phép nội suy - Tôi chỉ đơn giản sử dụng một tích hợp rất cơ bản, thiết lập vận tốc và cập nhật vị trí dựa trên vector mỗi bản cập nhật.
ShadowChaser

Tôi không chắc chắn làm thế nào để kết hợp điều đó với nội suy hoặc dự đoán. Tôi đã thử lấy vị trí cập nhật được gửi trong gói, tích hợp nó trong một khoảng thời gian cố định (giả sử, 200ms) và sau đó xác định vectơ (vận tốc) cần thiết để đạt đến điểm đó trong 200ms. Nói cách khác, bất kể vị trí không chính xác hiện tại của người chơi ở phía máy khách, họ vẫn sẽ đạt được "vị trí chính xác ước tính" trong 200ms. Cuối cùng, việc gửi nhân vật của tôi đi theo hướng điên rồ - tôi cho rằng vì 200ms thực sự sẽ là thời gian cho gói tiếp theo, mà tôi không thể ước tính được.
ShadowChaser

Bạn có chắc chắn trước tiên tích hợp đúng vị trí tại t đến t + 1 trước khi tích hợp vị trí sai với vị trí đoán đúng ở t + 1 không?
Jonathan Connell

Có - Tôi đã kiểm tra lại rằng tôi đang sử dụng đúng vị trí cho tích hợp ban đầu. Ban đầu đó là một lỗi, nhưng việc sửa nó vẫn không tạo ra sự cải thiện rõ rệt. Sự nghi ngờ của tôi là "+1" - nó cần phải phụ thuộc rất nhiều vào thời gian giữa các gói. Có hai vấn đề: gửi các thay đổi trạng thái bên cạnh các cập nhật thông thường (250ms) và tôi không thể dự đoán khi nào những thay đổi đó sẽ xảy ra. Ngoài ra, tôi miễn cưỡng khóa trong một khoảng thời gian cụ thể vì việc máy chủ gửi ít cập nhật hơn cho các thực thể ở xa trình phát hơn. Thời gian giữa các gói có thể thay đổi.
ShadowChaser

1
Vâng bao gồm một loại dấu thời gian cố định có lẽ không phải là một ý tưởng tốt. Mặc dù tôi lo lắng rằng sự thất thường của chuyển động 8 hướng sẽ rất khó (nếu không nói là không thể?) Để dự đoán. Mặc dù vậy, bạn có thể cố gắng sử dụng độ trễ trung bình của máy khách để dự đoán t + 1 và có ngưỡng mà bạn luôn "dịch chuyển" các người chơi khác đến vị trí mới của họ.
Jonathan Connell

0

Bạn có thể không bao gồm vận tốc trong thông điệp thay đổi trạng thái của bạn và sử dụng điều đó để dự đoán chuyển động? ví dụ: giả sử vận ​​tốc không thay đổi cho đến khi bạn nhận được thông báo cho biết nó đã thay đổi? Tôi nghĩ rằng bạn đã gửi các vị trí, vì vậy nếu một cái gì đó "vượt quá" vì điều này bạn có vị trí chính xác từ bản cập nhật tiếp theo nào. Sau đó, bạn có thể bước các vị trí trong quá trình cập nhật như bạn đã thực hiện bằng cách sử dụng vận tốc từ tin nhắn cuối cùng và ghi đè lên vị trí bất cứ khi nào nhận được tin nhắn với vị trí mới. Điều này cũng có nghĩa là nếu vị trí không thay đổi, nhưng vận tốc bạn cần gửi tin nhắn (nếu đó thậm chí là một trường hợp hợp lệ trong trò chơi của bạn), nhưng điều đó sẽ không ảnh hưởng nhiều đến việc sử dụng băng thông của bạn.

Nội suy không nên quan trọng ở đây, đó là ví dụ khi bạn biết nơi nào đó sẽ có trong tương lai, cho dù bạn có nó, phương pháp nào bạn đang sử dụng, v.v. Bạn có nhầm lẫn với phép ngoại suy không? (mà những gì tôi mô tả là một, đơn giản, cách tiếp cận)


-1

Câu hỏi đầu tiên của tôi sẽ là: Điều gì sai khi sử dụng một mô hình mà máy chủ có thẩm quyền? Tại sao môi trường là 2D hay 3D lại quan trọng? Nó sẽ làm cho việc bảo vệ gian lận của bạn dễ dàng hơn rất nhiều nếu máy chủ của bạn có thẩm quyền.

Hầu hết các mẫu tôi thấy chặt chẽ dự đoán chuyển động cặp đôi ngay vào chính các thực thể. Ví dụ: lưu trữ trạng thái trước đó cùng với trạng thái hiện tại. Tôi muốn tránh điều đó và chỉ giữ các thực thể với "trạng thái hiện tại" của chúng. Có cách nào tốt hơn để xử lý việc này?

Khi thực hiện dự đoán, cần duy trì một số trạng thái (hoặc ít nhất là deltas) trên máy khách để khi nhận được trạng thái có thẩm quyền / delta từ máy chủ, có thể so sánh với trạng thái của máy khách và bạn có thể thực hiện cần thiết đính chính. Ý tưởng là giữ càng nhiều càng tốt để xác định để giảm thiểu số lượng sửa chữa cần thiết. Nếu bạn không duy trì các trạng thái trước đó, bạn không thể biết nếu có điều gì khác xảy ra trên máy chủ.

Điều gì sẽ xảy ra khi người chơi dừng lại? Tôi không thể nội suy đến đúng vị trí, vì họ có thể cần đi lùi hoặc hướng khác nếu vị trí của họ quá xa.

Tại sao bạn cần phải nội suy? Các máy chủ có thẩm quyền nên ghi đè bất kỳ chuyển động sai lầm.

Điều gì sẽ xảy ra khi các thực thể va chạm? Nếu người chơi hiện tại va chạm với thứ gì đó, câu trả lời rất đơn giản - chỉ cần ngăn người chơi di chuyển. Nhưng điều gì xảy ra nếu hai thực thể chiếm cùng một không gian trên máy chủ? Điều gì xảy ra nếu dự đoán cục bộ khiến một thực thể từ xa va chạm với người chơi hoặc thực thể khác - tôi có ngăn chặn chúng không? Nếu dự đoán có sự bất hạnh khi dán chúng trước bức tường mà người chơi đã đi xung quanh, dự đoán sẽ không bao giờ có thể bù lại và một khi lỗi xảy ra ở mức cao, thực thể sẽ chộp lấy vị trí mới.

Đây là những tình huống sẽ xảy ra xung đột giữa máy chủ và máy khách và đó là lý do tại sao bạn cần duy trì trạng thái trên máy khách để máy chủ có thể sửa bất kỳ lỗi nào.

Xin lỗi vì câu trả lời nhanh, tôi phải đi thôi. Đọc bài viết này , nó có đề cập đến game bắn súng nhưng nên hoạt động cho bất kỳ trò chơi nào yêu cầu kết nối mạng thời gian thực.


Một vài câu trả lời: * Nếu máy chủ có thẩm quyền, nó sẽ chịu trách nhiệm theo dõi tất cả các thực thể di chuyển và cập nhật vị trí của chúng theo định kỳ. Nói cách khác, nó cần chạy động cơ vật lý - có thể tốn kém. Khả năng mở rộng là một mục tiêu thiết kế chính của tôi. * Tôi cần phải nội suy ở phía máy khách, thông minh khác mỗi lần cập nhật máy chủ được gửi cho máy khách sẽ khiến các thực thể nhảy. Ngay bây giờ phép nội suy của tôi được thực hiện trong động cơ vật lý - nó chỉ đặt vận tốc. Không có tiểu bang hoặc đồng bằng châu thổ.
ShadowChaser

Tôi đã đọc qua tất cả các bài viết của Glenn, nhưng anh ấy nói trong các nhận xét rằng chúng chỉ hướng tới các game bắn súng (tức là / tần số cập nhật cao). Một số bài viết của ông nói về các khách hàng có thẩm quyền, đó là việc thực hiện mà tôi đang phấn đấu. Tôi không muốn thực hiện bất kỳ phép nội suy / vật lý nào trên máy chủ, nhưng tôi sẵn sàng thay đổi suy nghĩ nếu đó thực sự là cách duy nhất :)
ShadowChaser

1
-1. Những gì bạn viết chỉ mơ hồ chạm vào chủ đề; cảm thấy mơ hồ. Câu trả lời cảm thấy ngang bằng khi về cơ bản chúng là "đọc bài viết dài này", trong khi không chứa thông tin hữu ích từ bài viết trong tay.
Tấn

1
@AttackingHobo Tôi phải đồng ý với bạn. Tôi đã đề cập rằng tôi đang vội nhưng đó không phải là lý do. Nếu tôi không có thời gian thì tốt hơn là để nó một mình. Bài học kinh nghiệm.
Gyan aka Gary Buyn
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.